Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: loader.c 8299 2007-08-13 08:41:18Z michi $
-
*/
#include "mm/memory.h"
+#include "native/llni.h"
+
#include "threads/lock-common.h"
#include "toolbox/hashtable.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/package.h"
#include "vm/primitive.h"
+#include "vm/resolve.h"
#include "vm/stringlocal.h"
#include "vm/vm.h"
static hashtable *hashtable_classloader;
-/* loader_init *****************************************************************
+/* 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.
+
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
*******************************************************************************/
-bool loader_init(void)
+void loader_preinit(void)
{
#if defined(ENABLE_THREADS)
list_classpath_entry *lce;
/* 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
/* initialize classloader hashtable, 10 entries should be enough */
hashtable_classloader = NEW(hashtable);
hashtable_create(hashtable_classloader, 10);
- /* load some important classes */
+ /* Load the most basic classes. */
- if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
- return false;
+ assert(vm_initializing == true);
- if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
- return false;
+ class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
#if defined(ENABLE_JAVASE)
- if (!(class_java_lang_Cloneable =
- load_class_bootstrap(utf_java_lang_Cloneable)))
- return false;
-
- if (!(class_java_io_Serializable =
- load_class_bootstrap(utf_java_io_Serializable)))
- return false;
+ class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
+ class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
#endif
+}
- /* load classes for wrapping primitive types */
-
-#if defined(ENABLE_JAVASE)
- if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
- return false;
-#endif
-
- if (!(class_java_lang_Boolean =
- load_class_bootstrap(utf_java_lang_Boolean)))
- return false;
-
- if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
- return false;
- if (!(class_java_lang_Character =
- load_class_bootstrap(utf_java_lang_Character)))
- return false;
+/* loader_init *****************************************************************
- if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
- return false;
+ Loads all classes required in the VM.
- if (!(class_java_lang_Integer =
- load_class_bootstrap(utf_java_lang_Integer)))
- return false;
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
- if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
- return false;
+*******************************************************************************/
+
+void loader_init(void)
+{
+ /* Load primitive-type wrapping classes. */
- if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
- return false;
+ assert(vm_initializing == true);
- if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
- return false;
+#if defined(ENABLE_JAVASE)
+ class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
+#endif
+ class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
+ class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
+ class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
+ class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
+ class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
+ class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
+ class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
+ class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
- /* load some other important classes */
+ /* Load important system classes. */
- if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
- return false;
+ class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
+ class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
#if defined(ENABLE_JAVASE)
- if (!(class_java_lang_ClassLoader =
- load_class_bootstrap(utf_java_lang_ClassLoader)))
- return false;
+ class_java_lang_ClassLoader =
+ load_class_bootstrap(utf_java_lang_ClassLoader);
- if (!(class_java_lang_SecurityManager =
- load_class_bootstrap(utf_java_lang_SecurityManager)))
- return false;
+ class_java_lang_SecurityManager =
+ load_class_bootstrap(utf_java_lang_SecurityManager);
#endif
- if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
- return false;
+ class_java_lang_System =
+ load_class_bootstrap(utf_new_char("java/lang/System"));
- if (!(class_java_lang_Thread =
- load_class_bootstrap(utf_new_char("java/lang/Thread"))))
- return false;
+ class_java_lang_Thread =
+ load_class_bootstrap(utf_new_char("java/lang/Thread"));
#if defined(ENABLE_JAVASE)
- if (!(class_java_lang_ThreadGroup =
- load_class_bootstrap(utf_java_lang_ThreadGroup)))
- return false;
+ class_java_lang_ThreadGroup =
+ load_class_bootstrap(utf_java_lang_ThreadGroup);
#endif
+ class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
+
#if defined(WITH_CLASSPATH_GNU)
- if (!(class_java_lang_VMSystem =
- load_class_bootstrap(utf_new_char("java/lang/VMSystem"))))
+ class_java_lang_VMSystem =
+ load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
- return false;
+ class_java_lang_VMThread =
+ load_class_bootstrap(utf_new_char("java/lang/VMThread"));
- if (!(class_java_lang_VMThread =
- load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
- return false;
+ class_java_lang_VMThrowable =
+ load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
#endif
-
- /* some classes which may be used more often */
+ /* Some classes which may be used often. */
#if defined(ENABLE_JAVASE)
- if (!(class_java_lang_StackTraceElement =
- load_class_bootstrap(utf_java_lang_StackTraceElement)))
- return false;
+ class_java_lang_StackTraceElement =
+ load_class_bootstrap(utf_java_lang_StackTraceElement);
- if (!(class_java_lang_reflect_Constructor =
- load_class_bootstrap(utf_java_lang_reflect_Constructor)))
- return false;
+ class_java_lang_reflect_Constructor =
+ load_class_bootstrap(utf_java_lang_reflect_Constructor);
- if (!(class_java_lang_reflect_Field =
- load_class_bootstrap(utf_java_lang_reflect_Field)))
- return false;
+ class_java_lang_reflect_Field =
+ load_class_bootstrap(utf_java_lang_reflect_Field);
- if (!(class_java_lang_reflect_Method =
- load_class_bootstrap(utf_java_lang_reflect_Method)))
- return false;
+ class_java_lang_reflect_Method =
+ load_class_bootstrap(utf_java_lang_reflect_Method);
- if (!(class_java_security_PrivilegedAction =
- load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
- return false;
+ class_java_security_PrivilegedAction =
+ load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
- if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
- return false;
+ class_java_util_HashMap =
+ load_class_bootstrap(utf_new_char("java/util/HashMap"));
+
+ class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
# if defined(WITH_CLASSPATH_SUN)
- if (!(class_sun_reflect_MagicAccessorImpl =
- load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"))))
- return false;
+ class_sun_reflect_MagicAccessorImpl =
+ load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
# endif
- if (!(arrayclass_java_lang_Object =
- load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
- return false;
+ arrayclass_java_lang_Object =
+ load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
-#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;
+ class_sun_reflect_ConstantPool =
+ load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
-#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
+ class_sun_reflect_annotation_AnnotationParser =
+ load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
+# endif
+# endif
#endif
-
-
- return true;
}
*******************************************************************************/
-classloader *loader_hashtable_classloader_add(java_objectheader *cl)
+classloader *loader_hashtable_classloader_add(java_handle_t *cl)
{
hashtable_classloader_entry *cle;
u4 key;
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(cl) >> 4;
-#else
- key = ((u4) (ptrint) cl) >> 4;
-#endif
-
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
slot = key & (hashtable_classloader->size - 1);
cle = hashtable_classloader->ptr[slot];
/* search hashchain for existing entry */
- /* XXX no GC collection is allowed here, make this a critical section */
while (cle) {
- if (cle->object == cl)
+ 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) {
#if defined(ENABLE_GC_CACAO)
/* register the classloader object with the GC */
- gc_reference_register(&(cle->object));
+ gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
#endif
- cle->object = cl;
+ LLNI_CRITICAL_START;
+
+ cle->object = LLNI_DIRECT(cl);
+
+ LLNI_CRITICAL_END;
+
+/*#define LOADER_DEBUG_CLASSLOADER*/
+#ifdef LOADER_DEBUG_CLASSLOADER
+ printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+#endif
/* insert entry into hashtable */
LOCK_MONITOR_EXIT(hashtable_classloader->header);
+#if defined(ENABLE_HANDLES)
return cle;
+#else
+ return cl;
+#endif
}
*******************************************************************************/
-classloader *loader_hashtable_classloader_find(java_objectheader *cl)
+classloader *loader_hashtable_classloader_find(java_handle_t *cl)
{
hashtable_classloader_entry *cle;
u4 key;
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(cl) >> 4;
-#else
- key = ((u4) (ptrint) cl) >> 4;
-#endif
-
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
slot = key & (hashtable_classloader->size - 1);
cle = hashtable_classloader->ptr[slot];
/* search hashchain for existing entry */
- /* XXX no GC collection is allowed here, make this a critical section */
while (cle) {
- if (cle->object == cl)
+ if (cle->object == LLNI_DIRECT(cl))
break;
cle = cle->hashlink;
}
+#ifdef LOADER_DEBUG_CLASSLOADER
+ if (cle == NULL) {
+ printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
+
+ LLNI_CRITICAL_END;
+
+#if defined(ENABLE_HANDLES)
return cle;
+#else
+ return cl;
+#endif
}
return c;
}
}
-
- assert(class_java_lang_Object);
- lc = class_resolveclassmethod(cl->object->vftbl->class,
+ LLNI_class_get(cl, c);
+
+#if defined(WITH_CLASSPATH_SUN)
+ /* OpenJDK uses this internal function because it's
+ synchronized. */
+
+ lc = class_resolveclassmethod(c,
+ utf_loadClassInternal,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+#else
+ lc = class_resolveclassmethod(c,
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* */
RT_TIMING_GET_TIME(time_prepare);
- o = vm_call_method(lc, cl->object, string);
+ o = vm_call_method(lc, (java_handle_t *) cl, string);
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
cb = suck_start(c);
if (cb == NULL) {
- /* this normally means, the classpath was not set properly */
-
- if (name == utf_java_lang_Object)
- vm_abort("java/lang/NoClassDefFoundError: java/lang/Object");
-
exceptions_throw_classnotfoundexception(name);
-
return NULL;
}
RT_TIMING_GET_TIME(time_load);
- if (!r) {
+ if (r == NULL) {
/* the class could not be loaded, free the classinfo struct */
class_free(c);
-
- } else {
+ }
+ else {
/* Store this class in the loaded class cache this step also
- checks the loading constraints. If the class has been loaded
- before, the earlier loaded class is returned. */
+ checks the loading constraints. If the class has been
+ loaded before, the earlier loaded class is returned. */
classinfo *res = classcache_store(NULL, c, true);
- if (!res) {
+ if (res == NULL) {
/* exception */
class_free(c);
}
+ else {
+ /* Add the package name to the boot packages. */
+
+ package_add(c->packagename);
+ }
r = res;
}
}
-/* 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;
+ classinfo *c;
+ classinfo *tc;
+ utf *name;
+ utf *supername;
+ utf **interfacesnames;
+ utf *u;
+ constant_classref *cr;
+ int16_t index;
+
u4 i,j;
u4 ma, mi;
- s4 dumpsize;
descriptor_pool *descpool;
#if defined(ENABLE_STATISTICS)
u4 classrefsize;
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 */
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);
/* 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. */
exceptions_throw_classformaterror(c,
"Illegal class modifiers: 0x%X",
c->flags);
- goto return_exception;
+ return false;
}
if (c->flags & ACC_SUPER) {
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 */
+ /* This class. */
- i = suck_u2(cb);
+ index = suck_u2(cb);
- if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
- goto return_exception;
+ name = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (name == NULL)
+ return false;
if (c->name == utf_not_named_yet) {
/* we finally have a name for this class */
}
else if (name != c->name) {
exceptions_throw_noclassdeffounderror_wrong_name(c, name);
- goto return_exception;
+ return false;
}
- /* retrieve superclass */
+ /* Retrieve superclass. */
+
+ c->super = NULL;
+
+ index = suck_u2(cb);
- c->super.any = NULL;
+ if (index == 0) {
+ supername = NULL;
- if ((i = suck_u2(cb))) {
- if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
- goto return_exception;
+ /* This is only allowed for java.lang.Object. */
+
+ if (c->name != utf_java_lang_Object) {
+ exceptions_throw_classformaterror(c, "Bad superclass index");
+ return false;
+ }
+ }
+ else {
+ supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (supername == NULL)
+ 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. */
+ /* Detect circularity. */
- 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;
+ if (supername == c->name) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
}
- } else {
- supername = NULL;
-
- /* This is only allowed for java.lang.Object. */
+ /* Interfaces must have java.lang.Object as super class. */
- if (c->name != utf_java_lang_Object) {
- exceptions_throw_classformaterror(c, "Bad superclass index");
- goto return_exception;
+ if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
+ exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
+ return false;
}
}
- /* retrieve interfaces */
+ /* Parse the super 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(classinfo*, c->interfacescount);
+
+ /* Get the names of the super interfaces. */
+
+ interfacesnames = DMNEW(utf*, c->interfacescount);
- 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;
+ index = suck_u2(cb);
+
+ u = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (u == NULL)
+ return false;
+
+ interfacesnames[i] = u;
}
RT_TIMING_GET_TIME(time_setup);
- /* load fields */
+ /* Parse fields. */
if (!suck_check_classbuffer_size(cb, 2))
- goto return_exception;
+ return false;
c->fieldscount = suck_u2(cb);
c->fields = MNEW(fieldinfo, c->fieldscount);
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 */
+ /* Parse methods. */
if (!suck_check_classbuffer_size(cb, 2))
- goto return_exception;
+ return false;
c->methodscount = suck_u2(cb);
c->methods = MNEW(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);
RT_TIMING_GET_TIME(time_descs);
/* put the classrefs in the constant pool */
+
for (i = 0; i < c->cpcount; i++) {
if (c->cptags[i] == CONSTANT_Class) {
utf *name = (utf *) c->cpinfos[i];
}
}
- /* set the super class reference */
+ /* Resolve the super class. */
+
+ if (supername != NULL) {
+ cr = descriptor_pool_lookup_classref(descpool, supername);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL)
+ return false;
+
+ /* Interfaces are not allowed as super classes. */
+
+ if (tc->flags & ACC_INTERFACE) {
+ exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
+ return false;
+ }
+
+ /* Don't allow extending final classes */
+
+ if (tc->flags & ACC_FINAL) {
+ exceptions_throw_verifyerror(NULL,
+ "Cannot inherit from final class");
+ return false;
+ }
+
+ /* Store the super class. */
- if (supername) {
- c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
- if (!c->super.ref)
- goto return_exception;
+ c->super = tc;
}
- /* set the super interfaces references */
+ /* Resolve the super interfaces. */
for (i = 0; i < c->interfacescount; i++) {
- c->interfaces[i].ref =
- descriptor_pool_lookup_classref(descpool,
- (utf *) c->interfaces[i].any);
- if (!c->interfaces[i].ref)
- goto return_exception;
+ u = interfacesnames[i];
+ cr = descriptor_pool_lookup_classref(descpool, u);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL)
+ return false;
+
+ /* Detect circularity. */
+
+ if (tc == c) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
+ }
+
+ if (!(tc->flags & ACC_INTERFACE)) {
+ exceptions_throw_incompatibleclasschangeerror(tc,
+ "Implementing class");
+ return false;
+ }
+
+ /* Store the super interface. */
+
+ c->interfaces[i] = tc;
}
RT_TIMING_GET_TIME(time_setrefs);
- /* parse field descriptors */
+ /* Parse the field descriptors. */
for (i = 0; i < c->fieldscount; i++) {
c->fields[i].parseddesc =
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);
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;
}
}
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:
(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;
}
}
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]));
}
index = ((((size_t) mi->name) +
((size_t) mi->descriptor)) >> shift) % hashlen;
- /*{ JOWENN
- int dbg;
- for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
- printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
- }
- }*/
-
if ((old = hashtab[index])) {
old--;
next[i] = old;
if (c->methods[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]));
}
/* 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 */
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);
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;
-return_exception:
- /* release dump area */
+ /* 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();
+
+ /* 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. */
+
+ if (result == false) {
+ /* Revert loading state. */
+
+ c->state = (c->state & ~CLASS_LOADING);
+
+ return NULL;
+ }
+
+ /* Revert loading state and set loaded. */
- return NULL;
+ 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;
}
assert(class_java_io_Serializable);
#endif
- /* setup the array class */
+ /* Setup the array class. */
- c->super.cls = class_java_lang_Object;
+ c->super = class_java_lang_Object;
#if defined(ENABLE_JAVASE)
- c->interfacescount = 2;
- c->interfaces = MNEW(classref_or_classinfo, 2);
- c->interfaces[0].cls = class_java_lang_Cloneable;
- c->interfaces[1].cls = class_java_io_Serializable;
+ c->interfacescount = 2;
+ c->interfaces = MNEW(classinfo*, 2);
+ c->interfaces[0] = class_java_lang_Cloneable;
+ c->interfaces[1] = class_java_io_Serializable;
#elif defined(ENABLE_JAVAME_CLDC1_1)
- c->interfacescount = 0;
- c->interfaces = NULL;
+ c->interfacescount = 0;
+ c->interfaces = NULL;
#else
# error unknow Java configuration
#endif
c->methodscount = 1;
- c->methods = MNEW(methodinfo, c->methodscount);
+ c->methods = MNEW(methodinfo, c->methodscount);
+
MZERO(c->methods, methodinfo, c->methodscount);
classrefs = MNEW(constant_classref, 2);
+
CLASSREF_INIT(classrefs[0], c, c->name);
CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);