This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: JNI cleanup + separate global refs


I'm checking this in on the trunk.  This cleans up a FIXME in the JNI
implementation.  It also adds a separate hash table for global
references.  While (probably) not strictly necessary, I think this
makes it a little easier to find bugs in JNI code.

2001-06-15  Tom Tromey  <tromey@redhat.com>

	* jni.cc (ClassClass): Removed; updated all users.
	(ObjectClass): Likewise.
	(ThrowableClass): Likewise.
	(MethodClass): Likewise.
	(ThreadGroupClass): Likewise.
	(local_ref_table): Renamed from `ref_table'.
	(global_ref_table): New global.
	(_Jv_JNI_Init): Initialize both ref tables.
	(mark_for_gc): Added `ref_table' parameter.
	(unmark_for_gc): Likewise.  Also, fail if we unreferenced too many
	times.
	(_Jv_JNI_NewGlobalRef): Updated for new mark function.
	(_Jv_JNI_DeleteGlobalRef): Likewise.
	(_Jv_JNI_DeleteLocalRef): Likewise.
	(_Jv_JNI_NewLocalRef): Likewise.
	(_Jv_JNI_PopLocalFrame): Likewise.
	(_Jv_JNI_GetStringChars): Likewise.
	(_Jv_JNI_ReleaseStringChars): Likewise.
	(_Jv_JNI_GetPrimitiveArrayElements): Likewise.
	(_Jv_JNI_ReleasePrimitiveArrayElements): Likewise.

Tom

Index: jni.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni.cc,v
retrieving revision 1.45
diff -u -r1.45 jni.cc
--- jni.cc	2001/05/22 06:47:48	1.45
+++ jni.cc	2001/06/15 22:02:02
@@ -48,13 +48,6 @@
 #include <java-interp.h>
 #include <java-threads.h>
 
-// FIXME: remove these defines.
-#define ClassClass java::lang::Class::class$
-#define ObjectClass java::lang::Object::class$
-#define ThrowableClass java::lang::Throwable::class$
-#define MethodClass java::lang::reflect::Method::class$
-#define ThreadGroupClass java::lang::ThreadGroup::class$
-
 // This enum is used to select different template instantiations in
 // the invocation code.
 enum invocation_type
@@ -97,8 +90,10 @@
   jobject vec[0];
 };
 
-// This holds a reference count for all local and global references.
-static java::util::Hashtable *ref_table;
+// This holds a reference count for all local references.
+static java::util::Hashtable *local_ref_table;
+// This holds a reference count for all global references.
+static java::util::Hashtable *global_ref_table;
 
 // The only VM.
 static JavaVM *the_vm;
@@ -153,8 +148,9 @@
 void
 _Jv_JNI_Init (void)
 {
-  ref_table = new java::util::Hashtable;
-  
+  local_ref_table = new java::util::Hashtable;
+  global_ref_table = new java::util::Hashtable;
+
 #ifdef ENABLE_JVMPI
   _Jv_JVMPI_Interface.version = 1;
   _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
@@ -167,7 +163,7 @@
 
 // Tell the GC that a certain pointer is live.
 static void
-mark_for_gc (jobject obj)
+mark_for_gc (jobject obj, java::util::Hashtable *ref_table)
 {
   JvSynchronize sync (ref_table);
 
@@ -180,7 +176,7 @@
 
 // Unmark a pointer.
 static void
-unmark_for_gc (jobject obj)
+unmark_for_gc (jobject obj, java::util::Hashtable *ref_table)
 {
   JvSynchronize sync (ref_table);
 
@@ -188,6 +184,7 @@
   Integer *refcount = (Integer *) ref_table->get (obj);
   JvAssert (refcount);
   jint val = refcount->intValue () - 1;
+  JvAssert (val >= 0);
   if (val == 0)
     ref_table->remove (obj);
   else
@@ -200,14 +197,14 @@
 static jobject
 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
 {
-  mark_for_gc (obj);
+  mark_for_gc (obj, global_ref_table);
   return obj;
 }
 
 static void
 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
 {
-  unmark_for_gc (obj);
+  unmark_for_gc (obj, global_ref_table);
 }
 
 static void
@@ -222,7 +219,7 @@
 	  if (frame->vec[i] == obj)
 	    {
 	      frame->vec[i] = NULL;
-	      unmark_for_gc (obj);
+	      unmark_for_gc (obj, local_ref_table);
 	      return;
 	    }
 	}
@@ -302,7 +299,7 @@
       env->locals->vec[0] = obj;
     }
 
-  mark_for_gc (obj);
+  mark_for_gc (obj, local_ref_table);
   return obj;
 }
 
@@ -316,7 +313,7 @@
     {  
       for (int i = 0; i < rf->size; ++i)
 	if (rf->vec[i] != NULL)
-	  unmark_for_gc (rf->vec[i]);
+	  unmark_for_gc (rf->vec[i], local_ref_table);
 
       // If the frame we just freed is the marker frame, we are done.
       done = (rf->marker == stop);
@@ -467,7 +464,7 @@
 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
 {
   // We check in case the user did some funky cast.
-  JvAssert (obj != NULL && (&ThrowableClass)->isInstance (obj));
+  JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
   env->ex = obj;
   return 0;
 }
@@ -477,13 +474,14 @@
 {
   using namespace java::lang::reflect;
 
-  JvAssert ((&ThrowableClass)->isAssignableFrom (clazz));
+  JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
 
   int r = JNI_OK;
   try
     {
       JArray<jclass> *argtypes
-	= (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
+	= (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
+					       NULL);
 
       jclass *elts = elements (argtypes);
       elts[0] = &StringClass;
@@ -922,7 +920,7 @@
 			   jmethodID id, va_list args)
 {
   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
-  JvAssert ((&ClassClass)->isInstance (klass));
+  JvAssert (java::lang::Class::class$.isInstance (klass));
 
   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
 }
@@ -937,7 +935,7 @@
   T result;
 
   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
-  JvAssert ((&ClassClass)->isInstance (klass));
+  JvAssert (java::lang::Class::class$.isInstance (klass));
 
   va_start (args, id);
   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
@@ -955,7 +953,7 @@
 			   jvalue *args)
 {
   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
-  JvAssert ((&ClassClass)->isInstance (klass));
+  JvAssert (java::lang::Class::class$.isInstance (klass));
 
   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
 }
@@ -1155,7 +1153,7 @@
 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
 {
   jchar *result = _Jv_GetStringChars (string);
-  mark_for_gc (string);
+  mark_for_gc (string, global_ref_table);
   if (isCopy)
     *isCopy = false;
   return (const jchar *) result;
@@ -1164,7 +1162,7 @@
 static void
 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
 {
-  unmark_for_gc (string);
+  unmark_for_gc (string, global_ref_table);
 }
 
 static jstring
@@ -1343,7 +1341,7 @@
       // We elect never to copy.
       *isCopy = false;
     }
-  mark_for_gc (array);
+  mark_for_gc (array, global_ref_table);
   return elts;
 }
 
@@ -1355,7 +1353,7 @@
   // Note that we ignore MODE.  We can do this because we never copy
   // the array elements.  My reading of the JNI documentation is that
   // this is an option for the implementor.
-  unmark_for_gc (array);
+  unmark_for_gc (array, global_ref_table);
 }
 
 template<typename T>
@@ -1532,7 +1530,7 @@
 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
 {
   using namespace java::lang::reflect;
-  if ((&MethodClass)->isInstance (method))
+  if (Method::class$.isInstance (method))
     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
   return
     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
@@ -1831,7 +1829,7 @@
 	  && attach->version != JNI_VERSION_1_1)
 	return JNI_EVERSION;
 
-      JvAssert ((&ThreadGroupClass)->isInstance (attach->group));
+      JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
       group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
     }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]