Commit e7f7d233 by Tom Tromey Committed by Tom Tromey

register2.java: New file.


	* 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>

Co-Authored-By: Bryce McKinlay <mckinlay@redhat.com>

From-SVN: r117867
parent 9e7fc6b9
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> 2006-10-16 Geoffrey Keating <geoffk@apple.com>
* testsuite/libjava.jvmti/natevents.cc (env): Delete. * testsuite/libjava.jvmti/natevents.cc (env): Delete.
......
...@@ -231,6 +231,7 @@ jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *); ...@@ -231,6 +231,7 @@ jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);
jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *); jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);
jint JvNumMethods (jclass); jint JvNumMethods (jclass);
jmethodID JvGetFirstMethod (jclass); jmethodID JvGetFirstMethod (jclass);
_Jv_Utf8Const *_Jv_GetClassNameUtf8 (jclass);
#ifdef INTERPRETER #ifdef INTERPRETER
// Finds a desired interpreter method in the given class or NULL if not found // Finds a desired interpreter method in the given class or NULL if not found
...@@ -474,6 +475,7 @@ private: ...@@ -474,6 +475,7 @@ private:
friend jmethodID (::_Jv_FromReflectedConstructor) (java::lang::reflect::Constructor *); friend jmethodID (::_Jv_FromReflectedConstructor) (java::lang::reflect::Constructor *);
friend jint (::JvNumMethods) (jclass); friend jint (::JvNumMethods) (jclass);
friend jmethodID (::JvGetFirstMethod) (jclass); friend jmethodID (::JvGetFirstMethod) (jclass);
friend _Jv_Utf8Const *::_Jv_GetClassNameUtf8 (jclass);
#ifdef INTERPRETER #ifdef INTERPRETER
friend _Jv_MethodBase *(::_Jv_FindInterpreterMethod) (jclass klass, friend _Jv_MethodBase *(::_Jv_FindInterpreterMethod) (jclass klass,
jmethodID desired_method); jmethodID desired_method);
......
...@@ -1259,3 +1259,11 @@ _Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method) ...@@ -1259,3 +1259,11 @@ _Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method)
return NULL; return NULL;
} }
#endif #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;
}
...@@ -1789,8 +1789,13 @@ _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer) ...@@ -1789,8 +1789,13 @@ _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
struct NativeMethodCacheEntry : public JNINativeMethod
{
char *className;
};
// Hash table of native methods. // Hash table of native methods.
static JNINativeMethod *nathash; static NativeMethodCacheEntry *nathash;
// Number of slots used. // Number of slots used.
static int nathash_count = 0; static int nathash_count = 0;
// Number of slots available. Must be power of 2. // Number of slots available. Must be power of 2.
...@@ -1800,11 +1805,15 @@ static int nathash_size = 0; ...@@ -1800,11 +1805,15 @@ static int nathash_size = 0;
// Compute a hash value for a native method descriptor. // Compute a hash value for a native method descriptor.
static int static int
hash (const JNINativeMethod *method) hash (const NativeMethodCacheEntry *method)
{ {
char *ptr; char *ptr;
int hash = 0; int hash = 0;
ptr = method->className;
while (*ptr)
hash = (31 * hash) + *ptr++;
ptr = method->name; ptr = method->name;
while (*ptr) while (*ptr)
hash = (31 * hash) + *ptr++; hash = (31 * hash) + *ptr++;
...@@ -1817,8 +1826,8 @@ hash (const JNINativeMethod *method) ...@@ -1817,8 +1826,8 @@ hash (const JNINativeMethod *method)
} }
// Find the slot where a native method goes. // Find the slot where a native method goes.
static JNINativeMethod * static NativeMethodCacheEntry *
nathash_find_slot (const JNINativeMethod *method) nathash_find_slot (const NativeMethodCacheEntry *method)
{ {
jint h = hash (method); jint h = hash (method);
int step = (h ^ (h >> 16)) | 1; int step = (h ^ (h >> 16)) | 1;
...@@ -1827,7 +1836,7 @@ nathash_find_slot (const JNINativeMethod *method) ...@@ -1827,7 +1836,7 @@ nathash_find_slot (const JNINativeMethod *method)
for (;;) for (;;)
{ {
JNINativeMethod *slotp = &nathash[w]; NativeMethodCacheEntry *slotp = &nathash[w];
if (slotp->name == NULL) if (slotp->name == NULL)
{ {
if (del >= 0) if (del >= 0)
...@@ -1838,7 +1847,8 @@ nathash_find_slot (const JNINativeMethod *method) ...@@ -1838,7 +1847,8 @@ nathash_find_slot (const JNINativeMethod *method)
else if (slotp->name == DELETED_ENTRY) else if (slotp->name == DELETED_ENTRY)
del = w; del = w;
else if (! strcmp (slotp->name, method->name) else if (! strcmp (slotp->name, method->name)
&& ! strcmp (slotp->signature, method->signature)) && ! strcmp (slotp->signature, method->signature)
&& ! strcmp (slotp->className, method->className))
return slotp; return slotp;
w = (w + step) & (nathash_size - 1); w = (w + step) & (nathash_size - 1);
} }
...@@ -1846,11 +1856,11 @@ nathash_find_slot (const JNINativeMethod *method) ...@@ -1846,11 +1856,11 @@ nathash_find_slot (const JNINativeMethod *method)
// Find a method. Return NULL if it isn't in the hash table. // Find a method. Return NULL if it isn't in the hash table.
static void * static void *
nathash_find (JNINativeMethod *method) nathash_find (NativeMethodCacheEntry *method)
{ {
if (nathash == NULL) if (nathash == NULL)
return NULL; return NULL;
JNINativeMethod *slot = nathash_find_slot (method); NativeMethodCacheEntry *slot = nathash_find_slot (method);
if (slot->name == NULL || slot->name == DELETED_ENTRY) if (slot->name == NULL || slot->name == DELETED_ENTRY)
return NULL; return NULL;
return slot->fnPtr; return slot->fnPtr;
...@@ -1863,23 +1873,23 @@ natrehash () ...@@ -1863,23 +1873,23 @@ natrehash ()
{ {
nathash_size = 1024; nathash_size = 1024;
nathash = nathash =
(JNINativeMethod *) _Jv_AllocBytes (nathash_size (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
* sizeof (JNINativeMethod)); * sizeof (NativeMethodCacheEntry));
} }
else else
{ {
int savesize = nathash_size; int savesize = nathash_size;
JNINativeMethod *savehash = nathash; NativeMethodCacheEntry *savehash = nathash;
nathash_size *= 2; nathash_size *= 2;
nathash = nathash =
(JNINativeMethod *) _Jv_AllocBytes (nathash_size (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
* sizeof (JNINativeMethod)); * sizeof (NativeMethodCacheEntry));
for (int i = 0; i < savesize; ++i) for (int i = 0; i < savesize; ++i)
{ {
if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY) 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]; *slot = savehash[i];
} }
} }
...@@ -1887,16 +1897,17 @@ natrehash () ...@@ -1887,16 +1897,17 @@ natrehash ()
} }
static void static void
nathash_add (const JNINativeMethod *method) nathash_add (const NativeMethodCacheEntry *method)
{ {
if (3 * nathash_count >= 2 * nathash_size) if (3 * nathash_count >= 2 * nathash_size)
natrehash (); 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 the slot has a real entry in it, then there is no work to do.
if (slot->name != NULL && slot->name != DELETED_ENTRY) if (slot->name != NULL && slot->name != DELETED_ENTRY)
return; return;
// FIXME // FIXME: memory leak?
slot->name = strdup (method->name); slot->name = strdup (method->name);
slot->className = strdup (method->className);
// This was already strduped in _Jv_JNI_RegisterNatives. // This was already strduped in _Jv_JNI_RegisterNatives.
slot->signature = method->signature; slot->signature = method->signature;
slot->fnPtr = method->fnPtr; slot->fnPtr = method->fnPtr;
...@@ -1912,7 +1923,7 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass, ...@@ -1912,7 +1923,7 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
// the nathash table. // the nathash table.
JvSynchronize sync (global_ref_table); JvSynchronize sync (global_ref_table);
JNINativeMethod dottedMethod; NativeMethodCacheEntry dottedMethod;
// Look at each descriptor given us, and find the corresponding // Look at each descriptor given us, and find the corresponding
// method in the class. // method in the class.
...@@ -1928,8 +1939,11 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass, ...@@ -1928,8 +1939,11 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
// Copy this JNINativeMethod and do a slash to dot // Copy this JNINativeMethod and do a slash to dot
// conversion on the signature. // conversion on the signature.
dottedMethod.name = methods[j].name; 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.signature = strdup (methods[j].signature);
dottedMethod.fnPtr = methods[j].fnPtr; dottedMethod.fnPtr = methods[j].fnPtr;
dottedMethod.className = _Jv_GetClassNameUtf8 (klass)->chars();
char *c = dottedMethod.signature; char *c = dottedMethod.signature;
while (*c) while (*c)
{ {
...@@ -2172,9 +2186,10 @@ _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name, ...@@ -2172,9 +2186,10 @@ _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
buf[name_length] = '\0'; buf[name_length] = '\0';
strncpy (buf + name_length + 1, signature->chars (), sig_length); strncpy (buf + name_length + 1, signature->chars (), sig_length);
buf[name_length + sig_length + 1] = '\0'; buf[name_length + sig_length + 1] = '\0';
JNINativeMethod meth; NativeMethodCacheEntry meth;
meth.name = buf; meth.name = buf;
meth.signature = buf + name_length + 1; meth.signature = buf + name_length + 1;
meth.className = _Jv_GetClassNameUtf8(klass)->chars();
function = nathash_find (&meth); function = nathash_find (&meth);
if (function != NULL) if (function != NULL)
return function; return function;
......
#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;
}
// 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());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment