1 /* src/vmcore/loader.c - class loader functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "mm/memory.h"
36 #include "native/llni.h"
38 #include "threads/lock-common.h"
40 #include "toolbox/hashtable.h"
41 #include "toolbox/logging.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/global.h"
46 #include "vm/package.h"
47 #include "vm/primitive.h"
48 #include "vm/resolve.h"
49 #include "vm/stringlocal.h"
52 #include "vm/jit_interface.h"
54 #if defined(ENABLE_JAVASE)
55 # include "vmcore/annotation.h"
56 # include "vmcore/stackmap.h"
59 #include "vmcore/classcache.h"
60 #include "vmcore/field.h"
61 #include "vmcore/linker.h"
62 #include "vmcore/loader.h"
63 #include "vmcore/method.h"
64 #include "vmcore/options.h"
65 #include "vmcore/rt-timing.h"
67 #if defined(ENABLE_STATISTICS)
68 # include "vmcore/statistics.h"
71 #include "vmcore/suck.h"
73 #if defined(ENABLE_ZLIB)
74 # include "vmcore/zip.h"
77 #if defined(ENABLE_JVMTI)
78 # include "native/jvmti/cacaodbg.h"
82 /* global variables ***********************************************************/
84 static hashtable *hashtable_classloader;
87 /* loader_preinit **************************************************************
89 Initializes the classpath list and loads classes required for the
92 NOTE: Exceptions thrown during VM initialization are caught in the
93 exception functions themselves.
95 *******************************************************************************/
97 void loader_preinit(void)
99 #if defined(ENABLE_THREADS)
100 list_classpath_entry *lce;
103 TRACESUBSYSTEMINITIALIZATION("loader_preinit");
105 #if defined(ENABLE_THREADS)
106 /* Initialize the monitor pointer for zip/jar file locking. */
108 for (lce = list_first(list_classpath_entries); lce != NULL;
109 lce = list_next(list_classpath_entries, lce)) {
110 if (lce->type == CLASSPATH_ARCHIVE)
111 LOCK_INIT_OBJECT_LOCK(lce);
115 /* initialize classloader hashtable, 10 entries should be enough */
117 hashtable_classloader = NEW(hashtable);
118 hashtable_create(hashtable_classloader, 10);
120 /* Load the most basic classes. */
122 assert(vm_initializing == true);
124 class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
126 #if defined(ENABLE_JAVASE)
127 class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
128 class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
133 /* loader_init *****************************************************************
135 Loads all classes required in the VM.
137 NOTE: Exceptions thrown during VM initialization are caught in the
138 exception functions themselves.
140 *******************************************************************************/
142 void loader_init(void)
144 TRACESUBSYSTEMINITIALIZATION("loader_init");
146 /* Load primitive-type wrapping classes. */
148 assert(vm_initializing == true);
150 #if defined(ENABLE_JAVASE)
151 class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
154 class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
155 class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
156 class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
157 class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
158 class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
159 class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
160 class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
161 class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
163 /* Load important system classes. */
165 class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
166 class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
168 #if defined(ENABLE_JAVASE)
169 class_java_lang_ClassLoader =
170 load_class_bootstrap(utf_java_lang_ClassLoader);
172 class_java_lang_SecurityManager =
173 load_class_bootstrap(utf_java_lang_SecurityManager);
176 class_java_lang_System =
177 load_class_bootstrap(utf_new_char("java/lang/System"));
179 class_java_lang_Thread =
180 load_class_bootstrap(utf_new_char("java/lang/Thread"));
182 #if defined(ENABLE_JAVASE)
183 class_java_lang_ThreadGroup =
184 load_class_bootstrap(utf_java_lang_ThreadGroup);
187 class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
189 #if defined(WITH_CLASSPATH_GNU)
190 class_java_lang_VMSystem =
191 load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
193 class_java_lang_VMThread =
194 load_class_bootstrap(utf_new_char("java/lang/VMThread"));
196 class_java_lang_VMThrowable =
197 load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
200 /* Important system exceptions. */
202 class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
204 class_java_lang_ClassNotFoundException =
205 load_class_bootstrap(utf_java_lang_ClassNotFoundException);
207 class_java_lang_RuntimeException =
208 load_class_bootstrap(utf_java_lang_RuntimeException);
210 /* Some classes which may be used often. */
212 #if defined(ENABLE_JAVASE)
213 class_java_lang_StackTraceElement =
214 load_class_bootstrap(utf_java_lang_StackTraceElement);
216 class_java_lang_reflect_Constructor =
217 load_class_bootstrap(utf_java_lang_reflect_Constructor);
219 class_java_lang_reflect_Field =
220 load_class_bootstrap(utf_java_lang_reflect_Field);
222 class_java_lang_reflect_Method =
223 load_class_bootstrap(utf_java_lang_reflect_Method);
225 class_java_security_PrivilegedAction =
226 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
228 class_java_util_HashMap =
229 load_class_bootstrap(utf_new_char("java/util/HashMap"));
231 class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
233 # if defined(WITH_CLASSPATH_SUN)
234 class_sun_reflect_MagicAccessorImpl =
235 load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
238 arrayclass_java_lang_Object =
239 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
241 # if defined(ENABLE_ANNOTATIONS)
242 /* needed by annotation support */
243 class_sun_reflect_ConstantPool =
244 load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
246 # if defined(WITH_CLASSPATH_GNU)
247 /* needed by GNU Classpaths annotation support */
248 class_sun_reflect_annotation_AnnotationParser =
249 load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
256 /* loader_hashtable_classloader_add ********************************************
258 Adds an entry to the classloader hashtable.
260 REMEMBER: Also use this to register native loaders!
262 *******************************************************************************/
264 classloader *loader_hashtable_classloader_add(java_handle_t *cl)
266 hashtable_classloader_entry *cle;
273 LOCK_MONITOR_ENTER(hashtable_classloader->header);
277 /* key for entry is the hashcode of the classloader;
278 aligned to 16-byte boundaries */
280 key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
281 slot = key & (hashtable_classloader->size - 1);
282 cle = hashtable_classloader->ptr[slot];
284 /* search hashchain for existing entry */
287 if (cle->object == LLNI_DIRECT(cl))
295 /* if no classloader was found, we create a new entry here */
298 cle = NEW(hashtable_classloader_entry);
300 #if defined(ENABLE_GC_CACAO)
301 /* register the classloader object with the GC */
303 gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
308 cle->object = LLNI_DIRECT(cl);
312 /*#define LOADER_DEBUG_CLASSLOADER*/
313 #ifdef LOADER_DEBUG_CLASSLOADER
314 printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
315 class_print(LLNI_vftbl_direct(cl)->class);
320 /* insert entry into hashtable */
322 cle->hashlink = hashtable_classloader->ptr[slot];
323 hashtable_classloader->ptr[slot] = cle;
325 /* update number of entries */
327 hashtable_classloader->entries++;
331 LOCK_MONITOR_EXIT(hashtable_classloader->header);
333 #if defined(ENABLE_HANDLES)
341 /* loader_hashtable_classloader_find *******************************************
343 Find an entry in the classloader hashtable.
345 *******************************************************************************/
347 classloader *loader_hashtable_classloader_find(java_handle_t *cl)
349 hashtable_classloader_entry *cle;
358 /* key for entry is the hashcode of the classloader;
359 aligned to 16-byte boundaries */
361 key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
362 slot = key & (hashtable_classloader->size - 1);
363 cle = hashtable_classloader->ptr[slot];
365 /* search hashchain for existing entry */
368 if (cle->object == LLNI_DIRECT(cl))
374 #ifdef LOADER_DEBUG_CLASSLOADER
376 printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
377 class_print(LLNI_vftbl_direct(cl)->class);
385 #if defined(ENABLE_HANDLES)
393 /* loader_load_all_classes *****************************************************
395 Loads all classes specified in the BOOTCLASSPATH.
397 *******************************************************************************/
399 void loader_load_all_classes(void)
401 list_classpath_entry *lce;
402 #if defined(ENABLE_ZLIB)
405 hashtable_zipfile_entry *htzfe;
409 for (lce = list_first(list_classpath_entries); lce != NULL;
410 lce = list_next(list_classpath_entries, lce)) {
411 #if defined(ENABLE_ZLIB)
412 if (lce->type == CLASSPATH_ARCHIVE) {
413 /* get the classes hashtable */
417 for (slot = 0; slot < ht->size; slot++) {
418 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
420 for (; htzfe; htzfe = htzfe->hashlink) {
423 /* skip all entries in META-INF and .properties,
426 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
427 strstr(u->text, ".properties") ||
428 strstr(u->text, ".png"))
431 /* load class from bootstrap classloader */
433 if (!load_class_bootstrap(u)) {
434 fprintf(stderr, "Error loading: ");
435 utf_fprint_printable_ascii_classname(stderr, u);
436 fprintf(stderr, "\n");
439 /* print out exception and cause */
441 exceptions_print_current_exception();
449 #if defined(ENABLE_ZLIB)
456 /* loader_skip_attribute_body **************************************************
458 Skips an attribute the attribute_name_index has already been read.
461 u2 attribute_name_index;
463 u1 info[attribute_length];
466 *******************************************************************************/
468 bool loader_skip_attribute_body(classbuffer *cb)
472 if (!suck_check_classbuffer_size(cb, 4))
475 attribute_length = suck_u4(cb);
477 if (!suck_check_classbuffer_size(cb, attribute_length))
480 suck_skip_nbytes(cb, attribute_length);
486 /* load_constantpool ***********************************************************
488 Loads the constantpool of a class, the entries are transformed into
489 a simpler format by resolving references (a detailed overview of
490 the compact structures can be found in global.h).
492 *******************************************************************************/
494 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
497 /* The following structures are used to save information which cannot be
498 processed during the first pass. After the complete constantpool has
499 been traversed the references can be resolved.
500 (only in specific order) */
502 /* CONSTANT_Class entries */
503 typedef struct forward_class {
504 struct forward_class *next;
509 /* CONSTANT_String */
510 typedef struct forward_string {
511 struct forward_string *next;
516 /* CONSTANT_NameAndType */
517 typedef struct forward_nameandtype {
518 struct forward_nameandtype *next;
522 } forward_nameandtype;
524 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
525 typedef struct forward_fieldmethint {
526 struct forward_fieldmethint *next;
530 u2 nameandtype_index;
531 } forward_fieldmethint;
537 forward_class *forward_classes = NULL;
538 forward_string *forward_strings = NULL;
539 forward_nameandtype *forward_nameandtypes = NULL;
540 forward_fieldmethint *forward_fieldmethints = NULL;
544 forward_nameandtype *nfn;
545 forward_fieldmethint *nff;
553 /* number of entries in the constant_pool table plus one */
554 if (!suck_check_classbuffer_size(cb, 2))
557 cpcount = c->cpcount = suck_u2(cb);
559 /* allocate memory */
560 cptags = c->cptags = MNEW(u1, cpcount);
561 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
564 exceptions_throw_classformaterror(c, "Illegal constant pool size");
568 #if defined(ENABLE_STATISTICS)
570 count_const_pool_len += (sizeof(u1) + sizeof(voidptr)) * cpcount;
573 /* initialize constantpool */
574 for (idx = 0; idx < cpcount; idx++) {
575 cptags[idx] = CONSTANT_UNUSED;
580 /******* first pass *******/
581 /* entries which cannot be resolved now are written into
582 temporary structures and traversed again later */
585 while (idx < cpcount) {
588 /* get constant type */
589 if (!suck_check_classbuffer_size(cb, 1))
596 nfc = DNEW(forward_class);
598 nfc->next = forward_classes;
599 forward_classes = nfc;
601 nfc->thisindex = idx;
602 /* reference to CONSTANT_NameAndType */
603 if (!suck_check_classbuffer_size(cb, 2))
606 nfc->name_index = suck_u2(cb);
611 case CONSTANT_String:
612 nfs = DNEW(forward_string);
614 nfs->next = forward_strings;
615 forward_strings = nfs;
617 nfs->thisindex = idx;
619 /* reference to CONSTANT_Utf8_info with string characters */
620 if (!suck_check_classbuffer_size(cb, 2))
623 nfs->string_index = suck_u2(cb);
628 case CONSTANT_NameAndType:
629 nfn = DNEW(forward_nameandtype);
631 nfn->next = forward_nameandtypes;
632 forward_nameandtypes = nfn;
634 nfn->thisindex = idx;
636 if (!suck_check_classbuffer_size(cb, 2 + 2))
639 /* reference to CONSTANT_Utf8_info containing simple name */
640 nfn->name_index = suck_u2(cb);
642 /* reference to CONSTANT_Utf8_info containing field or method
644 nfn->sig_index = suck_u2(cb);
649 case CONSTANT_Fieldref:
650 case CONSTANT_Methodref:
651 case CONSTANT_InterfaceMethodref:
652 nff = DNEW(forward_fieldmethint);
654 nff->next = forward_fieldmethints;
655 forward_fieldmethints = nff;
657 nff->thisindex = idx;
661 if (!suck_check_classbuffer_size(cb, 2 + 2))
664 /* class or interface type that contains the declaration of the
666 nff->class_index = suck_u2(cb);
668 /* name and descriptor of the field or method */
669 nff->nameandtype_index = suck_u2(cb);
674 case CONSTANT_Integer: {
675 constant_integer *ci = NEW(constant_integer);
677 #if defined(ENABLE_STATISTICS)
679 count_const_pool_len += sizeof(constant_integer);
682 if (!suck_check_classbuffer_size(cb, 4))
685 ci->value = suck_s4(cb);
686 cptags[idx] = CONSTANT_Integer;
693 case CONSTANT_Float: {
694 constant_float *cf = NEW(constant_float);
696 #if defined(ENABLE_STATISTICS)
698 count_const_pool_len += sizeof(constant_float);
701 if (!suck_check_classbuffer_size(cb, 4))
704 cf->value = suck_float(cb);
705 cptags[idx] = CONSTANT_Float;
712 case CONSTANT_Long: {
713 constant_long *cl = NEW(constant_long);
715 #if defined(ENABLE_STATISTICS)
717 count_const_pool_len += sizeof(constant_long);
720 if (!suck_check_classbuffer_size(cb, 8))
723 cl->value = suck_s8(cb);
724 cptags[idx] = CONSTANT_Long;
728 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
734 case CONSTANT_Double: {
735 constant_double *cd = NEW(constant_double);
737 #if defined(ENABLE_STATISTICS)
739 count_const_pool_len += sizeof(constant_double);
742 if (!suck_check_classbuffer_size(cb, 8))
745 cd->value = suck_double(cb);
746 cptags[idx] = CONSTANT_Double;
750 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
756 case CONSTANT_Utf8: {
759 /* number of bytes in the bytes array (not string-length) */
760 if (!suck_check_classbuffer_size(cb, 2))
763 length = suck_u2(cb);
764 cptags[idx] = CONSTANT_Utf8;
766 /* validate the string */
767 if (!suck_check_classbuffer_size(cb, length))
770 #ifdef ENABLE_VERIFIER
772 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
774 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
777 #endif /* ENABLE_VERIFIER */
778 /* insert utf-string into the utf-symboltable */
779 cpinfos[idx] = utf_new((char *) cb->pos, length);
781 /* skip bytes of the string (buffer size check above) */
782 suck_skip_nbytes(cb, length);
788 exceptions_throw_classformaterror(c, "Illegal constant pool type");
794 /* resolve entries in temporary structures */
796 while (forward_classes) {
798 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
802 #ifdef ENABLE_VERIFIER
803 if (opt_verify && !is_valid_name_utf(name)) {
804 exceptions_throw_classformaterror(c, "Class reference with invalid name");
807 #endif /* ENABLE_VERIFIER */
809 /* add all class references to the descriptor_pool */
811 if (!descriptor_pool_add_class(descpool, name))
814 cptags[forward_classes->thisindex] = CONSTANT_Class;
816 /* the classref is created later */
817 cpinfos[forward_classes->thisindex] = name;
819 nfc = forward_classes;
820 forward_classes = forward_classes->next;
823 while (forward_strings) {
825 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
829 /* resolve utf-string */
830 cptags[forward_strings->thisindex] = CONSTANT_String;
831 cpinfos[forward_strings->thisindex] = text;
833 nfs = forward_strings;
834 forward_strings = forward_strings->next;
837 while (forward_nameandtypes) {
838 constant_nameandtype *cn = NEW(constant_nameandtype);
840 #if defined(ENABLE_STATISTICS)
842 count_const_pool_len += sizeof(constant_nameandtype);
845 /* resolve simple name and descriptor */
846 cn->name = class_getconstant(c,
847 forward_nameandtypes->name_index,
852 cn->descriptor = class_getconstant(c,
853 forward_nameandtypes->sig_index,
858 #ifdef ENABLE_VERIFIER
861 if (!is_valid_name_utf(cn->name)) {
862 exceptions_throw_classformaterror(c,
863 "Illegal Field name \"%s\"",
869 /* disallow referencing <clinit> among others */
870 if (cn->name->text[0] == '<' && cn->name != utf_init) {
871 exceptions_throw_classformaterror(c, "Illegal reference to special method");
875 #endif /* ENABLE_VERIFIER */
877 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
878 cpinfos[forward_nameandtypes->thisindex] = cn;
880 nfn = forward_nameandtypes;
881 forward_nameandtypes = forward_nameandtypes->next;
884 while (forward_fieldmethints) {
885 constant_nameandtype *nat;
886 constant_FMIref *fmi = NEW(constant_FMIref);
888 #if defined(ENABLE_STATISTICS)
890 count_const_pool_len += sizeof(constant_FMIref);
892 /* resolve simple name and descriptor */
894 nat = class_getconstant(c,
895 forward_fieldmethints->nameandtype_index,
896 CONSTANT_NameAndType);
900 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
902 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
905 /* the classref is created later */
907 fmi->p.index = forward_fieldmethints->class_index;
908 fmi->name = nat->name;
909 fmi->descriptor = nat->descriptor;
911 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
912 cpinfos[forward_fieldmethints->thisindex] = fmi;
914 nff = forward_fieldmethints;
915 forward_fieldmethints = forward_fieldmethints->next;
918 /* everything was ok */
924 /* loader_load_attribute_signature *********************************************
926 Signature_attribute {
927 u2 attribute_name_index;
932 *******************************************************************************/
934 #if defined(ENABLE_JAVASE)
935 bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
945 /* check remaining bytecode */
947 if (!suck_check_classbuffer_size(cb, 4 + 2))
950 /* check attribute length */
952 attribute_length = suck_u4(cb);
954 if (attribute_length != 2) {
955 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
959 if (*signature != NULL) {
960 exceptions_throw_classformaterror(c, "Multiple Signature attributes");
966 signature_index = suck_u2(cb);
968 if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
973 #endif /* defined(ENABLE_JAVASE) */
976 /* load_class_from_sysloader ***************************************************
978 Load the class with the given name using the system class loader
981 name.............the classname
985 NULL if an exception has been thrown
987 *******************************************************************************/
989 classinfo *load_class_from_sysloader(utf *name)
996 assert(class_java_lang_Object);
997 assert(class_java_lang_ClassLoader);
998 assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
1000 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1001 utf_getSystemClassLoader,
1002 utf_void__java_lang_ClassLoader,
1003 class_java_lang_Object,
1009 clo = vm_call_method(m, NULL);
1014 cl = loader_hashtable_classloader_add(clo);
1016 c = load_class_from_classloader(name, cl);
1022 /* load_class_from_classloader *************************************************
1024 Load the class with the given name using the given user-defined class loader.
1027 name.............the classname
1028 cl...............user-defined class loader
1031 the loaded class, or
1032 NULL if an exception has been thrown
1034 *******************************************************************************/
1036 classinfo *load_class_from_classloader(utf *name, classloader *cl)
1041 java_handle_t *string;
1042 #if defined(ENABLE_RT_TIMING)
1043 struct timespec time_start, time_lookup, time_prepare, time_java,
1047 RT_TIMING_GET_TIME(time_start);
1051 /* lookup if this class has already been loaded */
1053 c = classcache_lookup(cl, name);
1055 RT_TIMING_GET_TIME(time_lookup);
1056 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
1061 /* if other class loader than bootstrap, call it */
1069 namelen = name->blength;
1071 /* handle array classes */
1072 if (text[0] == '[') {
1078 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1079 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1080 exceptions_throw_classnotfoundexception(name);
1084 u = utf_new(text + 2, namelen - 3);
1086 if (!(comp = load_class_from_classloader(u, cl)))
1089 /* create the array class */
1091 c = class_array_of(comp, false);
1093 tmpc = classcache_store(cl, c, true);
1096 /* exception, free the loaded class */
1097 c->state &= ~CLASS_LOADING;
1104 /* load the component class */
1106 u = utf_new(text + 1, namelen - 1);
1108 if (!(comp = load_class_from_classloader(u, cl)))
1111 /* create the array class */
1113 c = class_array_of(comp, false);
1115 tmpc = classcache_store(cl, c, true);
1118 /* exception, free the loaded class */
1119 c->state &= ~CLASS_LOADING;
1126 /* primitive array classes are loaded by the bootstrap loader */
1128 c = load_class_bootstrap(name);
1134 LLNI_class_get(cl, c);
1136 #if defined(WITH_CLASSPATH_SUN)
1137 /* OpenJDK uses this internal function because it's
1140 lc = class_resolveclassmethod(c,
1141 utf_loadClassInternal,
1142 utf_java_lang_String__java_lang_Class,
1146 lc = class_resolveclassmethod(c,
1148 utf_java_lang_String__java_lang_Class,
1154 return false; /* exception */
1156 /* move return value into `o' and cast it afterwards to a classinfo* */
1158 string = javastring_new_slash_to_dot(name);
1160 RT_TIMING_GET_TIME(time_prepare);
1162 o = vm_call_method(lc, (java_handle_t *) cl, string);
1164 RT_TIMING_GET_TIME(time_java);
1166 c = LLNI_classinfo_unwrap(o);
1169 /* Store this class in the loaded class cache. If another
1170 class with the same (initloader,name) pair has been
1171 stored earlier it will be returned by classcache_store
1172 In this case classcache_store may not free the class
1173 because it has already been exposed to Java code which
1174 may have kept references to that class. */
1176 tmpc = classcache_store(cl, c, false);
1179 /* exception, free the loaded class */
1180 c->state &= ~CLASS_LOADING;
1187 RT_TIMING_GET_TIME(time_cache);
1189 RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
1190 RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
1191 RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
1193 /* SUN compatible -verbose:class output */
1195 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1197 utf_display_printable_ascii_classname(name);
1201 #if defined(ENABLE_JVMTI)
1202 /* fire Class Load JVMTI event */
1203 if (jvmti) jvmti_ClassLoadPrepare(false, c);
1210 c = load_class_bootstrap(name);
1216 /* load_class_bootstrap ********************************************************
1218 Load the class with the given name using the bootstrap class loader.
1221 name.............the classname
1224 loaded classinfo, or
1225 NULL if an exception has been thrown
1228 load_class_bootstrap is synchronized. It can be treated as an
1231 *******************************************************************************/
1233 classinfo *load_class_bootstrap(utf *name)
1238 #if defined(ENABLE_RT_TIMING)
1239 struct timespec time_start, time_lookup, time_array, time_suck,
1240 time_load, time_cache;
1243 RT_TIMING_GET_TIME(time_start);
1249 /* lookup if this class has already been loaded */
1251 r = classcache_lookup(NULL, name);
1254 RT_TIMING_GET_TIME(time_lookup);
1255 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1260 RT_TIMING_GET_TIME(time_lookup);
1261 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1263 /* create the classinfo */
1265 c = class_create_classinfo(name);
1267 /* handle array classes */
1269 if (name->text[0] == '[') {
1270 c = load_newly_created_array(c, NULL);
1275 assert(c->state & CLASS_LOADED);
1277 RT_TIMING_GET_TIME(time_array);
1278 RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
1283 #if defined(ENABLE_STATISTICS)
1286 if (opt_getcompilingtime)
1287 compilingtime_stop();
1289 if (opt_getloadingtime)
1290 loadingtime_start();
1293 /* load classdata, throw exception on error */
1298 exceptions_throw_classnotfoundexception(name);
1302 RT_TIMING_GET_TIME(time_suck);
1304 /* load the class from the buffer */
1306 r = load_class_from_classbuffer(cb);
1308 RT_TIMING_GET_TIME(time_load);
1311 /* the class could not be loaded, free the classinfo struct */
1316 /* Store this class in the loaded class cache this step also
1317 checks the loading constraints. If the class has been
1318 loaded before, the earlier loaded class is returned. */
1320 classinfo *res = classcache_store(NULL, c, true);
1327 /* Add the package name to the boot packages. */
1329 package_add(c->packagename);
1335 RT_TIMING_GET_TIME(time_cache);
1337 /* SUN compatible -verbose:class output */
1339 if (opt_verboseclass && r) {
1341 utf_display_printable_ascii_classname(name);
1342 printf(" from %s]\n", cb->path);
1349 #if defined(ENABLE_STATISTICS)
1352 if (opt_getloadingtime)
1355 if (opt_getcompilingtime)
1356 compilingtime_start();
1359 RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
1360 RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
1361 RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
1362 RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
1368 /* load_class_from_classbuffer_intern ******************************************
1370 Loads a class from a classbuffer into a given classinfo structure.
1371 Super-classes are also loaded at this point and some verfication
1375 This function is NOT synchronized!
1377 *******************************************************************************/
1379 static bool load_class_from_classbuffer_intern(classbuffer *cb)
1385 utf **interfacesnames;
1387 constant_classref *cr;
1392 descriptor_pool *descpool;
1393 #if defined(ENABLE_STATISTICS)
1397 #if defined(ENABLE_RT_TIMING)
1398 struct timespec time_start, time_checks, time_ndpool, time_cpool,
1399 time_setup, time_fields, time_methods, time_classrefs,
1400 time_descs, time_setrefs, time_parsefds, time_parsemds,
1401 time_parsecpool, time_verify, time_attrs;
1404 RT_TIMING_GET_TIME(time_start);
1406 /* Get the classbuffer's class. */
1410 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1413 /* check signature */
1415 if (suck_u4(cb) != MAGIC) {
1416 exceptions_throw_classformaterror(c, "Bad magic number");
1425 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1426 exceptions_throw_unsupportedclassversionerror(c, ma, mi);
1430 RT_TIMING_GET_TIME(time_checks);
1432 /* create a new descriptor pool */
1434 descpool = descriptor_pool_new(c);
1436 RT_TIMING_GET_TIME(time_ndpool);
1438 /* load the constant pool */
1440 if (!load_constantpool(cb, descpool))
1443 RT_TIMING_GET_TIME(time_cpool);
1447 if (!suck_check_classbuffer_size(cb, 2))
1450 /* We OR the flags here, as we set already some flags in
1451 class_create_classinfo. */
1453 c->flags |= suck_u2(cb);
1455 /* check ACC flags consistency */
1457 if (c->flags & ACC_INTERFACE) {
1458 if (!(c->flags & ACC_ABSTRACT)) {
1459 /* We work around this because interfaces in JDK 1.1 are
1460 * not declared abstract. */
1462 c->flags |= ACC_ABSTRACT;
1465 if (c->flags & ACC_FINAL) {
1466 exceptions_throw_classformaterror(c,
1467 "Illegal class modifiers: 0x%X",
1472 if (c->flags & ACC_SUPER) {
1473 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1477 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1478 exceptions_throw_classformaterror(c,
1479 "Illegal class modifiers: 0x%X",
1484 if (!suck_check_classbuffer_size(cb, 2 + 2))
1489 index = suck_u2(cb);
1491 name = (utf *) class_getconstant(c, index, CONSTANT_Class);
1496 if (c->name == utf_not_named_yet) {
1497 /* we finally have a name for this class */
1499 class_set_packagename(c);
1501 else if (name != c->name) {
1502 exceptions_throw_noclassdeffounderror_wrong_name(c, name);
1506 /* Retrieve superclass. */
1510 index = suck_u2(cb);
1515 /* This is only allowed for java.lang.Object. */
1517 if (c->name != utf_java_lang_Object) {
1518 exceptions_throw_classformaterror(c, "Bad superclass index");
1523 supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
1525 if (supername == NULL)
1528 /* java.lang.Object may not have a super class. */
1530 if (c->name == utf_java_lang_Object) {
1531 exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
1535 /* Detect circularity. */
1537 if (supername == c->name) {
1538 exceptions_throw_classcircularityerror(c);
1542 /* Interfaces must have java.lang.Object as super class. */
1544 if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
1545 exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
1550 /* Parse the super interfaces. */
1552 if (!suck_check_classbuffer_size(cb, 2))
1555 c->interfacescount = suck_u2(cb);
1557 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1560 c->interfaces = MNEW(classinfo*, c->interfacescount);
1562 /* Get the names of the super interfaces. */
1564 interfacesnames = DMNEW(utf*, c->interfacescount);
1566 for (i = 0; i < c->interfacescount; i++) {
1567 index = suck_u2(cb);
1569 u = (utf *) class_getconstant(c, index, CONSTANT_Class);
1574 interfacesnames[i] = u;
1577 RT_TIMING_GET_TIME(time_setup);
1581 if (!suck_check_classbuffer_size(cb, 2))
1584 c->fieldscount = suck_u2(cb);
1585 c->fields = MNEW(fieldinfo, c->fieldscount);
1587 MZERO(c->fields, fieldinfo, c->fieldscount);
1589 for (i = 0; i < c->fieldscount; i++) {
1590 if (!field_load(cb, &(c->fields[i]), descpool))
1594 RT_TIMING_GET_TIME(time_fields);
1596 /* Parse methods. */
1598 if (!suck_check_classbuffer_size(cb, 2))
1601 c->methodscount = suck_u2(cb);
1602 c->methods = MNEW(methodinfo, c->methodscount);
1604 MZERO(c->methods, methodinfo, c->methodscount);
1606 for (i = 0; i < c->methodscount; i++) {
1607 if (!method_load(cb, &(c->methods[i]), descpool))
1611 RT_TIMING_GET_TIME(time_methods);
1613 /* create the class reference table */
1616 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
1618 RT_TIMING_GET_TIME(time_classrefs);
1620 /* allocate space for the parsed descriptors */
1622 descriptor_pool_alloc_parsed_descriptors(descpool);
1624 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
1626 #if defined(ENABLE_STATISTICS)
1628 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
1629 count_classref_len += classrefsize;
1630 count_parsed_desc_len += descsize;
1634 RT_TIMING_GET_TIME(time_descs);
1636 /* put the classrefs in the constant pool */
1638 for (i = 0; i < c->cpcount; i++) {
1639 if (c->cptags[i] == CONSTANT_Class) {
1640 utf *name = (utf *) c->cpinfos[i];
1641 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
1645 /* Resolve the super class. */
1647 if (supername != NULL) {
1648 cr = descriptor_pool_lookup_classref(descpool, supername);
1653 /* XXX This should be done better. */
1654 tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
1657 resolve_handle_pending_exception(true);
1661 /* Interfaces are not allowed as super classes. */
1663 if (tc->flags & ACC_INTERFACE) {
1664 exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
1668 /* Don't allow extending final classes */
1670 if (tc->flags & ACC_FINAL) {
1671 exceptions_throw_verifyerror(NULL,
1672 "Cannot inherit from final class");
1676 /* Store the super class. */
1681 /* Resolve the super interfaces. */
1683 for (i = 0; i < c->interfacescount; i++) {
1684 u = interfacesnames[i];
1685 cr = descriptor_pool_lookup_classref(descpool, u);
1690 /* XXX This should be done better. */
1691 tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
1696 /* Detect circularity. */
1699 exceptions_throw_classcircularityerror(c);
1703 if (!(tc->flags & ACC_INTERFACE)) {
1704 exceptions_throw_incompatibleclasschangeerror(tc,
1705 "Implementing class");
1709 /* Store the super interface. */
1711 c->interfaces[i] = tc;
1714 RT_TIMING_GET_TIME(time_setrefs);
1716 /* Parse the field descriptors. */
1718 for (i = 0; i < c->fieldscount; i++) {
1719 c->fields[i].parseddesc =
1720 descriptor_pool_parse_field_descriptor(descpool,
1721 c->fields[i].descriptor);
1722 if (!c->fields[i].parseddesc)
1726 RT_TIMING_GET_TIME(time_parsefds);
1728 /* parse method descriptors */
1730 for (i = 0; i < c->methodscount; i++) {
1731 methodinfo *m = &c->methods[i];
1733 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
1734 m->flags, class_get_self_classref(m->class));
1738 for (j = 0; j < m->rawexceptiontablelength; j++) {
1739 if (!m->rawexceptiontable[j].catchtype.any)
1742 if ((m->rawexceptiontable[j].catchtype.ref =
1743 descriptor_pool_lookup_classref(descpool,
1744 (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
1748 for (j = 0; j < m->thrownexceptionscount; j++) {
1749 if (!m->thrownexceptions[j].any)
1752 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
1753 (utf *) m->thrownexceptions[j].any)) == NULL)
1758 RT_TIMING_GET_TIME(time_parsemds);
1760 /* parse the loaded descriptors */
1762 for (i = 0; i < c->cpcount; i++) {
1763 constant_FMIref *fmi;
1766 switch (c->cptags[i]) {
1767 case CONSTANT_Fieldref:
1768 fmi = (constant_FMIref *) c->cpinfos[i];
1769 fmi->parseddesc.fd =
1770 descriptor_pool_parse_field_descriptor(descpool,
1772 if (!fmi->parseddesc.fd)
1775 index = fmi->p.index;
1777 (constant_classref *) class_getconstant(c, index,
1779 if (!fmi->p.classref)
1782 case CONSTANT_Methodref:
1783 case CONSTANT_InterfaceMethodref:
1784 fmi = (constant_FMIref *) c->cpinfos[i];
1785 index = fmi->p.index;
1787 (constant_classref *) class_getconstant(c, index,
1789 if (!fmi->p.classref)
1791 fmi->parseddesc.md =
1792 descriptor_pool_parse_method_descriptor(descpool,
1796 if (!fmi->parseddesc.md)
1802 RT_TIMING_GET_TIME(time_parsecpool);
1804 #ifdef ENABLE_VERIFIER
1805 /* Check if all fields and methods can be uniquely
1806 * identified by (name,descriptor). */
1809 /* We use a hash table here to avoid making the
1810 * average case quadratic in # of methods, fields.
1812 static int shift = 0;
1814 u2 *next; /* for chaining colliding hash entries */
1820 /* Allocate hashtable */
1821 len = c->methodscount;
1822 if (len < c->fieldscount) len = c->fieldscount;
1824 hashtab = MNEW(u2,(hashlen + len));
1825 next = hashtab + hashlen;
1827 /* Determine bitshift (to get good hash values) */
1837 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1839 for (i = 0; i < c->fieldscount; ++i) {
1840 fieldinfo *fi = c->fields + i;
1842 /* It's ok if we lose bits here */
1843 index = ((((size_t) fi->name) +
1844 ((size_t) fi->descriptor)) >> shift) % hashlen;
1846 if ((old = hashtab[index])) {
1850 if (c->fields[old].name == fi->name &&
1851 c->fields[old].descriptor == fi->descriptor) {
1852 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
1855 } while ((old = next[old]));
1857 hashtab[index] = i + 1;
1861 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
1863 for (i = 0; i < c->methodscount; ++i) {
1864 methodinfo *mi = c->methods + i;
1866 /* It's ok if we lose bits here */
1867 index = ((((size_t) mi->name) +
1868 ((size_t) mi->descriptor)) >> shift) % hashlen;
1870 if ((old = hashtab[index])) {
1874 if (c->methods[old].name == mi->name &&
1875 c->methods[old].descriptor == mi->descriptor) {
1876 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
1879 } while ((old = next[old]));
1881 hashtab[index] = i + 1;
1884 MFREE(hashtab, u2, (hashlen + len));
1886 #endif /* ENABLE_VERIFIER */
1888 RT_TIMING_GET_TIME(time_verify);
1890 #if defined(ENABLE_STATISTICS)
1892 size_classinfo += sizeof(classinfo*) * c->interfacescount;
1893 size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
1894 size_methodinfo += sizeof(methodinfo) * c->methodscount;
1898 /* load attribute structures */
1900 if (!class_load_attributes(cb))
1903 /* Pre Java 1.5 version don't check this. This implementation is
1904 like Java 1.5 do it: for class file version 45.3 we don't check
1905 it, older versions are checked. */
1907 if (((ma == 45) && (mi > 3)) || (ma > 45)) {
1908 /* check if all data has been read */
1909 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
1911 if (classdata_left > 0) {
1912 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
1917 RT_TIMING_GET_TIME(time_attrs);
1919 RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
1920 RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
1921 RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
1922 RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
1923 RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
1924 RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
1925 RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
1926 RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
1927 RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
1928 RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
1929 RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
1930 RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
1931 RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
1932 RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
1933 RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
1939 /* load_class_from_classbuffer *************************************************
1941 Convenience wrapper for load_class_from_classbuffer.
1944 This function is NOT synchronized!
1946 *******************************************************************************/
1948 classinfo *load_class_from_classbuffer(classbuffer *cb)
1954 /* Get the classbuffer's class. */
1958 /* Check if the class is already loaded. */
1960 if (c->state & CLASS_LOADED)
1963 #if defined(ENABLE_STATISTICS)
1965 count_class_loads++;
1968 #if !defined(NDEBUG)
1970 log_message_class("Loading class: ", c);
1973 /* Mark start of dump memory area. */
1977 /* Class is currently loading. */
1979 c->state |= CLASS_LOADING;
1981 /* Parse the classbuffer. */
1983 result = load_class_from_classbuffer_intern(cb);
1985 /* Release dump area. */
1989 /* An error occurred. */
1991 if (result == false) {
1992 /* Revert loading state. */
1994 c->state = (c->state & ~CLASS_LOADING);
1999 /* Revert loading state and set loaded. */
2001 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2003 #if defined(ENABLE_JVMTI)
2004 /* fire Class Prepare JVMTI event */
2007 jvmti_ClassLoadPrepare(true, c);
2010 #if !defined(NDEBUG)
2012 log_message_class("Loading done class: ", c);
2019 /* load_newly_created_array ****************************************************
2021 Load a newly created array class.
2024 c....................the array class C has been loaded
2025 other classinfo......the array class was found in the class cache,
2027 NULL.................an exception has been thrown
2030 This is an internal function. Do not use it unless you know exactly
2033 Use one of the load_class_... functions for general array class loading.
2035 *******************************************************************************/
2037 classinfo *load_newly_created_array(classinfo *c, classloader *loader)
2039 classinfo *comp = NULL;
2041 methoddesc *clonedesc;
2042 constant_classref *classrefs;
2047 text = c->name->text;
2048 namelen = c->name->blength;
2050 /* Check array class name */
2052 if ((namelen < 2) || (text[0] != '[')) {
2053 exceptions_throw_classnotfoundexception(c->name);
2057 /* Check the element type */
2061 /* c is an array of arrays. We have to create the component class. */
2063 u = utf_new(text + 1, namelen - 1);
2065 comp = load_class_from_classloader(u, loader);
2070 assert(comp->state & CLASS_LOADED);
2072 /* the array's flags are that of the component class */
2073 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2074 c->classloader = comp->classloader;
2078 /* c is an array of objects. */
2080 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2081 if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
2082 exceptions_throw_classnotfoundexception(c->name);
2086 u = utf_new(text + 2, namelen - 3);
2088 if (!(comp = load_class_from_classloader(u, loader)))
2091 assert(comp->state & CLASS_LOADED);
2093 /* the array's flags are that of the component class */
2094 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2095 c->classloader = comp->classloader;
2099 /* c is an array of a primitive type */
2101 /* check for cases like `[II' and whether the character is a
2102 valid primitive type */
2104 if ((namelen > 2) || (primitive_class_get_by_char(text[1]) == NULL)) {
2105 exceptions_throw_classnotfoundexception(c->name);
2109 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2110 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2111 c->classloader = NULL;
2114 assert(class_java_lang_Object);
2115 #if defined(ENABLE_JAVASE)
2116 assert(class_java_lang_Cloneable);
2117 assert(class_java_io_Serializable);
2120 /* Setup the array class. */
2122 c->super = class_java_lang_Object;
2124 #if defined(ENABLE_JAVASE)
2126 c->interfacescount = 2;
2127 c->interfaces = MNEW(classinfo*, 2);
2128 c->interfaces[0] = class_java_lang_Cloneable;
2129 c->interfaces[1] = class_java_io_Serializable;
2131 #elif defined(ENABLE_JAVAME_CLDC1_1)
2133 c->interfacescount = 0;
2134 c->interfaces = NULL;
2137 # error unknow Java configuration
2140 c->methodscount = 1;
2141 c->methods = MNEW(methodinfo, c->methodscount);
2143 MZERO(c->methods, methodinfo, c->methodscount);
2145 classrefs = MNEW(constant_classref, 2);
2147 CLASSREF_INIT(classrefs[0], c, c->name);
2148 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2150 /* create descriptor for clone method */
2151 /* we need one paramslot which is reserved for the 'this' parameter */
2152 clonedesc = NEW(methoddesc);
2153 clonedesc->returntype.type = TYPE_ADR;
2154 clonedesc->returntype.classref = classrefs + 1;
2155 clonedesc->returntype.arraydim = 0;
2156 /* initialize params to "empty", add real params below in
2157 descriptor_params_from_paramtypes */
2158 clonedesc->paramcount = 0;
2159 clonedesc->paramslots = 0;
2160 clonedesc->paramtypes[0].classref = classrefs + 0;
2161 clonedesc->params = NULL;
2163 /* create methodinfo */
2166 MSET(clone, 0, methodinfo, 1);
2168 #if defined(ENABLE_THREADS)
2169 lock_init_object_lock(&clone->header);
2172 /* ATTENTION: if you delete the ACC_NATIVE below, set
2173 clone->maxlocals=1 (interpreter related) */
2175 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2176 clone->name = utf_clone;
2177 clone->descriptor = utf_void__java_lang_Object;
2178 clone->parseddesc = clonedesc;
2181 /* parse the descriptor to get the register allocation */
2183 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2186 clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
2188 /* XXX: field: length? */
2190 /* array classes are not loaded from class files */
2192 c->state |= CLASS_LOADED;
2193 c->parseddescs = (u1 *) clonedesc;
2194 c->parseddescsize = sizeof(methodinfo);
2195 c->classrefs = classrefs;
2196 c->classrefcount = 1;
2198 /* insert class into the loaded class cache */
2199 /* XXX free classinfo if NULL returned? */
2201 return classcache_store(loader, c, true);
2205 /* loader_close ****************************************************************
2207 Frees all resources.
2209 *******************************************************************************/
2211 void loader_close(void)
2218 * These are local overrides for various environment variables in Emacs.
2219 * Please do not remove this and leave it at the end of the file, where
2220 * Emacs will automagically detect them.
2221 * ---------------------------------------------------------------------
2224 * indent-tabs-mode: t
2228 * vim:noexpandtab:sw=4:ts=4: