const jbyte *buf, jsize bufLen)
{
#if defined(ENABLE_JAVASE)
- utf *u;
- classloader *cl;
- classinfo *c;
+ utf *u;
+ classloader *cl;
+ classinfo *c;
+ java_lang_Class *co;
- TRACEJNICALLS("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d", env, name, loader, buf, bufLen);
+ TRACEJNICALLS("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen);
u = utf_new_char(name);
- cl = (classloader *) loader;
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
- c = class_define(u, cl, bufLen, (const uint8_t *) buf, NULL);
+ c = class_define(u, cl, bufLen, (const uint8_t *) buf);
- return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
+ co = LLNI_classinfo_wrap(c);
+
+ return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) co);
#else
vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
{
java_handle_t *o;
+ classinfo *c;
methodinfo *m;
- STATISTICS(jniinvokation());
-
- o = exceptions_get_exception();
+ TRACEJNICALLS("_Jv_JNI_ExceptionDescribe(env=%p)", env);
- if (o == NULL) {
- /* clear exception, because we are calling jit code again */
+ /* Clear exception, because we are probably calling Java code
+ again. */
- exceptions_clear_exception();
+ o = exceptions_get_and_clear_exception();
- /* Get printStackTrace method from exception class. */
+ if (o != NULL) {
+ /* get printStackTrace method from exception class */
+
+ LLNI_class_get(o, c);
- m = class_resolveclassmethod(o->vftbl->class,
+ m = class_resolveclassmethod(c,
utf_printStackTrace,
utf_void__void,
NULL,
jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
jboolean isStatic)
--{
#if defined(ENABLE_JAVASE)
methodinfo *m;
java_lang_reflect_Constructor *rc;
#endif
- /* loader_init *****************************************************************
+/* global variables ***********************************************************/
+
+static hashtable *hashtable_classloader;
+
+
+ /* loader_preinit **************************************************************
- Initializes all lists and loads all classes required for the system
- or the compiler.
+ Initializes the classpath list and loads classes required for the
+ primitive table.
*******************************************************************************/
/* Initialize the monitor pointer for zip/jar file locking. */
for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce))
+ lce = list_next(list_classpath_entries, lce)) {
if (lce->type == CLASSPATH_ARCHIVE)
LOCK_INIT_OBJECT_LOCK(lce);
+ }
#endif
- /* load some important classes */
+ /* initialize classloader hashtable, 10 entries should be enough */
+
+ hashtable_classloader = NEW(hashtable);
+ hashtable_create(hashtable_classloader, 10);
+
+ /* Load the most basic class. */
if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
- return false;
-
- if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
- return false;
+ vm_abort("loader_preinit: loading java/lang/Object failed");
#if defined(ENABLE_JAVASE)
if (!(class_java_lang_Cloneable =
if (!(arrayclass_java_lang_Object =
load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
- vm_abort("loader_init: loading failed");
+ return false;
- #if defined(ENABLE_ANNOTATIONS)
+ # if defined(ENABLE_ANNOTATIONS)
/* needed by annotation support */
if (!(class_sun_reflect_ConstantPool =
- load_class_bootstrap(utf_sun_reflect_ConstantPool)))
- return false;
+ load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"))))
+ vm_abort("loader_init: loading failed");
- #if defined(WITH_CLASSPATH_GNU)
+ # if defined(WITH_CLASSPATH_GNU)
/* needed by GNU Classpaths annotation support */
if (!(class_sun_reflect_annotation_AnnotationParser =
- load_class_bootstrap(utf_sun_reflect_annotation_AnnotationParser)))
- return false;
- #endif
- #endif
+ load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"))))
+ vm_abort("loader_init: loading failed");
+ # endif
+ # endif
#endif
+
+
+ return true;
+}
+
+
+/* loader_hashtable_classloader_add ********************************************
+
+ Adds an entry to the classloader hashtable.
+
+ REMEMBER: Also use this to register native loaders!
+
+*******************************************************************************/
+
+classloader *loader_hashtable_classloader_add(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LOCK_MONITOR_ENTER(hashtable_classloader->header);
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+#if defined(ENABLE_GC_CACAO)
+ key = heap_get_hashcode(LLNI_DIRECT(cl)) >> 4;
+#else
+ key = ((u4) (ptrint) cl) >> 4;
+#endif
+
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+ LLNI_CRITICAL_END;
+
+ /* if no classloader was found, we create a new entry here */
+
+ if (cle == NULL) {
+ cle = NEW(hashtable_classloader_entry);
+
+#if defined(ENABLE_GC_CACAO)
+ /* register the classloader object with the GC */
+
+ gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
+#endif
+
+ LLNI_CRITICAL_START;
+
+ cle->object = LLNI_DIRECT(cl);
+
+ LLNI_CRITICAL_END;
+
+ /* insert entry into hashtable */
+
+ cle->hashlink = hashtable_classloader->ptr[slot];
+ hashtable_classloader->ptr[slot] = cle;
+
+ /* update number of entries */
+
+ hashtable_classloader->entries++;
+ }
+
+
+ LOCK_MONITOR_EXIT(hashtable_classloader->header);
+
+ return cle;
+}
+
+
+/* loader_hashtable_classloader_find *******************************************
+
+ Find an entry in the classloader hashtable.
+
+*******************************************************************************/
+
+classloader *loader_hashtable_classloader_find(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+#if defined(ENABLE_GC_CACAO)
+ key = heap_get_hashcode(LLNI_DIRECT(cl)) >> 4;
+#else
+ key = ((u4) (ptrint) cl) >> 4;
+#endif
+
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+ LLNI_CRITICAL_END;
+
+ return cle;
}
}
}
- assert(class_java_lang_Object);
+ #if defined(WITH_CLASSPATH_SUN)
+ /* OpenJDK uses this internal function because it's
+ synchronized. */
- lc = class_resolveclassmethod(cl->vftbl->class,
+ lc = class_resolveclassmethod(cl->object->vftbl->class,
+ utf_loadClassInternal,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+ #else
+ lc = class_resolveclassmethod(cl->vftbl->class,
utf_loadClass,
utf_java_lang_String__java_lang_Class,
- class_java_lang_Object,
+ NULL,
true);
+ #endif
- if (!lc)
+ if (lc == NULL)
return false; /* exception */
/* move return value into `o' and cast it afterwards to a classinfo* */