X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvmcore%2Floader.c;h=d7b90d98737ae5b6ea28af05a7aa09be1c043742;hb=f02ed17b806efe4e5b417365e9aac478b51b86d9;hp=26447947c10ce9ef8c82854f5ded7bb33482f19c;hpb=192b7fc58d70858c438d182301f2af6616c338c3;p=cacao.git diff --git a/src/vmcore/loader.c b/src/vmcore/loader.c index 26447947c..d7b90d987 100644 --- a/src/vmcore/loader.c +++ b/src/vmcore/loader.c @@ -22,8 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: loader.c 8249 2007-07-31 12:59:03Z panzi $ - */ @@ -37,13 +35,17 @@ #include "mm/memory.h" +#include "native/llni.h" + #include "threads/lock-common.h" +#include "toolbox/hashtable.h" #include "toolbox/logging.h" #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/global.h" +#include "vm/primitive.h" #include "vm/stringlocal.h" #include "vm/vm.h" @@ -60,7 +62,6 @@ #include "vmcore/loader.h" #include "vmcore/method.h" #include "vmcore/options.h" -#include "vmcore/primitive.h" #include "vmcore/rt-timing.h" #if defined(ENABLE_STATISTICS) @@ -78,14 +79,19 @@ #endif -/* loader_init ***************************************************************** +/* global variables ***********************************************************/ + +static hashtable *hashtable_classloader; + - Initializes all lists and loads all classes required for the system - or the compiler. +/* loader_preinit ************************************************************** + + Initializes the classpath list and loads classes required for the + primitive table. *******************************************************************************/ -bool loader_init(void) +void loader_preinit(void) { #if defined(ENABLE_THREADS) list_classpath_entry *lce; @@ -93,101 +99,115 @@ bool loader_init(void) /* 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 */ - if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object))) - return false; + hashtable_classloader = NEW(hashtable); + hashtable_create(hashtable_classloader, 10); - if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String))) - return false; + /* Load the most basic class. */ + + if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object))) + vm_abort("loader_preinit: loading java/lang/Object failed"); #if defined(ENABLE_JAVASE) if (!(class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable))) - return false; + vm_abort("loader_preinit: loading java/lang/Cloneable failed"); if (!(class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable))) - return false; + vm_abort("loader_preinit: loading java/io/Serializable failed"); #endif +} + - /* load classes for wrapping primitive types */ +/* loader_init ***************************************************************** + + Loads all classes required in the VM. + +*******************************************************************************/ + +void loader_init(void) +{ + /* Load primitive-type wrapping classes. */ #if defined(ENABLE_JAVASE) if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void))) - return false; + vm_abort("loader_init: loading failed"); #endif if (!(class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double))) - return false; - + vm_abort("loader_init: loading failed"); - /* load some other important classes */ + /* Load important system classes. */ if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class))) - return false; + vm_abort("loader_init: loading failed"); + + if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String))) + vm_abort("loader_init: loading failed"); #if defined(ENABLE_JAVASE) if (!(class_java_lang_ClassLoader = load_class_bootstrap(utf_java_lang_ClassLoader))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_SecurityManager = load_class_bootstrap(utf_java_lang_SecurityManager))) - return false; + vm_abort("loader_init: loading failed"); #endif if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_Thread = load_class_bootstrap(utf_new_char("java/lang/Thread")))) - return false; + vm_abort("loader_init: loading failed"); #if defined(ENABLE_JAVASE) if (!(class_java_lang_ThreadGroup = load_class_bootstrap(utf_java_lang_ThreadGroup))) - return false; + vm_abort("loader_init: loading failed"); #endif #if defined(WITH_CLASSPATH_GNU) if (!(class_java_lang_VMSystem = load_class_bootstrap(utf_new_char("java/lang/VMSystem")))) - - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_VMThread = load_class_bootstrap(utf_new_char("java/lang/VMThread")))) - return false; + vm_abort("loader_init: loading failed"); #endif @@ -196,54 +216,173 @@ bool loader_init(void) #if defined(ENABLE_JAVASE) if (!(class_java_lang_StackTraceElement = load_class_bootstrap(utf_java_lang_StackTraceElement))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_reflect_Constructor = load_class_bootstrap(utf_java_lang_reflect_Constructor))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_reflect_Field = load_class_bootstrap(utf_java_lang_reflect_Field))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_lang_reflect_Method = load_class_bootstrap(utf_java_lang_reflect_Method))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction")))) - return false; + vm_abort("loader_init: loading failed"); if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector))) - return false; + vm_abort("loader_init: loading failed"); # if defined(WITH_CLASSPATH_SUN) if (!(class_sun_reflect_MagicAccessorImpl = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl")))) - return false; + vm_abort("loader_init: loading failed"); # endif if (!(arrayclass_java_lang_Object = load_class_bootstrap(utf_new_char("[Ljava/lang/Object;")))) - return false; + vm_abort("loader_init: loading failed"); -#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; + load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser")))) + vm_abort("loader_init: loading failed"); +# endif +# endif #endif +} + + +/* 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; - return true; + 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; } @@ -845,9 +984,10 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature) classinfo *load_class_from_sysloader(utf *name) { - methodinfo *m; - java_objectheader *cl; - classinfo *c; + methodinfo *m; + java_handle_t *clo; + classloader *cl; + classinfo *c; assert(class_java_lang_Object); assert(class_java_lang_ClassLoader); @@ -862,11 +1002,13 @@ classinfo *load_class_from_sysloader(utf *name) if (!m) return false; - cl = vm_call_method(m, NULL); + clo = vm_call_method(m, NULL); - if (!cl) + if (!clo) return false; + cl = loader_hashtable_classloader_add(clo); + c = load_class_from_classloader(name, cl); return c; @@ -887,12 +1029,12 @@ classinfo *load_class_from_sysloader(utf *name) *******************************************************************************/ -classinfo *load_class_from_classloader(utf *name, java_objectheader *cl) +classinfo *load_class_from_classloader(utf *name, classloader *cl) { - java_objectheader *o; - classinfo *c; - classinfo *tmpc; - java_objectheader *string; + java_handle_t *o; + classinfo *c; + classinfo *tmpc; + java_handle_t *string; #if defined(ENABLE_RT_TIMING) struct timespec time_start, time_lookup, time_prepare, time_java, time_cache; @@ -985,15 +1127,24 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl) } } - 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->object->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* */ @@ -1002,11 +1153,15 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl) RT_TIMING_GET_TIME(time_prepare); - o = vm_call_method(lc, cl, string); +#if defined(ENABLE_HANDLES) + o = vm_call_method(lc, (java_handle_t *) cl, string); +#else + o = vm_call_method(lc, cl->object, string); +#endif RT_TIMING_GET_TIME(time_java); - c = (classinfo *) o; + c = LLNI_classinfo_unwrap(o); if (c != NULL) { /* Store this class in the loaded class cache. If another @@ -1209,27 +1364,24 @@ classinfo *load_class_bootstrap(utf *name) } -/* load_class_from_classbuffer ************************************************* +/* load_class_from_classbuffer_intern ****************************************** - Loads everything interesting about a class from the class file. The - 'classinfo' structure must have been allocated previously. - - The super class and the interfaces implemented by this class need - not be loaded. The link is set later by the function 'class_link'. + Loads a class from a classbuffer into a given classinfo structure. + Super-classes are also loaded at this point and some verfication + checks are done. SYNCHRONIZATION: This function is NOT synchronized! *******************************************************************************/ -classinfo *load_class_from_classbuffer(classbuffer *cb) +static bool load_class_from_classbuffer_intern(classbuffer *cb) { classinfo *c; utf *name; utf *supername; u4 i,j; u4 ma, mi; - s4 dumpsize; descriptor_pool *descpool; #if defined(ENABLE_STATISTICS) u4 classrefsize; @@ -1244,44 +1396,18 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) RT_TIMING_GET_TIME(time_start); - /* get the classbuffer's class */ + /* Get the classbuffer's class. */ c = cb->class; - /* the class is already loaded */ - - if (c->state & CLASS_LOADED) - return c; - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - count_class_loads++; -#endif - -#if !defined(NDEBUG) - /* output for debugging purposes */ - - if (loadverbose) - log_message_class("Loading class: ", c); -#endif - - /* mark start of dump memory area */ - - dumpsize = dump_size(); - - /* class is currently loading */ - - c->state |= CLASS_LOADING; - if (!suck_check_classbuffer_size(cb, 4 + 2 + 2)) - goto return_exception; + return false; /* check signature */ if (suck_u4(cb) != MAGIC) { exceptions_throw_classformaterror(c, "Bad magic number"); - - goto return_exception; + return false; } /* check version */ @@ -1291,7 +1417,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) { exceptions_throw_unsupportedclassversionerror(c, ma, mi); - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_checks); @@ -1305,14 +1431,14 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) /* load the constant pool */ if (!load_constantpool(cb, descpool)) - goto return_exception; + return false; RT_TIMING_GET_TIME(time_cpool); /* ACC flags */ if (!suck_check_classbuffer_size(cb, 2)) - goto return_exception; + return false; /* We OR the flags here, as we set already some flags in class_create_classinfo. */ @@ -1333,7 +1459,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) exceptions_throw_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags); - goto return_exception; + return false; } if (c->flags & ACC_SUPER) { @@ -1345,18 +1471,18 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) exceptions_throw_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags); - goto return_exception; + return false; } if (!suck_check_classbuffer_size(cb, 2 + 2)) - goto return_exception; + return false; /* this class */ i = suck_u2(cb); if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class))) - goto return_exception; + return false; if (c->name == utf_not_named_yet) { /* we finally have a name for this class */ @@ -1365,7 +1491,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) } else if (name != c->name) { exceptions_throw_noclassdeffounderror_wrong_name(c, name); - goto return_exception; + return false; } /* retrieve superclass */ @@ -1374,83 +1500,83 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if ((i = suck_u2(cb))) { if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class))) - goto return_exception; + return false; /* java.lang.Object may not have a super class. */ if (c->name == utf_java_lang_Object) { exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass"); - goto return_exception; + return false; } /* Interfaces must have java.lang.Object as super class. */ if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) { exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass"); - goto return_exception; + return false; } - - } else { + } + else { supername = NULL; /* This is only allowed for java.lang.Object. */ if (c->name != utf_java_lang_Object) { exceptions_throw_classformaterror(c, "Bad superclass index"); - goto return_exception; + return false; } } /* retrieve interfaces */ if (!suck_check_classbuffer_size(cb, 2)) - goto return_exception; + return false; c->interfacescount = suck_u2(cb); if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount)) - goto return_exception; + return false; c->interfaces = MNEW(classref_or_classinfo, c->interfacescount); + for (i = 0; i < c->interfacescount; i++) { /* the classrefs are created later */ if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class))) - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_setup); /* load fields */ + if (!suck_check_classbuffer_size(cb, 2)) - goto return_exception; + return false; c->fieldscount = suck_u2(cb); -#if defined(ENABLE_GC_CACAO) - c->fields = MNEW(fieldinfo, c->fieldscount); + c->fields = MNEW(fieldinfo, c->fieldscount); + MZERO(c->fields, fieldinfo, c->fieldscount); -#else - c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount); -#endif for (i = 0; i < c->fieldscount; i++) { if (!field_load(cb, &(c->fields[i]), descpool)) - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_fields); /* load methods */ + if (!suck_check_classbuffer_size(cb, 2)) - goto return_exception; + return false; c->methodscount = suck_u2(cb); - c->methods = MNEW(methodinfo, c->methodscount); + c->methods = MNEW(methodinfo, c->methodscount); MZERO(c->methods, methodinfo, c->methodscount); for (i = 0; i < c->methodscount; i++) { if (!method_load(cb, &(c->methods[i]), descpool)) - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_methods); @@ -1491,7 +1617,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (supername) { c->super.ref = descriptor_pool_lookup_classref(descpool, supername); if (!c->super.ref) - goto return_exception; + return false; } /* set the super interfaces references */ @@ -1501,7 +1627,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) descriptor_pool_lookup_classref(descpool, (utf *) c->interfaces[i].any); if (!c->interfaces[i].ref) - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_setrefs); @@ -1513,7 +1639,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) descriptor_pool_parse_field_descriptor(descpool, c->fields[i].descriptor); if (!c->fields[i].parseddesc) - goto return_exception; + return false; } RT_TIMING_GET_TIME(time_parsefds); @@ -1526,23 +1652,25 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) descriptor_pool_parse_method_descriptor(descpool, m->descriptor, m->flags, class_get_self_classref(m->class)); if (!m->parseddesc) - goto return_exception; + return false; for (j = 0; j < m->rawexceptiontablelength; j++) { if (!m->rawexceptiontable[j].catchtype.any) continue; + if ((m->rawexceptiontable[j].catchtype.ref = descriptor_pool_lookup_classref(descpool, (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL) - goto return_exception; + return false; } for (j = 0; j < m->thrownexceptionscount; j++) { if (!m->thrownexceptions[j].any) continue; + if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool, (utf *) m->thrownexceptions[j].any)) == NULL) - goto return_exception; + return false; } } @@ -1561,13 +1689,14 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) descriptor_pool_parse_field_descriptor(descpool, fmi->descriptor); if (!fmi->parseddesc.fd) - goto return_exception; + return false; + index = fmi->p.index; fmi->p.classref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class); if (!fmi->p.classref) - goto return_exception; + return false; break; case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: @@ -1577,14 +1706,14 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) (constant_classref *) class_getconstant(c, index, CONSTANT_Class); if (!fmi->p.classref) - goto return_exception; + return false; fmi->parseddesc.md = descriptor_pool_parse_method_descriptor(descpool, fmi->descriptor, ACC_UNDEF, fmi->p.classref); if (!fmi->parseddesc.md) - goto return_exception; + return false; break; } } @@ -1640,7 +1769,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (c->fields[old].name == fi->name && c->fields[old].descriptor == fi->descriptor) { exceptions_throw_classformaterror(c, "Repetitive field name/signature"); - goto return_exception; + return false; } } while ((old = next[old])); } @@ -1657,13 +1786,6 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) index = ((((size_t) mi->name) + ((size_t) mi->descriptor)) >> shift) % hashlen; - /*{ JOWENN - int dbg; - for (dbg=0;dbgmethods[old].name == mi->name && c->methods[old].descriptor == mi->descriptor) { exceptions_throw_classformaterror(c, "Repetitive method name/signature"); - goto return_exception; + return false; } } while ((old = next[old])); } @@ -1695,12 +1817,11 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) /* load attribute structures */ if (!class_load_attributes(cb)) - goto return_exception; + return false; - /* Pre Java 1.5 version don't check this. This implementation is like - Java 1.5 do it: for class file version 45.3 we don't check it, older - versions are checked. - */ + /* Pre Java 1.5 version don't check this. This implementation is + like Java 1.5 do it: for class file version 45.3 we don't check + it, older versions are checked. */ if (((ma == 45) && (mi > 3)) || (ma > 45)) { /* check if all data has been read */ @@ -1708,32 +1829,12 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (classdata_left > 0) { exceptions_throw_classformaterror(c, "Extra bytes at the end of class file"); - goto return_exception; + return false; } } RT_TIMING_GET_TIME(time_attrs); - /* release dump area */ - - dump_release(dumpsize); - - /* revert loading state and class is loaded */ - - c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED; - -#if defined(ENABLE_JVMTI) - /* fire Class Prepare JVMTI event */ - - if (jvmti) - jvmti_ClassLoadPrepare(true, c); -#endif - -#if !defined(NDEBUG) - if (loadverbose) - log_message_class("Loading done class: ", c); -#endif - RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS); RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL); RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL); @@ -1750,16 +1851,87 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS); RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL); - return c; + return true; +} + + +/* load_class_from_classbuffer ************************************************* + + Convenience wrapper for load_class_from_classbuffer. + + SYNCHRONIZATION: + This function is NOT synchronized! + +*******************************************************************************/ + +classinfo *load_class_from_classbuffer(classbuffer *cb) +{ + classinfo *c; + int32_t dumpsize; + bool result; + + /* Get the classbuffer's class. */ + + c = cb->class; + + /* Check if the class is already loaded. */ + + if (c->state & CLASS_LOADED) + return c; + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + count_class_loads++; +#endif + +#if !defined(NDEBUG) + if (loadverbose) + log_message_class("Loading class: ", c); +#endif + + /* Mark start of dump memory area. */ + + dumpsize = dump_size(); -return_exception: - /* release dump area */ + /* Class is currently loading. */ + + c->state |= CLASS_LOADING; + + /* Parse the classbuffer. */ + + result = load_class_from_classbuffer_intern(cb); + + /* Release dump area. */ dump_release(dumpsize); - /* an exception has been thrown */ + /* An error occurred. */ - return NULL; + if (result == false) { + /* Revert loading state. */ + + c->state = (c->state & ~CLASS_LOADING); + + return NULL; + } + + /* Revert loading state and set loaded. */ + + c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED; + +#if defined(ENABLE_JVMTI) + /* fire Class Prepare JVMTI event */ + + if (jvmti) + jvmti_ClassLoadPrepare(true, c); +#endif + +#if !defined(NDEBUG) + if (loadverbose) + log_message_class("Loading done class: ", c); +#endif + + return c; } @@ -1781,7 +1953,7 @@ return_exception: *******************************************************************************/ -classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader) +classinfo *load_newly_created_array(classinfo *c, classloader *loader) { classinfo *comp = NULL; methodinfo *clone;