3333 return; \
3434 }
3535
36+ static jclass java_lang_OutOfMemoryError ;
37+ static jclass com_uber_h3core_exceptions_H3Exception ;
38+
39+ static jmethodID com_uber_h3core_exceptions_H3Exception_init ;
40+ static jmethodID java_lang_OutOfMemoryError_init ;
41+
42+ jint JNI_OnLoad (JavaVM * vm , void * reserved ) {
43+ JNIEnv * env ;
44+ if ((* * vm ).GetEnv (vm , (void * * )& env , JNI_VERSION_1_6 ) != JNI_OK ) {
45+ return JNI_ERR ;
46+ } else {
47+ jclass local_h3eClass =
48+ (* * env ).FindClass (env , "com/uber/h3core/exceptions/H3Exception" );
49+ com_uber_h3core_exceptions_H3Exception_init =
50+ (* * env ).GetMethodID (env , local_h3eClass , "<init>" , "(I)V" );
51+ com_uber_h3core_exceptions_H3Exception =
52+ (jclass )(* * env ).NewGlobalRef (env , local_h3eClass );
53+
54+ jclass local_oomeClass =
55+ (* * env ).FindClass (env , "java/lang/OutOfMemoryError" );
56+ java_lang_OutOfMemoryError_init =
57+ (* * env ).GetMethodID (env , local_oomeClass , "<init>" , "()V" );
58+ java_lang_OutOfMemoryError =
59+ (jclass )(* * env ).NewGlobalRef (env , local_oomeClass );
60+
61+ return JNI_VERSION_1_6 ;
62+ }
63+ }
64+
65+ void JNI_OnUnload (JavaVM * vm , void * reserved ) {
66+ JNIEnv * env ;
67+ if ((* * vm ).GetEnv (vm , (void * * )& env , JNI_VERSION_1_6 ) != JNI_OK ) {
68+ // Something is wrong but nothing we can do about this :(
69+ return ;
70+ } else {
71+ // delete global references so the GC can collect them
72+ if (com_uber_h3core_exceptions_H3Exception != NULL ) {
73+ (* * env ).DeleteGlobalRef (env ,
74+ com_uber_h3core_exceptions_H3Exception );
75+ }
76+ if (java_lang_OutOfMemoryError != NULL ) {
77+ (* * env ).DeleteGlobalRef (env , java_lang_OutOfMemoryError );
78+ }
79+ }
80+ }
81+
3682/**
3783 * Triggers an H3Exception
3884 */
3985void ThrowH3Exception (JNIEnv * env , H3Error err ) {
40- jclass h3e =
41- (* * env ).FindClass (env , "com/uber/h3core/exceptions/H3Exception" );
42-
43- if (h3e != NULL ) {
44- jmethodID h3eConstructor =
45- (* * env ).GetMethodID (env , h3e , "<init>" , "(I)V" );
46-
47- if (h3eConstructor != NULL ) {
48- jthrowable h3eInstance =
49- (jthrowable )((* * env ).NewObject (env , h3e , h3eConstructor , err ));
86+ jthrowable h3eInstance = (jthrowable )((* * env ).NewObject (
87+ env , com_uber_h3core_exceptions_H3Exception ,
88+ com_uber_h3core_exceptions_H3Exception_init , err ));
5089
51- if (h3eInstance != NULL ) {
52- // TODO: Is ExceptionClear needed here?
53- (* * env ).Throw (env , h3eInstance );
54- }
55- }
90+ if (h3eInstance != NULL ) {
91+ (* * env ).Throw (env , h3eInstance );
92+ (* * env ).DeleteLocalRef (env , h3eInstance );
5693 }
5794}
5895
@@ -65,21 +102,13 @@ void ThrowH3Exception(JNIEnv *env, H3Error err) {
65102void ThrowOutOfMemoryError (JNIEnv * env ) {
66103 // Alternately, we could call the JNI function FatalError(JNIEnv *env, const
67104 // char *msg)
68- jclass oome = (* * env ).FindClass (env , "java/lang/OutOfMemoryError" );
69-
70- if (oome != NULL ) {
71- jmethodID oomeConstructor =
72- (* * env ).GetMethodID (env , oome , "<init>" , "()V" );
73-
74- if (oomeConstructor != NULL ) {
75- jthrowable oomeInstance =
76- (jthrowable )((* * env ).NewObject (env , oome , oomeConstructor ));
105+ jthrowable oomeInstance = (jthrowable )((* * env ).NewObject (
106+ env , java_lang_OutOfMemoryError , java_lang_OutOfMemoryError_init ));
77107
78- if (oomeInstance != NULL ) {
79- (* * env ).ExceptionClear (env );
80- (* * env ).Throw (env , oomeInstance );
81- }
82- }
108+ if (oomeInstance != NULL ) {
109+ (* * env ).ExceptionClear (env );
110+ (* * env ).Throw (env , oomeInstance );
111+ (* * env ).DeleteLocalRef (env , oomeInstance );
83112 }
84113}
85114
@@ -96,43 +125,50 @@ H3Error CreateGeoPolygon(JNIEnv *env, jdoubleArray verts, jintArray holeSizes,
96125 if (polygon -> geoloop .verts != NULL ) {
97126 polygon -> numHoles = (* * env ).GetArrayLength (env , holeSizes );
98127
99- polygon -> holes = calloc (sizeof (GeoPolygon ), polygon -> numHoles );
100- if (polygon -> holes == NULL ) {
101- ThrowOutOfMemoryError (env );
102- return E_MEMORY_ALLOC ;
103- }
128+ if (polygon -> numHoles > 0 ) {
129+ polygon -> holes = calloc (polygon -> numHoles , sizeof (GeoPolygon ));
130+ if (polygon -> holes == NULL ) {
131+ (* * env ).ReleaseDoubleArrayElements (
132+ env , verts , polygon -> geoloop .verts , JNI_ABORT );
133+ ThrowOutOfMemoryError (env );
134+ return E_MEMORY_ALLOC ;
135+ }
104136
105- jint * holeSizesElements =
106- (* * env ).GetIntArrayElements (env , holeSizes , 0 );
107- if (holeSizesElements == NULL ) {
108- free (polygon -> holes );
109- ThrowOutOfMemoryError (env );
110- return E_MEMORY_ALLOC ;
111- }
137+ jint * holeSizesElements =
138+ (* * env ).GetIntArrayElements (env , holeSizes , 0 );
139+ if (holeSizesElements == NULL ) {
140+ (* * env ).ReleaseDoubleArrayElements (
141+ env , verts , polygon -> geoloop .verts , JNI_ABORT );
142+ free (polygon -> holes );
143+ ThrowOutOfMemoryError (env );
144+ return E_MEMORY_ALLOC ;
145+ }
112146
113- jdouble * holeVertsElements =
114- (* * env ).GetDoubleArrayElements (env , holeVerts , 0 );
115- if (holeVertsElements == NULL ) {
116- free (polygon -> holes );
117- (* * env ).ReleaseIntArrayElements (env , holeSizes , holeSizesElements ,
118- 0 );
119- ThrowOutOfMemoryError (env );
120- return E_MEMORY_ALLOC ;
121- }
147+ jdouble * holeVertsElements =
148+ (* * env ).GetDoubleArrayElements (env , holeVerts , 0 );
149+ if (holeVertsElements == NULL ) {
150+ (* * env ).ReleaseDoubleArrayElements (
151+ env , verts , polygon -> geoloop .verts , JNI_ABORT );
152+ free (polygon -> holes );
153+ (* * env ).ReleaseIntArrayElements (env , holeSizes ,
154+ holeSizesElements , JNI_ABORT );
155+ ThrowOutOfMemoryError (env );
156+ return E_MEMORY_ALLOC ;
157+ }
122158
123- size_t offset = 0 ;
124- for (int i = 0 ; i < polygon -> numHoles ; i ++ ) {
125- // This is the number of doubles, so convert to number of verts
126- polygon -> holes [i ].numVerts = holeSizesElements [i ] / 2 ;
127- polygon -> holes [i ].verts = holeVertsElements + offset ;
128- offset += holeSizesElements [i ];
159+ size_t offset = 0 ;
160+ for (int i = 0 ; i < polygon -> numHoles ; i ++ ) {
161+ // This is the number of doubles, so convert to number of verts
162+ polygon -> holes [i ].numVerts = holeSizesElements [i ] / 2 ;
163+ polygon -> holes [i ].verts = holeVertsElements + offset ;
164+ offset += holeSizesElements [i ];
165+ }
166+ (* * env ).ReleaseIntArrayElements (env , holeSizes , holeSizesElements ,
167+ JNI_ABORT );
168+ // holeVertsElements is not released here because it is still being
169+ // pointed to by polygon->holes[*].verts. It will be released in
170+ // DestroyGeoPolygon.
129171 }
130-
131- (* * env ).ReleaseIntArrayElements (env , holeSizes , holeSizesElements , 0 );
132- // holeVertsElements is not released here because it is still being
133- // pointed to by polygon->holes[*].verts. It will be released in
134- // DestroyGeoPolygon.
135-
136172 return E_SUCCESS ;
137173 } else {
138174 ThrowOutOfMemoryError (env );
@@ -143,15 +179,16 @@ H3Error CreateGeoPolygon(JNIEnv *env, jdoubleArray verts, jintArray holeSizes,
143179void DestroyGeoPolygon (JNIEnv * env , jdoubleArray verts ,
144180 jintArray holeSizesElements , jdoubleArray holeVerts ,
145181 GeoPolygon * polygon ) {
146- (* * env ).ReleaseDoubleArrayElements (env , verts , polygon -> geoloop .verts , 0 );
182+ (* * env ).ReleaseDoubleArrayElements (env , verts , polygon -> geoloop .verts ,
183+ JNI_ABORT );
147184
148185 if (polygon -> numHoles > 0 ) {
149186 // The hole verts were pinned only once, so we don't need to iterate.
150187 (* * env ).ReleaseDoubleArrayElements (env , holeVerts ,
151- polygon -> holes [0 ].verts , 0 );
152- }
188+ polygon -> holes [0 ].verts , JNI_ABORT );
153189
154- free (polygon -> holes );
190+ free (polygon -> holes );
191+ }
155192}
156193
157194/*
@@ -584,7 +621,6 @@ JNIEXPORT void JNICALL Java_com_uber_h3core_NativeMethods_polygonToCells(
584621 (* * env ).ReleaseLongArrayElements (env , results , resultsElements , 0 );
585622 } else {
586623 ThrowOutOfMemoryError (env );
587- return ;
588624 }
589625
590626 DestroyGeoPolygon (env , verts , holeSizes , holeVerts , & polygon );
0 commit comments