summaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2006-10-18 23:17:04 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2006-10-18 23:17:04 +0000
commitb68dfd9590812041be7f41c9e44877a936bf0b6f (patch)
tree090a052b333feb86cf809ba60ebdc7a86794ff1e /libjava
parentdf45db482c1b39f2c39dce63ffabab82e8a68c5c (diff)
downloadgcc-b68dfd9590812041be7f41c9e44877a936bf0b6f.tar.gz
* 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> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117867 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog19
-rw-r--r--libjava/java/lang/Class.h2
-rw-r--r--libjava/java/lang/natClass.cc8
-rw-r--r--libjava/jni.cc53
-rw-r--r--libjava/testsuite/libjava.jni/register2.c48
-rw-r--r--libjava/testsuite/libjava.jni/register2.java27
-rw-r--r--libjava/testsuite/libjava.jni/register2.out2
7 files changed, 140 insertions, 19 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 98d4c41a90f..9dc48337bfe 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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.
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index 1638f94e107..a884cd6c59b 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -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);
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 0682fd6e190..12984291ee1 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -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;
+}
diff --git a/libjava/jni.cc b/libjava/jni.cc
index f7d73e55385..c5c2b0ff3cd 100644
--- a/libjava/jni.cc
+++ b/libjava/jni.cc
@@ -1789,8 +1789,13 @@ _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
+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
index 00000000000..1ed10a88a23
--- /dev/null
+++ b/libjava/testsuite/libjava.jni/register2.c
@@ -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
index 00000000000..2d6c56a3b02
--- /dev/null
+++ b/libjava/testsuite/libjava.jni/register2.java
@@ -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
index 00000000000..5b90358a22b
--- /dev/null
+++ b/libjava/testsuite/libjava.jni/register2.out
@@ -0,0 +1,2 @@
+23
+197