--- jni.cc 2006-06-01 16:04:21.000000000 +0200 +++ jni.cc 2006-06-19 23:05:14.000000000 +0200 @@ -1775,10 +1775,16 @@ return tmp->capacity(); } - +typedef struct +{ + char *class_name; + char *name; + char *signature; + void *fnPtr; +} NativeMethod; // Hash table of native methods. -static JNINativeMethod *nathash; +static NativeMethod *nathash; // Number of slots used. static int nathash_count = 0; // Number of slots available. Must be power of 2. @@ -1788,11 +1794,15 @@ // Compute a hash value for a native method descriptor. static int -hash (const JNINativeMethod *method) +hash (const NativeMethod *method) { char *ptr; int hash = 0; + ptr = method->class_name; + while (*ptr) + hash = (31 * hash) + *ptr++; + ptr = method->name; while (*ptr) hash = (31 * hash) + *ptr++; @@ -1805,8 +1815,8 @@ } // Find the slot where a native method goes. -static JNINativeMethod * -nathash_find_slot (const JNINativeMethod *method) +static NativeMethod * +nathash_find_slot (const NativeMethod *method) { jint h = hash (method); int step = (h ^ (h >> 16)) | 1; @@ -1815,7 +1825,7 @@ for (;;) { - JNINativeMethod *slotp = &nathash[w]; + NativeMethod *slotp = &nathash[w]; if (slotp->name == NULL) { if (del >= 0) @@ -1825,7 +1835,8 @@ } else if (slotp->name == DELETED_ENTRY) del = w; - else if (! strcmp (slotp->name, method->name) + else if (! strcmp (slotp->class_name, method->class_name) + && ! strcmp (slotp->name, method->name) && ! strcmp (slotp->signature, method->signature)) return slotp; w = (w + step) & (nathash_size - 1); @@ -1834,11 +1845,11 @@ // Find a method. Return NULL if it isn't in the hash table. static void * -nathash_find (JNINativeMethod *method) +nathash_find (NativeMethod *method) { if (nathash == NULL) return NULL; - JNINativeMethod *slot = nathash_find_slot (method); + NativeMethod *slot = nathash_find_slot (method); if (slot->name == NULL || slot->name == DELETED_ENTRY) return NULL; return slot->fnPtr; @@ -1851,39 +1862,42 @@ { nathash_size = 1024; nathash = - (JNINativeMethod *) _Jv_AllocBytes (nathash_size - * sizeof (JNINativeMethod)); + (NativeMethod *) _Jv_AllocBytes (nathash_size + * sizeof (NativeMethod)); } else { int savesize = nathash_size; - JNINativeMethod *savehash = nathash; + NativeMethod *savehash = nathash; nathash_size *= 2; nathash = - (JNINativeMethod *) _Jv_AllocBytes (nathash_size - * sizeof (JNINativeMethod)); + (NativeMethod *) _Jv_AllocBytes (nathash_size + * sizeof (NativeMethod)); for (int i = 0; i < savesize; ++i) { if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY) { - JNINativeMethod *slot = nathash_find_slot (&savehash[i]); + NativeMethod *slot = nathash_find_slot (&savehash[i]); *slot = savehash[i]; } } + // free old table after rehash + _Jv_Free (savehash); } } static void -nathash_add (const JNINativeMethod *method) +nathash_add (const NativeMethod *method) { if (3 * nathash_count >= 2 * nathash_size) natrehash (); - JNINativeMethod *slot = nathash_find_slot (method); + NativeMethod *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 + slot->class_name = strdup (method->class_name); slot->name = strdup (method->name); // This was already strduped in _Jv_JNI_RegisterNatives. slot->signature = method->signature; @@ -1900,10 +1914,15 @@ // the nathash table. JvSynchronize sync (global_ref_table); - JNINativeMethod dottedMethod; + NativeMethod method; // Look at each descriptor given us, and find the corresponding // method in the class. + + // Get the class name in UTF format + method.class_name = strdup (_Jv_GetClassNameUtf8 (klass)->chars ()); + + jint r = JNI_OK; for (int j = 0; j < nMethods; ++j) { bool found = false; @@ -1915,10 +1934,10 @@ // Copy this JNINativeMethod and do a slash to dot // conversion on the signature. - dottedMethod.name = methods[j].name; - dottedMethod.signature = strdup (methods[j].signature); - dottedMethod.fnPtr = methods[j].fnPtr; - char *c = dottedMethod.signature; + method.name = methods[j].name; + method.signature = strdup (methods[j].signature); + method.fnPtr = methods[j].fnPtr; + char *c = method.signature; while (*c) { if (*c == '/') @@ -1926,15 +1945,15 @@ c++; } - if (! strcmp (self->name->chars (), dottedMethod.name) - && ! strcmp (self->signature->chars (), dottedMethod.signature)) + if (! strcmp (self->name->chars (), method.name) + && ! strcmp (self->signature->chars (), method.signature)) { if (! (self->accflags & java::lang::reflect::Modifier::NATIVE)) break; // Found a match that is native. found = true; - nathash_add (&dottedMethod); + nathash_add (&method); break; } @@ -1951,11 +1970,12 @@ { env->ex = t; } - return JNI_ERR; + r = JNI_ERR; + break; } } - - return JNI_OK; + _Jv_Free (method.class_name); + return r; } static jint JNICALL @@ -2160,10 +2180,13 @@ buf[name_length] = '\0'; strncpy (buf + name_length + 1, signature->chars (), sig_length); buf[name_length + sig_length + 1] = '\0'; - JNINativeMethod meth; + NativeMethod meth; + // Get the class name in UTF format + meth.class_name = strdup (_Jv_GetClassNameUtf8 (klass)->chars ()); meth.name = buf; meth.signature = buf + name_length + 1; function = nathash_find (&meth); + _Jv_Free (meth.class_name); if (function != NULL) return function;