This is a better attempt at fixing the JCL_NewRawDataObject and
JCL_GetRawData, which initializes the cached class, method, and field
variables in JNI_OnLoad.

This is potentially problematic, I suppose, because the jcl.lo object is
linked directly to a number of Classpath's JNI libraries, which I
suppose would mean that any such library couldn't have its own
JNI_OnLoad. None of them do now, however (this sounds like it may be
wrong, anyway: the JNI invocation interface docs seem to indicate that
you need to have this function in your JNI library, which returns the
JNI version you want to use, because otherwise the VM will assume you
will be using the 1.1 interface; IOW we're using it wrong if we use JNI
functions beyond 1.1. This sounds silly, though, and it works regardless).

Comments on whether or not this will work are appreciated.

2006-09-09  Casey Marshall  <[EMAIL PROTECTED]>

        * native/jni/classpath/jcl.c (JNI_OnLoad): new function.
        (JCL_NewRawDataObject): use pre-initialized Pointer variables.
        (JCL_GetRawData): likewise.

Thanks.
? native/jni/classpath/jcl_nstate.c
? native/jni/classpath/jcl_pointer.c
? native/jni/classpath/jcl_pointer.h
Index: native/jni/classpath/jcl.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/classpath/jcl.c,v
retrieving revision 1.23
diff -u -r1.23 jcl.c
--- native/jni/classpath/jcl.c  3 Apr 2006 14:03:12 -0000       1.23
+++ native/jni/classpath/jcl.c  10 Sep 2006 03:46:35 -0000
@@ -48,6 +48,63 @@
   #endif
 #endif
 
+/*
+ * Cached Pointer class info.
+ */
+static jclass rawDataClass;
+static jfieldID rawData_fid;
+static jmethodID rawData_mid;
+
+/*
+ * JNI OnLoad constructor.
+ */
+jint
+JNI_OnLoad (JavaVM *vm, void *reserved)
+{
+  JNIEnv *env;
+
+  if ((*vm)->GetEnv (vm, &env, JNI_VERSION_1_4) != JNI_OK)
+    {
+      return JNI_VERSION_1_4;
+    }
+#if SIZEOF_VOID_P == 8
+  rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
+  if (rawDataClass != NULL)
+    {
+      jclass tmp = rawDataClass;
+      rawDataClass = (*env)->NewGlobalRef (env, rawDataClass);
+      (*env)->DeleteGlobalRef (env, tmp);
+    }
+
+  if (rawDataClass != NULL)
+    {
+      rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "J");
+      rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(J)V");
+    }
+#else
+#if SIZEOF_VOID_P == 4
+  rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer32");
+  if (rawDataClass != NULL)
+    {
+      jclass tmp = rawDataClass;
+      rawDataClass = (*env)->NewGlobalRef (env, rawDataClass);
+      (*env)->DeleteGlobalRef (env, tmp);
+    }
+
+  if (rawDataClass != NULL)
+    {
+      rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "I");
+      rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(I)V");
+    }
+#else
+#error "Pointer size is not supported."
+#endif /* SIZEOF_VOID_P == 4 */
+#endif /* SIZEOF_VOID_P == 8 */
+
+  return JNI_VERSION_1_4;
+}
+
+
 JNIEXPORT void JNICALL
 JCL_ThrowException (JNIEnv * env, const char *className, const char *errMsg)
 {
@@ -183,78 +240,17 @@
 
 
 /*
- * Build a Pointer object. The function caches the class type 
+ * Build a Pointer object.
  */
 
-static jclass rawDataClass;
-static jfieldID rawData_fid;
-static jmethodID rawData_mid;
-
 JNIEXPORT jobject JNICALL
 JCL_NewRawDataObject (JNIEnv * env, void *data)
 {
-  if (rawDataClass == NULL)
+  if (rawDataClass == NULL || rawData_mid == NULL)
     {
-      jclass tmp;
-#if SIZEOF_VOID_P == 8
-      rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
-      if (rawDataClass == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal class");
-         return NULL;
-       }
-
-      rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(J)V");
-      if (rawData_mid == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal constructor");
-         return NULL;
-       }
-
-      rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "J");
-      if (rawData_fid == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal field");
-         return NULL;
-       }
-#else
-      rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer32");
-      if (rawDataClass == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal class");
-         return NULL;
-       }
-
-      rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(I)V");
-      if (rawData_mid == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal constructor");
-         return NULL;
-       }
-
-      rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "I");
-      if (rawData_fid == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to find internal field");
-         return NULL;
-       }
-
-#endif
-      tmp = (*env)->NewGlobalRef (env, rawDataClass);
-      if (tmp == NULL)
-       {
-         JCL_ThrowException (env, "java/lang/InternalError",
-                             "unable to create an internal global ref");
-         return NULL;
-       }
-      (*env)->DeleteLocalRef(env, rawDataClass);
-      rawDataClass = tmp;
+      JCL_ThrowException (env, "java/lang/InternalError",
+                          "Pointer class was not properly initialized");
+      return NULL;
     }
 
 #if SIZEOF_VOID_P == 8
@@ -267,6 +263,13 @@
 JNIEXPORT void * JNICALL
 JCL_GetRawData (JNIEnv * env, jobject rawdata)
 {
+  if (rawData_fid == NULL)
+    {
+      JCL_ThrowException (env, "java/lang/InternalError",
+                          "Pointer class was not properly initialized");
+      return NULL;
+    }
+
 #if SIZEOF_VOID_P == 8
   return (void *) (*env)->GetLongField (env, rawdata, rawData_fid);
 #else

Reply via email to