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 /* Some classes which may be used often. */
202 #if defined(ENABLE_JAVASE)
203 class_java_lang_StackTraceElement =
204 load_class_bootstrap(utf_java_lang_StackTraceElement);
206 class_java_lang_reflect_Constructor =
207 load_class_bootstrap(utf_java_lang_reflect_Constructor);
209 class_java_lang_reflect_Field =
210 load_class_bootstrap(utf_java_lang_reflect_Field);
212 class_java_lang_reflect_Method =
213 load_class_bootstrap(utf_java_lang_reflect_Method);
215 class_java_security_PrivilegedAction =
216 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
218 class_java_util_HashMap =
219 load_class_bootstrap(utf_new_char("java/util/HashMap"));
221 class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
223 # if defined(WITH_CLASSPATH_SUN)
224 class_sun_reflect_MagicAccessorImpl =
225 load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
228 arrayclass_java_lang_Object =
229 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
231 # if defined(ENABLE_ANNOTATIONS)
232 /* needed by annotation support */
233 class_sun_reflect_ConstantPool =
234 load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
236 # if defined(WITH_CLASSPATH_GNU)
237 /* needed by GNU Classpaths annotation support */
238 class_sun_reflect_annotation_AnnotationParser =
239 load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
246 /* loader_hashtable_classloader_add ********************************************
248 Adds an entry to the classloader hashtable.
250 REMEMBER: Also use this to register native loaders!
252 *******************************************************************************/
254 classloader *loader_hashtable_classloader_add(java_handle_t *cl)
256 hashtable_classloader_entry *cle;
263 LOCK_MONITOR_ENTER(hashtable_classloader->header);
267 /* key for entry is the hashcode of the classloader;
268 aligned to 16-byte boundaries */
270 key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
271 slot = key & (hashtable_classloader->size - 1);
272 cle = hashtable_classloader->ptr[slot];
274 /* search hashchain for existing entry */
277 if (cle->object == LLNI_DIRECT(cl))
285 /* if no classloader was found, we create a new entry here */
288 cle = NEW(hashtable_classloader_entry);
290 #if defined(ENABLE_GC_CACAO)
291 /* register the classloader object with the GC */
293 gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
298 cle->object = LLNI_DIRECT(cl);
302 /*#define LOADER_DEBUG_CLASSLOADER*/
303 #ifdef LOADER_DEBUG_CLASSLOADER
304 printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
305 class_print(LLNI_vftbl_direct(cl)->class);
310 /* insert entry into hashtable */
312 cle->hashlink = hashtable_classloader->ptr[slot];
313 hashtable_classloader->ptr[slot] = cle;
315 /* update number of entries */
317 hashtable_classloader->entries++;
321 LOCK_MONITOR_EXIT(hashtable_classloader->header);
323 #if defined(ENABLE_HANDLES)
331 /* loader_hashtable_classloader_find *******************************************
333 Find an entry in the classloader hashtable.
335 *******************************************************************************/
337 classloader *loader_hashtable_classloader_find(java_handle_t *cl)
339 hashtable_classloader_entry *cle;
348 /* key for entry is the hashcode of the classloader;
349 aligned to 16-byte boundaries */
351 key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
352 slot = key & (hashtable_classloader->size - 1);
353 cle = hashtable_classloader->ptr[slot];
355 /* search hashchain for existing entry */
358 if (cle->object == LLNI_DIRECT(cl))
364 #ifdef LOADER_DEBUG_CLASSLOADER
366 printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
367 class_print(LLNI_vftbl_direct(cl)->class);
375 #if defined(ENABLE_HANDLES)
383 /* loader_load_all_classes *****************************************************
385 Loads all classes specified in the BOOTCLASSPATH.
387 *******************************************************************************/
389 void loader_load_all_classes(void)
391 list_classpath_entry *lce;
392 #if defined(ENABLE_ZLIB)
395 hashtable_zipfile_entry *htzfe;
399 for (lce = list_first(list_classpath_entries); lce != NULL;
400 lce = list_next(list_classpath_entries, lce)) {
401 #if defined(ENABLE_ZLIB)
402 if (lce->type == CLASSPATH_ARCHIVE) {
403 /* get the classes hashtable */
407 for (slot = 0; slot < ht->size; slot++) {
408 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
410 for (; htzfe; htzfe = htzfe->hashlink) {
413 /* skip all entries in META-INF and .properties,
416 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
417 strstr(u->text, ".properties") ||
418 strstr(u->text, ".png"))
421 /* load class from bootstrap classloader */
423 if (!load_class_bootstrap(u)) {
424 fprintf(stderr, "Error loading: ");
425 utf_fprint_printable_ascii_classname(stderr, u);
426 fprintf(stderr, "\n");
429 /* print out exception and cause */
431 exceptions_print_current_exception();
439 #if defined(ENABLE_ZLIB)
446 /* loader_skip_attribute_body **************************************************
448 Skips an attribute the attribute_name_index has already been read.
451 u2 attribute_name_index;
453 u1 info[attribute_length];
456 *******************************************************************************/
458 bool loader_skip_attribute_body(classbuffer *cb)
462 if (!suck_check_classbuffer_size(cb, 4))
465 attribute_length = suck_u4(cb);
467 if (!suck_check_classbuffer_size(cb, attribute_length))
470 suck_skip_nbytes(cb, attribute_length);
476 /* load_constantpool ***********************************************************
478 Loads the constantpool of a class, the entries are transformed into
479 a simpler format by resolving references (a detailed overview of
480 the compact structures can be found in global.h).
482 *******************************************************************************/
484 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
487 /* The following structures are used to save information which cannot be
488 processed during the first pass. After the complete constantpool has
489 been traversed the references can be resolved.
490 (only in specific order) */
492 /* CONSTANT_Class entries */
493 typedef struct forward_class {
494 struct forward_class *next;
499 /* CONSTANT_String */
500 typedef struct forward_string {
501 struct forward_string *next;
506 /* CONSTANT_NameAndType */
507 typedef struct forward_nameandtype {
508 struct forward_nameandtype *next;
512 } forward_nameandtype;
514 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
515 typedef struct forward_fieldmethint {
516 struct forward_fieldmethint *next;
520 u2 nameandtype_index;
521 } forward_fieldmethint;
527 forward_class *forward_classes = NULL;
528 forward_string *forward_strings = NULL;
529 forward_nameandtype *forward_nameandtypes = NULL;
530 forward_fieldmethint *forward_fieldmethints = NULL;
534 forward_nameandtype *nfn;
535 forward_fieldmethint *nff;
543 /* number of entries in the constant_pool table plus one */
544 if (!suck_check_classbuffer_size(cb, 2))
547 cpcount = c->cpcount = suck_u2(cb);
549 /* allocate memory */
550 cptags = c->cptags = MNEW(u1, cpcount);
551 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
554 exceptions_throw_classformaterror(c, "Illegal constant pool size");
558 #if defined(ENABLE_STATISTICS)
560 count_const_pool_len += (sizeof(u1) + sizeof(voidptr)) * cpcount;
563 /* initialize constantpool */
564 for (idx = 0; idx < cpcount; idx++) {
565 cptags[idx] = CONSTANT_UNUSED;
570 /******* first pass *******/
571 /* entries which cannot be resolved now are written into
572 temporary structures and traversed again later */
575 while (idx < cpcount) {
578 /* get constant type */
579 if (!suck_check_classbuffer_size(cb, 1))
586 nfc = DNEW(forward_class);
588 nfc->next = forward_classes;
589 forward_classes = nfc;
591 nfc->thisindex = idx;
592 /* reference to CONSTANT_NameAndType */
593 if (!suck_check_classbuffer_size(cb, 2))
596 nfc->name_index = suck_u2(cb);
601 case CONSTANT_String:
602 nfs = DNEW(forward_string);
604 nfs->next = forward_strings;
605 forward_strings = nfs;
607 nfs->thisindex = idx;
609 /* reference to CONSTANT_Utf8_info with string characters */
610 if (!suck_check_classbuffer_size(cb, 2))
613 nfs->string_index = suck_u2(cb);
618 case CONSTANT_NameAndType:
619 nfn = DNEW(forward_nameandtype);
621 nfn->next = forward_nameandtypes;
622 forward_nameandtypes = nfn;
624 nfn->thisindex = idx;
626 if (!suck_check_classbuffer_size(cb, 2 + 2))
629 /* reference to CONSTANT_Utf8_info containing simple name */
630 nfn->name_index = suck_u2(cb);
632 /* reference to CONSTANT_Utf8_info containing field or method
634 nfn->sig_index = suck_u2(cb);
639 case CONSTANT_Fieldref:
640 case CONSTANT_Methodref:
641 case CONSTANT_InterfaceMethodref:
642 nff = DNEW(forward_fieldmethint);
644 nff->next = forward_fieldmethints;
645 forward_fieldmethints = nff;
647 nff->thisindex = idx;
651 if (!suck_check_classbuffer_size(cb, 2 + 2))
654 /* class or interface type that contains the declaration of the
656 nff->class_index = suck_u2(cb);
658 /* name and descriptor of the field or method */
659 nff->nameandtype_index = suck_u2(cb);
664 case CONSTANT_Integer: {
665 constant_integer *ci = NEW(constant_integer);
667 #if defined(ENABLE_STATISTICS)
669 count_const_pool_len += sizeof(constant_integer);
672 if (!suck_check_classbuffer_size(cb, 4))
675 ci->value = suck_s4(cb);
676 cptags[idx] = CONSTANT_Integer;
683 case CONSTANT_Float: {
684 constant_float *cf = NEW(constant_float);
686 #if defined(ENABLE_STATISTICS)
688 count_const_pool_len += sizeof(constant_float);
691 if (!suck_check_classbuffer_size(cb, 4))
694 cf->value = suck_float(cb);
695 cptags[idx] = CONSTANT_Float;
702 case CONSTANT_Long: {
703 constant_long *cl = NEW(constant_long);
705 #if defined(ENABLE_STATISTICS)
707 count_const_pool_len += sizeof(constant_long);
710 if (!suck_check_classbuffer_size(cb, 8))
713 cl->value = suck_s8(cb);
714 cptags[idx] = CONSTANT_Long;
718 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
724 case CONSTANT_Double: {
725 constant_double *cd = NEW(constant_double);
727 #if defined(ENABLE_STATISTICS)
729 count_const_pool_len += sizeof(constant_double);
732 if (!suck_check_classbuffer_size(cb, 8))
735 cd->value = suck_double(cb);
736 cptags[idx] = CONSTANT_Double;
740 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
746 case CONSTANT_Utf8: {
749 /* number of bytes in the bytes array (not string-length) */
750 if (!suck_check_classbuffer_size(cb, 2))
753 length = suck_u2(cb);
754 cptags[idx] = CONSTANT_Utf8;
756 /* validate the string */
757 if (!suck_check_classbuffer_size(cb, length))
760 #ifdef ENABLE_VERIFIER
762 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
764 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
767 #endif /* ENABLE_VERIFIER */
768 /* insert utf-string into the utf-symboltable */
769 cpinfos[idx] = utf_new((char *) cb->pos, length);
771 /* skip bytes of the string (buffer size check above) */
772 suck_skip_nbytes(cb, length);
778 exceptions_throw_classformaterror(c, "Illegal constant pool type");
784 /* resolve entries in temporary structures */
786 while (forward_classes) {
788 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
792 #ifdef ENABLE_VERIFIER
793 if (opt_verify && !is_valid_name_utf(name)) {
794 exceptions_throw_classformaterror(c, "Class reference with invalid name");
797 #endif /* ENABLE_VERIFIER */
799 /* add all class references to the descriptor_pool */
801 if (!descriptor_pool_add_class(descpool, name))
804 cptags[forward_classes->thisindex] = CONSTANT_Class;
806 /* the classref is created later */
807 cpinfos[forward_classes->thisindex] = name;
809 nfc = forward_classes;
810 forward_classes = forward_classes->next;
813 while (forward_strings) {
815 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
819 /* resolve utf-string */
820 cptags[forward_strings->thisindex] = CONSTANT_String;
821 cpinfos[forward_strings->thisindex] = text;
823 nfs = forward_strings;
824 forward_strings = forward_strings->next;
827 while (forward_nameandtypes) {
828 constant_nameandtype *cn = NEW(constant_nameandtype);
830 #if defined(ENABLE_STATISTICS)
832 count_const_pool_len += sizeof(constant_nameandtype);
835 /* resolve simple name and descriptor */
836 cn->name = class_getconstant(c,
837 forward_nameandtypes->name_index,
842 cn->descriptor = class_getconstant(c,
843 forward_nameandtypes->sig_index,
848 #ifdef ENABLE_VERIFIER
851 if (!is_valid_name_utf(cn->name)) {
852 exceptions_throw_classformaterror(c,
853 "Illegal Field name \"%s\"",
859 /* disallow referencing <clinit> among others */
860 if (cn->name->text[0] == '<' && cn->name != utf_init) {
861 exceptions_throw_classformaterror(c, "Illegal reference to special method");
865 #endif /* ENABLE_VERIFIER */
867 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
868 cpinfos[forward_nameandtypes->thisindex] = cn;
870 nfn = forward_nameandtypes;
871 forward_nameandtypes = forward_nameandtypes->next;
874 while (forward_fieldmethints) {
875 constant_nameandtype *nat;
876 constant_FMIref *fmi = NEW(constant_FMIref);
878 #if defined(ENABLE_STATISTICS)
880 count_const_pool_len += sizeof(constant_FMIref);
882 /* resolve simple name and descriptor */
884 nat = class_getconstant(c,
885 forward_fieldmethints->nameandtype_index,
886 CONSTANT_NameAndType);
890 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
892 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
895 /* the classref is created later */
897 fmi->p.index = forward_fieldmethints->class_index;
898 fmi->name = nat->name;
899 fmi->descriptor = nat->descriptor;
901 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
902 cpinfos[forward_fieldmethints->thisindex] = fmi;
904 nff = forward_fieldmethints;
905 forward_fieldmethints = forward_fieldmethints->next;
908 /* everything was ok */
914 /* loader_load_attribute_signature *********************************************
916 Signature_attribute {
917 u2 attribute_name_index;
922 *******************************************************************************/
924 #if defined(ENABLE_JAVASE)
925 bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
935 /* check remaining bytecode */
937 if (!suck_check_classbuffer_size(cb, 4 + 2))
940 /* check attribute length */
942 attribute_length = suck_u4(cb);
944 if (attribute_length != 2) {
945 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
949 if (*signature != NULL) {
950 exceptions_throw_classformaterror(c, "Multiple Signature attributes");
956 signature_index = suck_u2(cb);
958 if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
963 #endif /* defined(ENABLE_JAVASE) */
966 /* load_class_from_sysloader ***************************************************
968 Load the class with the given name using the system class loader
971 name.............the classname
975 NULL if an exception has been thrown
977 *******************************************************************************/
979 classinfo *load_class_from_sysloader(utf *name)
986 assert(class_java_lang_Object);
987 assert(class_java_lang_ClassLoader);
988 assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
990 m = class_resolveclassmethod(class_java_lang_ClassLoader,
991 utf_getSystemClassLoader,
992 utf_void__java_lang_ClassLoader,
993 class_java_lang_Object,
999 clo = vm_call_method(m, NULL);
1004 cl = loader_hashtable_classloader_add(clo);
1006 c = load_class_from_classloader(name, cl);
1012 /* load_class_from_classloader *************************************************
1014 Load the class with the given name using the given user-defined class loader.
1017 name.............the classname
1018 cl...............user-defined class loader
1021 the loaded class, or
1022 NULL if an exception has been thrown
1024 *******************************************************************************/
1026 classinfo *load_class_from_classloader(utf *name, classloader *cl)
1031 java_handle_t *string;
1032 #if defined(ENABLE_RT_TIMING)
1033 struct timespec time_start, time_lookup, time_prepare, time_java,
1037 RT_TIMING_GET_TIME(time_start);
1041 /* lookup if this class has already been loaded */
1043 c = classcache_lookup(cl, name);
1045 RT_TIMING_GET_TIME(time_lookup);
1046 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
1051 /* if other class loader than bootstrap, call it */
1059 namelen = name->blength;
1061 /* handle array classes */
1062 if (text[0] == '[') {
1068 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1069 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1070 exceptions_throw_classnotfoundexception(name);
1074 u = utf_new(text + 2, namelen - 3);
1076 if (!(comp = load_class_from_classloader(u, cl)))
1079 /* create the array class */
1081 c = class_array_of(comp, false);
1083 tmpc = classcache_store(cl, c, true);
1086 /* exception, free the loaded class */
1087 c->state &= ~CLASS_LOADING;
1094 /* load the component class */
1096 u = utf_new(text + 1, namelen - 1);
1098 if (!(comp = load_class_from_classloader(u, cl)))
1101 /* create the array class */
1103 c = class_array_of(comp, false);
1105 tmpc = classcache_store(cl, c, true);
1108 /* exception, free the loaded class */
1109 c->state &= ~CLASS_LOADING;
1116 /* primitive array classes are loaded by the bootstrap loader */
1118 c = load_class_bootstrap(name);
1124 LLNI_class_get(cl, c);
1126 #if defined(WITH_CLASSPATH_SUN)
1127 /* OpenJDK uses this internal function because it's
1130 lc = class_resolveclassmethod(c,
1131 utf_loadClassInternal,
1132 utf_java_lang_String__java_lang_Class,
1136 lc = class_resolveclassmethod(c,
1138 utf_java_lang_String__java_lang_Class,
1144 return false; /* exception */
1146 /* move return value into `o' and cast it afterwards to a classinfo* */
1148 string = javastring_new_slash_to_dot(name);
1150 RT_TIMING_GET_TIME(time_prepare);
1152 o = vm_call_method(lc, (java_handle_t *) cl, string);
1154 RT_TIMING_GET_TIME(time_java);
1156 c = LLNI_classinfo_unwrap(o);
1159 /* Store this class in the loaded class cache. If another
1160 class with the same (initloader,name) pair has been
1161 stored earlier it will be returned by classcache_store
1162 In this case classcache_store may not free the class
1163 because it has already been exposed to Java code which
1164 may have kept references to that class. */
1166 tmpc = classcache_store(cl, c, false);
1169 /* exception, free the loaded class */
1170 c->state &= ~CLASS_LOADING;
1177 RT_TIMING_GET_TIME(time_cache);
1179 RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
1180 RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
1181 RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
1183 /* SUN compatible -verbose:class output */
1185 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1187 utf_display_printable_ascii_classname(name);
1191 #if defined(ENABLE_JVMTI)
1192 /* fire Class Load JVMTI event */
1193 if (jvmti) jvmti_ClassLoadPrepare(false, c);
1200 c = load_class_bootstrap(name);
1206 /* load_class_bootstrap ********************************************************
1208 Load the class with the given name using the bootstrap class loader.
1211 name.............the classname
1214 loaded classinfo, or
1215 NULL if an exception has been thrown
1218 load_class_bootstrap is synchronized. It can be treated as an
1221 *******************************************************************************/
1223 classinfo *load_class_bootstrap(utf *name)
1228 #if defined(ENABLE_RT_TIMING)
1229 struct timespec time_start, time_lookup, time_array, time_suck,
1230 time_load, time_cache;
1233 RT_TIMING_GET_TIME(time_start);
1239 /* lookup if this class has already been loaded */
1241 r = classcache_lookup(NULL, name);
1244 RT_TIMING_GET_TIME(time_lookup);
1245 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1250 RT_TIMING_GET_TIME(time_lookup);
1251 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1253 /* create the classinfo */
1255 c = class_create_classinfo(name);
1257 /* handle array classes */
1259 if (name->text[0] == '[') {
1260 c = load_newly_created_array(c, NULL);
1265 assert(c->state & CLASS_LOADED);
1267 RT_TIMING_GET_TIME(time_array);
1268 RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
1273 #if defined(ENABLE_STATISTICS)
1276 if (opt_getcompilingtime)
1277 compilingtime_stop();
1279 if (opt_getloadingtime)
1280 loadingtime_start();
1283 /* load classdata, throw exception on error */
1288 exceptions_throw_classnotfoundexception(name);
1292 RT_TIMING_GET_TIME(time_suck);
1294 /* load the class from the buffer */
1296 r = load_class_from_classbuffer(cb);
1298 RT_TIMING_GET_TIME(time_load);
1301 /* the class could not be loaded, free the classinfo struct */
1306 /* Store this class in the loaded class cache this step also
1307 checks the loading constraints. If the class has been
1308 loaded before, the earlier loaded class is returned. */
1310 classinfo *res = classcache_store(NULL, c, true);
1317 /* Add the package name to the boot packages. */
1319 package_add(c->packagename);
1325 RT_TIMING_GET_TIME(time_cache);
1327 /* SUN compatible -verbose:class output */
1329 if (opt_verboseclass && r) {
1331 utf_display_printable_ascii_classname(name);
1332 printf(" from %s]\n", cb->path);
1339 #if defined(ENABLE_STATISTICS)
1342 if (opt_getloadingtime)
1345 if (opt_getcompilingtime)
1346 compilingtime_start();
1349 RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
1350 RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
1351 RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
1352 RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
1358 /* load_class_from_classbuffer_intern ******************************************
1360 Loads a class from a classbuffer into a given classinfo structure.
1361 Super-classes are also loaded at this point and some verfication
1365 This function is NOT synchronized!
1367 *******************************************************************************/
1369 static bool load_class_from_classbuffer_intern(classbuffer *cb)
1375 utf **interfacesnames;
1377 constant_classref *cr;
1382 descriptor_pool *descpool;
1383 #if defined(ENABLE_STATISTICS)
1387 #if defined(ENABLE_RT_TIMING)
1388 struct timespec time_start, time_checks, time_ndpool, time_cpool,
1389 time_setup, time_fields, time_methods, time_classrefs,
1390 time_descs, time_setrefs, time_parsefds, time_parsemds,
1391 time_parsecpool, time_verify, time_attrs;
1394 RT_TIMING_GET_TIME(time_start);
1396 /* Get the classbuffer's class. */
1400 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1403 /* check signature */
1405 if (suck_u4(cb) != MAGIC) {
1406 exceptions_throw_classformaterror(c, "Bad magic number");
1415 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1416 exceptions_throw_unsupportedclassversionerror(c, ma, mi);
1420 RT_TIMING_GET_TIME(time_checks);
1422 /* create a new descriptor pool */
1424 descpool = descriptor_pool_new(c);
1426 RT_TIMING_GET_TIME(time_ndpool);
1428 /* load the constant pool */
1430 if (!load_constantpool(cb, descpool))
1433 RT_TIMING_GET_TIME(time_cpool);
1437 if (!suck_check_classbuffer_size(cb, 2))
1440 /* We OR the flags here, as we set already some flags in
1441 class_create_classinfo. */
1443 c->flags |= suck_u2(cb);
1445 /* check ACC flags consistency */
1447 if (c->flags & ACC_INTERFACE) {
1448 if (!(c->flags & ACC_ABSTRACT)) {
1449 /* We work around this because interfaces in JDK 1.1 are
1450 * not declared abstract. */
1452 c->flags |= ACC_ABSTRACT;
1455 if (c->flags & ACC_FINAL) {
1456 exceptions_throw_classformaterror(c,
1457 "Illegal class modifiers: 0x%X",
1462 if (c->flags & ACC_SUPER) {
1463 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1467 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1468 exceptions_throw_classformaterror(c,
1469 "Illegal class modifiers: 0x%X",
1474 if (!suck_check_classbuffer_size(cb, 2 + 2))
1479 index = suck_u2(cb);
1481 name = (utf *) class_getconstant(c, index, CONSTANT_Class);
1486 if (c->name == utf_not_named_yet) {
1487 /* we finally have a name for this class */
1489 class_set_packagename(c);
1491 else if (name != c->name) {
1492 exceptions_throw_noclassdeffounderror_wrong_name(c, name);
1496 /* Retrieve superclass. */
1500 index = suck_u2(cb);
1505 /* This is only allowed for java.lang.Object. */
1507 if (c->name != utf_java_lang_Object) {
1508 exceptions_throw_classformaterror(c, "Bad superclass index");
1513 supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
1515 if (supername == NULL)
1518 /* java.lang.Object may not have a super class. */
1520 if (c->name == utf_java_lang_Object) {
1521 exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
1525 /* Detect circularity. */
1527 if (supername == c->name) {
1528 exceptions_throw_classcircularityerror(c);
1532 /* Interfaces must have java.lang.Object as super class. */
1534 if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
1535 exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
1540 /* Parse the super interfaces. */
1542 if (!suck_check_classbuffer_size(cb, 2))
1545 c->interfacescount = suck_u2(cb);
1547 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1550 c->interfaces = MNEW(classinfo*, c->interfacescount);
1552 /* Get the names of the super interfaces. */
1554 interfacesnames = DMNEW(utf*, c->interfacescount);
1556 for (i = 0; i < c->interfacescount; i++) {
1557 index = suck_u2(cb);
1559 u = (utf *) class_getconstant(c, index, CONSTANT_Class);
1564 interfacesnames[i] = u;
1567 RT_TIMING_GET_TIME(time_setup);
1571 if (!suck_check_classbuffer_size(cb, 2))
1574 c->fieldscount = suck_u2(cb);
1575 c->fields = MNEW(fieldinfo, c->fieldscount);
1577 MZERO(c->fields, fieldinfo, c->fieldscount);
1579 for (i = 0; i < c->fieldscount; i++) {
1580 if (!field_load(cb, &(c->fields[i]), descpool))
1584 RT_TIMING_GET_TIME(time_fields);
1586 /* Parse methods. */
1588 if (!suck_check_classbuffer_size(cb, 2))
1591 c->methodscount = suck_u2(cb);
1592 c->methods = MNEW(methodinfo, c->methodscount);
1594 MZERO(c->methods, methodinfo, c->methodscount);
1596 for (i = 0; i < c->methodscount; i++) {
1597 if (!method_load(cb, &(c->methods[i]), descpool))
1601 RT_TIMING_GET_TIME(time_methods);
1603 /* create the class reference table */
1606 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
1608 RT_TIMING_GET_TIME(time_classrefs);
1610 /* allocate space for the parsed descriptors */
1612 descriptor_pool_alloc_parsed_descriptors(descpool);
1614 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
1616 #if defined(ENABLE_STATISTICS)
1618 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
1619 count_classref_len += classrefsize;
1620 count_parsed_desc_len += descsize;
1624 RT_TIMING_GET_TIME(time_descs);
1626 /* put the classrefs in the constant pool */
1628 for (i = 0; i < c->cpcount; i++) {
1629 if (c->cptags[i] == CONSTANT_Class) {
1630 utf *name = (utf *) c->cpinfos[i];
1631 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
1635 /* Resolve the super class. */
1637 if (supername != NULL) {
1638 cr = descriptor_pool_lookup_classref(descpool, supername);
1643 /* XXX This should be done better. */
1644 tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
1649 /* Interfaces are not allowed as super classes. */
1651 if (tc->flags & ACC_INTERFACE) {
1652 exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
1656 /* Don't allow extending final classes */
1658 if (tc->flags & ACC_FINAL) {
1659 exceptions_throw_verifyerror(NULL,
1660 "Cannot inherit from final class");
1664 /* Store the super class. */
1669 /* Resolve the super interfaces. */
1671 for (i = 0; i < c->interfacescount; i++) {
1672 u = interfacesnames[i];
1673 cr = descriptor_pool_lookup_classref(descpool, u);
1678 /* XXX This should be done better. */
1679 tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
1684 /* Detect circularity. */
1687 exceptions_throw_classcircularityerror(c);
1691 if (!(tc->flags & ACC_INTERFACE)) {
1692 exceptions_throw_incompatibleclasschangeerror(tc,
1693 "Implementing class");
1697 /* Store the super interface. */
1699 c->interfaces[i] = tc;
1702 RT_TIMING_GET_TIME(time_setrefs);
1704 /* Parse the field descriptors. */
1706 for (i = 0; i < c->fieldscount; i++) {
1707 c->fields[i].parseddesc =
1708 descriptor_pool_parse_field_descriptor(descpool,
1709 c->fields[i].descriptor);
1710 if (!c->fields[i].parseddesc)
1714 RT_TIMING_GET_TIME(time_parsefds);
1716 /* parse method descriptors */
1718 for (i = 0; i < c->methodscount; i++) {
1719 methodinfo *m = &c->methods[i];
1721 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
1722 m->flags, class_get_self_classref(m->class));
1726 for (j = 0; j < m->rawexceptiontablelength; j++) {
1727 if (!m->rawexceptiontable[j].catchtype.any)
1730 if ((m->rawexceptiontable[j].catchtype.ref =
1731 descriptor_pool_lookup_classref(descpool,
1732 (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
1736 for (j = 0; j < m->thrownexceptionscount; j++) {
1737 if (!m->thrownexceptions[j].any)
1740 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
1741 (utf *) m->thrownexceptions[j].any)) == NULL)
1746 RT_TIMING_GET_TIME(time_parsemds);
1748 /* parse the loaded descriptors */
1750 for (i = 0; i < c->cpcount; i++) {
1751 constant_FMIref *fmi;
1754 switch (c->cptags[i]) {
1755 case CONSTANT_Fieldref:
1756 fmi = (constant_FMIref *) c->cpinfos[i];
1757 fmi->parseddesc.fd =
1758 descriptor_pool_parse_field_descriptor(descpool,
1760 if (!fmi->parseddesc.fd)
1763 index = fmi->p.index;
1765 (constant_classref *) class_getconstant(c, index,
1767 if (!fmi->p.classref)
1770 case CONSTANT_Methodref:
1771 case CONSTANT_InterfaceMethodref:
1772 fmi = (constant_FMIref *) c->cpinfos[i];
1773 index = fmi->p.index;
1775 (constant_classref *) class_getconstant(c, index,
1777 if (!fmi->p.classref)
1779 fmi->parseddesc.md =
1780 descriptor_pool_parse_method_descriptor(descpool,
1784 if (!fmi->parseddesc.md)
1790 RT_TIMING_GET_TIME(time_parsecpool);
1792 #ifdef ENABLE_VERIFIER
1793 /* Check if all fields and methods can be uniquely
1794 * identified by (name,descriptor). */
1797 /* We use a hash table here to avoid making the
1798 * average case quadratic in # of methods, fields.
1800 static int shift = 0;
1802 u2 *next; /* for chaining colliding hash entries */
1808 /* Allocate hashtable */
1809 len = c->methodscount;
1810 if (len < c->fieldscount) len = c->fieldscount;
1812 hashtab = MNEW(u2,(hashlen + len));
1813 next = hashtab + hashlen;
1815 /* Determine bitshift (to get good hash values) */
1825 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1827 for (i = 0; i < c->fieldscount; ++i) {
1828 fieldinfo *fi = c->fields + i;
1830 /* It's ok if we lose bits here */
1831 index = ((((size_t) fi->name) +
1832 ((size_t) fi->descriptor)) >> shift) % hashlen;
1834 if ((old = hashtab[index])) {
1838 if (c->fields[old].name == fi->name &&
1839 c->fields[old].descriptor == fi->descriptor) {
1840 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
1843 } while ((old = next[old]));
1845 hashtab[index] = i + 1;
1849 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
1851 for (i = 0; i < c->methodscount; ++i) {
1852 methodinfo *mi = c->methods + i;
1854 /* It's ok if we lose bits here */
1855 index = ((((size_t) mi->name) +
1856 ((size_t) mi->descriptor)) >> shift) % hashlen;
1858 if ((old = hashtab[index])) {
1862 if (c->methods[old].name == mi->name &&
1863 c->methods[old].descriptor == mi->descriptor) {
1864 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
1867 } while ((old = next[old]));
1869 hashtab[index] = i + 1;
1872 MFREE(hashtab, u2, (hashlen + len));
1874 #endif /* ENABLE_VERIFIER */
1876 RT_TIMING_GET_TIME(time_verify);
1878 #if defined(ENABLE_STATISTICS)
1880 size_classinfo += sizeof(classinfo*) * c->interfacescount;
1881 size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
1882 size_methodinfo += sizeof(methodinfo) * c->methodscount;
1886 /* load attribute structures */
1888 if (!class_load_attributes(cb))
1891 /* Pre Java 1.5 version don't check this. This implementation is
1892 like Java 1.5 do it: for class file version 45.3 we don't check
1893 it, older versions are checked. */
1895 if (((ma == 45) && (mi > 3)) || (ma > 45)) {
1896 /* check if all data has been read */
1897 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
1899 if (classdata_left > 0) {
1900 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
1905 RT_TIMING_GET_TIME(time_attrs);
1907 RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
1908 RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
1909 RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
1910 RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
1911 RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
1912 RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
1913 RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
1914 RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
1915 RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
1916 RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
1917 RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
1918 RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
1919 RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
1920 RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
1921 RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
1927 /* load_class_from_classbuffer *************************************************
1929 Convenience wrapper for load_class_from_classbuffer.
1932 This function is NOT synchronized!
1934 *******************************************************************************/
1936 classinfo *load_class_from_classbuffer(classbuffer *cb)
1942 /* Get the classbuffer's class. */
1946 /* Check if the class is already loaded. */
1948 if (c->state & CLASS_LOADED)
1951 #if defined(ENABLE_STATISTICS)
1953 count_class_loads++;
1956 #if !defined(NDEBUG)
1958 log_message_class("Loading class: ", c);
1961 /* Mark start of dump memory area. */
1965 /* Class is currently loading. */
1967 c->state |= CLASS_LOADING;
1969 /* Parse the classbuffer. */
1971 result = load_class_from_classbuffer_intern(cb);
1973 /* Release dump area. */
1977 /* An error occurred. */
1979 if (result == false) {
1980 /* Revert loading state. */
1982 c->state = (c->state & ~CLASS_LOADING);
1987 /* Revert loading state and set loaded. */
1989 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
1991 #if defined(ENABLE_JVMTI)
1992 /* fire Class Prepare JVMTI event */
1995 jvmti_ClassLoadPrepare(true, c);
1998 #if !defined(NDEBUG)
2000 log_message_class("Loading done class: ", c);
2007 /* load_newly_created_array ****************************************************
2009 Load a newly created array class.
2012 c....................the array class C has been loaded
2013 other classinfo......the array class was found in the class cache,
2015 NULL.................an exception has been thrown
2018 This is an internal function. Do not use it unless you know exactly
2021 Use one of the load_class_... functions for general array class loading.
2023 *******************************************************************************/
2025 classinfo *load_newly_created_array(classinfo *c, classloader *loader)
2027 classinfo *comp = NULL;
2029 methoddesc *clonedesc;
2030 constant_classref *classrefs;
2035 text = c->name->text;
2036 namelen = c->name->blength;
2038 /* Check array class name */
2040 if ((namelen < 2) || (text[0] != '[')) {
2041 exceptions_throw_classnotfoundexception(c->name);
2045 /* Check the element type */
2049 /* c is an array of arrays. We have to create the component class. */
2051 u = utf_new(text + 1, namelen - 1);
2053 comp = load_class_from_classloader(u, loader);
2058 assert(comp->state & CLASS_LOADED);
2060 /* the array's flags are that of the component class */
2061 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2062 c->classloader = comp->classloader;
2066 /* c is an array of objects. */
2068 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2069 if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
2070 exceptions_throw_classnotfoundexception(c->name);
2074 u = utf_new(text + 2, namelen - 3);
2076 if (!(comp = load_class_from_classloader(u, loader)))
2079 assert(comp->state & CLASS_LOADED);
2081 /* the array's flags are that of the component class */
2082 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2083 c->classloader = comp->classloader;
2087 /* c is an array of a primitive type */
2089 /* check for cases like `[II' and whether the character is a
2090 valid primitive type */
2092 if ((namelen > 2) || (primitive_class_get_by_char(text[1]) == NULL)) {
2093 exceptions_throw_classnotfoundexception(c->name);
2097 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2098 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2099 c->classloader = NULL;
2102 assert(class_java_lang_Object);
2103 #if defined(ENABLE_JAVASE)
2104 assert(class_java_lang_Cloneable);
2105 assert(class_java_io_Serializable);
2108 /* Setup the array class. */
2110 c->super = class_java_lang_Object;
2112 #if defined(ENABLE_JAVASE)
2114 c->interfacescount = 2;
2115 c->interfaces = MNEW(classinfo*, 2);
2116 c->interfaces[0] = class_java_lang_Cloneable;
2117 c->interfaces[1] = class_java_io_Serializable;
2119 #elif defined(ENABLE_JAVAME_CLDC1_1)
2121 c->interfacescount = 0;
2122 c->interfaces = NULL;
2125 # error unknow Java configuration
2128 c->methodscount = 1;
2129 c->methods = MNEW(methodinfo, c->methodscount);
2131 MZERO(c->methods, methodinfo, c->methodscount);
2133 classrefs = MNEW(constant_classref, 2);
2135 CLASSREF_INIT(classrefs[0], c, c->name);
2136 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2138 /* create descriptor for clone method */
2139 /* we need one paramslot which is reserved for the 'this' parameter */
2140 clonedesc = NEW(methoddesc);
2141 clonedesc->returntype.type = TYPE_ADR;
2142 clonedesc->returntype.classref = classrefs + 1;
2143 clonedesc->returntype.arraydim = 0;
2144 /* initialize params to "empty", add real params below in
2145 descriptor_params_from_paramtypes */
2146 clonedesc->paramcount = 0;
2147 clonedesc->paramslots = 0;
2148 clonedesc->paramtypes[0].classref = classrefs + 0;
2149 clonedesc->params = NULL;
2151 /* create methodinfo */
2154 MSET(clone, 0, methodinfo, 1);
2156 #if defined(ENABLE_THREADS)
2157 lock_init_object_lock(&clone->header);
2160 /* ATTENTION: if you delete the ACC_NATIVE below, set
2161 clone->maxlocals=1 (interpreter related) */
2163 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2164 clone->name = utf_clone;
2165 clone->descriptor = utf_void__java_lang_Object;
2166 clone->parseddesc = clonedesc;
2169 /* parse the descriptor to get the register allocation */
2171 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2174 clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
2176 /* XXX: field: length? */
2178 /* array classes are not loaded from class files */
2180 c->state |= CLASS_LOADED;
2181 c->parseddescs = (u1 *) clonedesc;
2182 c->parseddescsize = sizeof(methodinfo);
2183 c->classrefs = classrefs;
2184 c->classrefcount = 1;
2186 /* insert class into the loaded class cache */
2187 /* XXX free classinfo if NULL returned? */
2189 return classcache_store(loader, c, true);
2193 /* loader_close ****************************************************************
2195 Frees all resources.
2197 *******************************************************************************/
2199 void loader_close(void)
2206 * These are local overrides for various environment variables in Emacs.
2207 * Please do not remove this and leave it at the end of the file, where
2208 * Emacs will automagically detect them.
2209 * ---------------------------------------------------------------------
2212 * indent-tabs-mode: t
2216 * vim:noexpandtab:sw=4:ts=4: