OSDN Git Service

* testsuite/libjava.jni/register2.java: New file.
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Oct 2006 23:17:04 +0000 (23:17 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Oct 2006 23:17:04 +0000 (23:17 +0000)
* testsuite/libjava.jni/register2.out: New file.
* testsuite/libjava.jni/register2.c: New file.
* java/lang/natClass.cc (_Jv_GetClassNameUtf8): New function.
* java/lang/Class.h (_Jv_GetClassNameUtf8): Declare.
* jni.cc (struct NativeMethodCacheEntry): New struct.
(nathash): Changed type.
(hash): Updated.
(nathash_find_slot): Likewise.
(nathash_find): Likewise.
(natrehash): Likewise.
(nathash_add): Likewise.
(_Jv_JNI_RegisterNatives): Likewise.
(_Jv_LookupJNIMethod): Likewise.
Idea from Juerg Lehni <juerg@scratchdisk.com>

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117867 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/java/lang/Class.h
libjava/java/lang/natClass.cc
libjava/jni.cc
libjava/testsuite/libjava.jni/register2.c [new file with mode: 0644]
libjava/testsuite/libjava.jni/register2.java [new file with mode: 0644]
libjava/testsuite/libjava.jni/register2.out [new file with mode: 0644]

index 98d4c41..9dc4833 100644 (file)
@@ -1,3 +1,22 @@
+2006-10-18  Tom Tromey  <tromey@redhat.com>
+           Bryce McKinlay  <mckinlay@redhat.com>
+
+       * testsuite/libjava.jni/register2.java: New file.
+       * testsuite/libjava.jni/register2.out: New file.
+       * testsuite/libjava.jni/register2.c: New file.
+       * java/lang/natClass.cc (_Jv_GetClassNameUtf8): New function.
+       * java/lang/Class.h (_Jv_GetClassNameUtf8): Declare.
+       * jni.cc (struct NativeMethodCacheEntry): New struct.
+       (nathash): Changed type.
+       (hash): Updated.
+       (nathash_find_slot): Likewise.
+       (nathash_find): Likewise.
+       (natrehash): Likewise.
+       (nathash_add): Likewise.
+       (_Jv_JNI_RegisterNatives): Likewise.
+       (_Jv_LookupJNIMethod): Likewise.
+       Idea from Juerg Lehni <juerg@scratchdisk.com>
+
 2006-10-16  Geoffrey Keating  <geoffk@apple.com>
 
        * testsuite/libjava.jvmti/natevents.cc (env): Delete.
index 1638f94..a884cd6 100644 (file)
@@ -231,6 +231,7 @@ jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);
 jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);
 jint JvNumMethods (jclass);
 jmethodID JvGetFirstMethod (jclass);
+_Jv_Utf8Const *_Jv_GetClassNameUtf8 (jclass);
 
 #ifdef INTERPRETER
 // Finds a desired interpreter method in the given class or NULL if not found
@@ -474,6 +475,7 @@ private:
   friend jmethodID (::_Jv_FromReflectedConstructor) (java::lang::reflect::Constructor *);
   friend jint (::JvNumMethods) (jclass);
   friend jmethodID (::JvGetFirstMethod) (jclass);
+  friend _Jv_Utf8Const *::_Jv_GetClassNameUtf8 (jclass);
 #ifdef INTERPRETER
   friend _Jv_MethodBase *(::_Jv_FindInterpreterMethod) (jclass klass,
                                                        jmethodID desired_method);
index 0682fd6..1298429 100644 (file)
@@ -1259,3 +1259,11 @@ _Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method)
   return NULL;
 }
 #endif
+
+// Return Utf8 name of a class. This function is here for code that
+// can't access klass->name directly.
+_Jv_Utf8Const*
+_Jv_GetClassNameUtf8 (jclass klass)
+{
+  return klass->name;
+}
index f7d73e5..c5c2b0f 100644 (file)
@@ -1789,8 +1789,13 @@ _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
 
 \f
 
+struct NativeMethodCacheEntry : public JNINativeMethod
+{
+  char *className;
+};
+
 // Hash table of native methods.
-static JNINativeMethod *nathash;
+static NativeMethodCacheEntry *nathash;
 // Number of slots used.
 static int nathash_count = 0;
 // Number of slots available.  Must be power of 2.
@@ -1800,11 +1805,15 @@ static int nathash_size = 0;
 
 // Compute a hash value for a native method descriptor.
 static int
-hash (const JNINativeMethod *method)
+hash (const NativeMethodCacheEntry *method)
 {
   char *ptr;
   int hash = 0;
 
+  ptr = method->className;
+  while (*ptr)
+    hash = (31 * hash) + *ptr++;
+
   ptr = method->name;
   while (*ptr)
     hash = (31 * hash) + *ptr++;
@@ -1817,8 +1826,8 @@ hash (const JNINativeMethod *method)
 }
 
 // Find the slot where a native method goes.
-static JNINativeMethod *
-nathash_find_slot (const JNINativeMethod *method)
+static NativeMethodCacheEntry *
+nathash_find_slot (const NativeMethodCacheEntry *method)
 {
   jint h = hash (method);
   int step = (h ^ (h >> 16)) | 1;
@@ -1827,7 +1836,7 @@ nathash_find_slot (const JNINativeMethod *method)
 
   for (;;)
     {
-      JNINativeMethod *slotp = &nathash[w];
+      NativeMethodCacheEntry *slotp = &nathash[w];
       if (slotp->name == NULL)
        {
          if (del >= 0)
@@ -1838,7 +1847,8 @@ nathash_find_slot (const JNINativeMethod *method)
       else if (slotp->name == DELETED_ENTRY)
        del = w;
       else if (! strcmp (slotp->name, method->name)
-              && ! strcmp (slotp->signature, method->signature))
+              && ! strcmp (slotp->signature, method->signature)
+              && ! strcmp (slotp->className, method->className))
        return slotp;
       w = (w + step) & (nathash_size - 1);
     }
@@ -1846,11 +1856,11 @@ nathash_find_slot (const JNINativeMethod *method)
 
 // Find a method.  Return NULL if it isn't in the hash table.
 static void *
-nathash_find (JNINativeMethod *method)
+nathash_find (NativeMethodCacheEntry *method)
 {
   if (nathash == NULL)
     return NULL;
-  JNINativeMethod *slot = nathash_find_slot (method);
+  NativeMethodCacheEntry *slot = nathash_find_slot (method);
   if (slot->name == NULL || slot->name == DELETED_ENTRY)
     return NULL;
   return slot->fnPtr;
@@ -1863,23 +1873,23 @@ natrehash ()
     {
       nathash_size = 1024;
       nathash =
-       (JNINativeMethod *) _Jv_AllocBytes (nathash_size
-                                           * sizeof (JNINativeMethod));
+       (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
+                                                  * sizeof (NativeMethodCacheEntry));
     }
   else
     {
       int savesize = nathash_size;
-      JNINativeMethod *savehash = nathash;
+      NativeMethodCacheEntry *savehash = nathash;
       nathash_size *= 2;
       nathash =
-       (JNINativeMethod *) _Jv_AllocBytes (nathash_size
-                                           * sizeof (JNINativeMethod));
+       (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
+                                                  * sizeof (NativeMethodCacheEntry));
 
       for (int i = 0; i < savesize; ++i)
        {
          if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
            {
-             JNINativeMethod *slot = nathash_find_slot (&savehash[i]);
+             NativeMethodCacheEntry *slot = nathash_find_slot (&savehash[i]);
              *slot = savehash[i];
            }
        }
@@ -1887,16 +1897,17 @@ natrehash ()
 }
 
 static void
-nathash_add (const JNINativeMethod *method)
+nathash_add (const NativeMethodCacheEntry *method)
 {
   if (3 * nathash_count >= 2 * nathash_size)
     natrehash ();
-  JNINativeMethod *slot = nathash_find_slot (method);
+  NativeMethodCacheEntry *slot = nathash_find_slot (method);
   // If the slot has a real entry in it, then there is no work to do.
   if (slot->name != NULL && slot->name != DELETED_ENTRY)
     return;
-  // FIXME
+  // FIXME: memory leak?
   slot->name = strdup (method->name);
+  slot->className = strdup (method->className);
   // This was already strduped in _Jv_JNI_RegisterNatives.
   slot->signature = method->signature;
   slot->fnPtr = method->fnPtr;
@@ -1912,7 +1923,7 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
   // the nathash table.
   JvSynchronize sync (global_ref_table);
 
-  JNINativeMethod dottedMethod;
+  NativeMethodCacheEntry dottedMethod;
 
   // Look at each descriptor given us, and find the corresponding
   // method in the class.
@@ -1928,8 +1939,11 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
          // Copy this JNINativeMethod and do a slash to dot
          // conversion on the signature.
          dottedMethod.name = methods[j].name;
+         // FIXME: we leak a little memory here if the method
+         // is not found.
          dottedMethod.signature = strdup (methods[j].signature);
          dottedMethod.fnPtr = methods[j].fnPtr;
+         dottedMethod.className = _Jv_GetClassNameUtf8 (klass)->chars();
          char *c = dottedMethod.signature;
          while (*c)
            {
@@ -2172,9 +2186,10 @@ _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
   buf[name_length] = '\0';
   strncpy (buf + name_length + 1, signature->chars (), sig_length);
   buf[name_length + sig_length + 1] = '\0';
-  JNINativeMethod meth;
+  NativeMethodCacheEntry meth;
   meth.name = buf;
   meth.signature = buf + name_length + 1;
+  meth.className = _Jv_GetClassNameUtf8(klass)->chars();
   function = nathash_find (&meth);
   if (function != NULL)
     return function;
diff --git a/libjava/testsuite/libjava.jni/register2.c b/libjava/testsuite/libjava.jni/register2.c
new file mode 100644 (file)
index 0000000..1ed10a8
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <register2.h>
+
+static int
+twentythree (JNIEnv *env, jclass k)
+{
+  return 23;
+}
+
+static int
+oneninetyseven (JNIEnv *env, jclass k)
+{
+  return 197;
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad (JavaVM *vm, void *nothing)
+{
+  JNIEnv *env;
+  JNINativeMethod meth;
+  jclass k;
+  jint r;
+
+  r = (*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_2);
+  assert (r == JNI_OK);
+  k = (*env)->FindClass (env, "register2$I1");
+  assert (k != NULL);
+
+  meth.name = "doit";
+  meth.signature = "()I";
+  meth.fnPtr = twentythree;
+
+  r = (*env)->RegisterNatives (env, k, &meth, 1);
+  assert (r == JNI_OK);
+
+  k = (*env)->FindClass (env, "register2$I2");
+  assert (k != NULL);
+
+  meth.name = "doit";
+  meth.signature = "()I";
+  meth.fnPtr = oneninetyseven;
+
+  r = (*env)->RegisterNatives (env, k, &meth, 1);
+  assert (r == JNI_OK);
+
+  return JNI_VERSION_1_2;
+}
diff --git a/libjava/testsuite/libjava.jni/register2.java b/libjava/testsuite/libjava.jni/register2.java
new file mode 100644 (file)
index 0000000..2d6c56a
--- /dev/null
@@ -0,0 +1,27 @@
+// Another test of RegisterNatives.
+// We neglected to track the class name in our internal hash table.
+// This is a regression test for the fix.
+
+public class register2
+{
+  static
+  {
+    System.loadLibrary ("register2");
+  }
+
+  static class I1
+  {
+    public static native int doit ();
+  }
+
+  static class I2
+  {
+    public static native int doit ();
+  }
+
+  public static void main (String[] args)
+  {
+    System.out.println (new I1().doit());
+    System.out.println (new I2().doit());
+  }
+}
diff --git a/libjava/testsuite/libjava.jni/register2.out b/libjava/testsuite/libjava.jni/register2.out
new file mode 100644 (file)
index 0000000..5b90358
--- /dev/null
@@ -0,0 +1,2 @@
+23
+197