This is the mail archive of the java-patches@sourceware.cygnus.com 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: RegisterNatives & associated bugs


I'm checking in this patch.  It implements the RegisterNatives JNI
call, and fixes some associated bugs.

2000-02-18  Tom Tromey  <tromey@cygnus.com>

	* include/jvm.h (_Jv_GetJavaVM): Declare.
	* include/java-interp.h (_Jv_GetFirstMethod): New function.
	(_Jv_MethodBase::get_method): New method.
	(_Jv_JNIMethod::set_function): New method.
	* jni.cc (_Jv_JNI_UnregisterNatives): New function.
	(_Jv_JNI_RegisterNatives): New function.
	(_Jv_JNIFunctions): Updated for new functions.
	(_Jv_GetJavaVM): New function.
	(_Jv_JNI_GetJavaVM): Use it.  Now static.
	(_Jv_JNI_AttachCurrentThread): Create a new JNIEnv if this thread
	is already a Java thread but does not have a JNIEnv yet.

	* java/lang/natRuntime.cc (_load): Pass the JavaVM to the onload
	function.

Tom

Index: jni.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/jni.cc,v
retrieving revision 1.20
diff -u -r1.20 jni.cc
--- jni.cc	2000/02/17 00:54:34	1.20
+++ jni.cc	2000/02/18 21:19:12
@@ -1258,6 +1258,63 @@
     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
 }
 
+static jint
+_Jv_JNI_RegisterNatives (JNIEnv *env, jclass k,
+			 const JNINativeMethod *methods,
+			 jint nMethods)
+{
+  // For now, this only matters for interpreted methods.  FIXME.
+  if (! _Jv_IsInterpretedClass (k))
+    {
+      // FIXME: throw exception.
+      return JNI_ERR;
+    }
+  _Jv_InterpClass *klass = reinterpret_cast<_Jv_InterpClass *> (k);
+
+  // Look at each descriptor given us, and find the corresponding
+  // method in the class.
+  for (int j = 0; j < nMethods; ++j)
+    {
+      bool found = false;
+
+      _Jv_MethodBase **imeths = _Jv_GetFirstMethod (klass);
+      for (int i = 0; i < JvNumMethods (klass); ++i)
+	{
+	  _Jv_MethodBase *meth = imeths[i];
+	  _Jv_Method *self = meth->get_method ();
+
+	  if (! strcmp (self->name->data, methods[j].name)
+	      && ! strcmp (self->signature->data, methods[j].signature))
+	    {
+	      if (! (self->accflags
+		     & java::lang::reflect::Modifier::NATIVE))
+		break;
+
+	      // Found a match that is native.
+	      _Jv_JNIMethod *jmeth = reinterpret_cast<_Jv_JNIMethod *> (meth);
+	      jmeth->set_function (methods[i].fnPtr);
+	      found = true;
+	      break;
+	    }
+	}
+
+      if (! found)
+	{
+	  jstring m = JvNewStringUTF (methods[j].name);
+	  _Jv_JNI_Throw (env, new java::lang::NoSuchMethodError (m));
+	  return JNI_ERR;
+	}
+    }
+
+  return JNI_OK;
+}
+
+static jint
+_Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
+{
+  return JNI_ERR;
+}
+
 
 
 #ifdef INTERPRETER
@@ -1460,7 +1517,7 @@
     }
 
   // Attaching an already-attached thread is a no-op.
-  if (_Jv_ThreadCurrent () != NULL)
+  if (_Jv_GetCurrentJNIEnv () != NULL)
     return 0;
 
   JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
@@ -1480,8 +1537,13 @@
     }
   *penv = reinterpret_cast<void *> (env);
 
-  java::lang::Thread *t = new gnu::gcj::jni::NativeThread (group, name);
-  t = t;			// Avoid compiler warning.  Eww.
+  // This thread might already be a Java thread -- this function might
+  // have been called simply to set the new JNIEnv.
+  if (_Jv_ThreadCurrent () == NULL)
+    {
+      java::lang::Thread *t = new gnu::gcj::jni::NativeThread (group, name);
+      t = t;			// Avoid compiler warning.  Eww.
+    }
   _Jv_SetCurrentJNIEnv (env);
 
   return 0;
@@ -1655,21 +1717,34 @@
   return 0;
 }
 
-jint
-_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
+JavaVM *
+_Jv_GetJavaVM ()
 {
   // FIXME: synchronize
   if (! the_vm)
     {
       JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
-      if (nvm == NULL)
-	return JNI_ERR;
-      nvm->functions = &_Jv_JNI_InvokeFunctions;
+      if (nvm != NULL)
+	nvm->functions = &_Jv_JNI_InvokeFunctions;
       the_vm = nvm;
     }
 
-  *vm = the_vm;
-  return 0;
+  // If this is a Java thread, we want to make sure it has an
+  // associated JNIEnv.
+  if (_Jv_ThreadCurrent () != NULL)
+    {
+      void *ignore;
+      _Jv_JNI_AttachCurrentThread (the_vm, &ignore, NULL);
+    }
+
+  return the_vm;
+}
+
+static jint
+_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
+{
+  *vm = _Jv_GetJavaVM ();
+  return *vm == NULL ? JNI_ERR : JNI_OK;
 }
 
 
@@ -1904,8 +1979,8 @@
   _Jv_JNI_SetPrimitiveArrayRegion,
   _Jv_JNI_SetPrimitiveArrayRegion,
   _Jv_JNI_SetPrimitiveArrayRegion,
-  NOT_IMPL /* RegisterNatives */,
-  NOT_IMPL /* UnregisterNatives */,
+  _Jv_JNI_RegisterNatives,
+  _Jv_JNI_UnregisterNatives,
   _Jv_JNI_MonitorEnter,
   _Jv_JNI_MonitorExit,
   _Jv_JNI_GetJavaVM,
Index: java/lang/natRuntime.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natRuntime.cc,v
retrieving revision 1.10
diff -u -r1.10 natRuntime.cc
--- natRuntime.cc	2000/02/15 08:51:04	1.10
+++ natRuntime.cc	2000/02/18 21:19:17
@@ -135,8 +135,13 @@
   void *onload = lt_dlsym (h, "JNI_OnLoad");
   if (onload != NULL)
     {
-      // FIXME: need invocation API to get JavaVM.
-      jint vers = ((jint (*) (...)) onload) (NULL, NULL);
+      JavaVM *vm = _Jv_GetJavaVM ();
+      if (vm == NULL)
+	{
+	  // FIXME: what?
+	  return;
+	}
+      jint vers = ((jint (*) (JavaVM *, void *)) onload) (vm, NULL);
       if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2)
 	{
 	  // FIXME: unload the library.
Index: include/java-interp.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/java-interp.h,v
retrieving revision 1.8
diff -u -r1.8 java-interp.h
--- java-interp.h	2000/02/16 00:07:34	1.8
+++ java-interp.h	2000/02/18 21:19:17
@@ -79,6 +79,12 @@
 
   // Size of raw arguments.
   _Jv_ushort args_raw_size;
+
+public:
+  _Jv_Method *get_method ()
+  {
+    return self;
+  }
 };
 
 class _Jv_InterpMethod : public _Jv_MethodBase
@@ -156,8 +162,16 @@
   friend void  _Jv_PrepareClass(jclass);
   friend void  _Jv_InitField (jobject, jclass, int);
   friend void* _Jv_MarkObj (void *, void *, void *, void *);
+
+  friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
 };
 
+extern inline _Jv_MethodBase **
+_Jv_GetFirstMethod (_Jv_InterpClass *klass)
+{
+  return klass->interpreted_methods;
+}
+
 struct _Jv_ResolvedMethod {
   jint            stack_item_count;	
   jint            vtable_index;	
@@ -190,6 +204,13 @@
 
   friend class _Jv_ClassReader;
   friend void _Jv_PrepareClass(jclass);
+
+public:
+  // FIXME: this is ugly.
+  void set_function (void *f)
+  {
+    function = f;
+  }
 };
 
 #endif /* INTERPRETER */
Index: include/jvm.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/jvm.h,v
retrieving revision 1.16
diff -u -r1.16 jvm.h
--- jvm.h	2000/02/10 20:31:48	1.16
+++ jvm.h	2000/02/18 21:19:17
@@ -211,4 +211,7 @@
 _Jv_JNIEnv *_Jv_GetCurrentJNIEnv ();
 void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
 
+struct _Jv_JavaVM;
+_Jv_JavaVM *_Jv_GetJavaVM ();
+
 #endif /* __JAVA_JVM_H__ */

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