1 /* src/vm/loader.c - class loader functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
34 $Id: loader.c 5937 2006-11-08 22:00:57Z twisti $
47 #include "mm/memory.h"
48 #include "native/native.h"
49 #include "native/include/java_lang_Throwable.h"
51 #if defined(ENABLE_THREADS)
52 # include "threads/native/threads.h"
55 #include "toolbox/logging.h"
56 #include "vm/builtin.h"
57 #include "vm/classcache.h"
58 #include "vm/exceptions.h"
59 #include "vm/global.h"
60 #include "vm/linker.h"
61 #include "vm/loader.h"
62 #include "vm/options.h"
63 #include "vm/statistics.h"
64 #include "vm/stringlocal.h"
68 #if defined(ENABLE_ZLIB)
72 #include "vm/jit/asmpart.h"
73 #include "vm/jit/codegen-common.h"
74 #include "vm/rt-timing.h"
76 #if defined(ENABLE_JVMTI)
77 #include "native/jvmti/cacaodbg.h"
81 /* loader_init *****************************************************************
83 Initializes all lists and loads all classes required for the system
86 *******************************************************************************/
88 bool loader_init(void)
90 #if defined(ENABLE_THREADS)
91 list_classpath_entry *lce;
93 /* Initialize the monitor pointer for zip/jar file locking. */
95 for (lce = list_first(list_classpath_entries); lce != NULL;
96 lce = list_next(list_classpath_entries, lce))
97 if (lce->type == CLASSPATH_ARCHIVE)
98 lock_init_object_lock((java_objectheader *) lce);
101 /* load some important classes */
103 if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
106 if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
109 if (!(class_java_lang_Cloneable =
110 load_class_bootstrap(utf_java_lang_Cloneable)))
113 if (!(class_java_io_Serializable =
114 load_class_bootstrap(utf_java_io_Serializable)))
118 /* load classes for wrapping primitive types */
120 if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
123 if (!(class_java_lang_Boolean =
124 load_class_bootstrap(utf_java_lang_Boolean)))
127 if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
130 if (!(class_java_lang_Character =
131 load_class_bootstrap(utf_java_lang_Character)))
134 if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
137 if (!(class_java_lang_Integer =
138 load_class_bootstrap(utf_java_lang_Integer)))
141 if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
144 if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
147 if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
151 /* load some other important classes */
153 if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
156 if (!(class_java_lang_ClassLoader =
157 load_class_bootstrap(utf_java_lang_ClassLoader)))
160 if (!(class_java_lang_SecurityManager =
161 load_class_bootstrap(utf_java_lang_SecurityManager)))
164 if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
167 if (!(class_java_lang_Thread =
168 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
171 if (!(class_java_lang_ThreadGroup =
172 load_class_bootstrap(utf_java_lang_ThreadGroup)))
175 if (!(class_java_lang_VMSystem =
176 load_class_bootstrap(utf_new_char("java/lang/VMSystem"))))
179 if (!(class_java_lang_VMThread =
180 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
184 /* some classes which may be used more often */
186 if (!(class_java_lang_StackTraceElement =
187 load_class_bootstrap(utf_java_lang_StackTraceElement)))
190 if (!(class_java_lang_reflect_Constructor =
191 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
194 if (!(class_java_lang_reflect_Field =
195 load_class_bootstrap(utf_java_lang_reflect_Field)))
198 if (!(class_java_lang_reflect_Method =
199 load_class_bootstrap(utf_java_lang_reflect_Method)))
202 if (!(class_java_security_PrivilegedAction =
203 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
206 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
209 if (!(arrayclass_java_lang_Object =
210 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
217 /* loader_load_all_classes *****************************************************
219 Loads all classes specified in the BOOTCLASSPATH.
221 *******************************************************************************/
223 void loader_load_all_classes(void)
225 list_classpath_entry *lce;
226 #if defined(ENABLE_ZLIB)
229 hashtable_zipfile_entry *htzfe;
233 for (lce = list_first(list_classpath_entries); lce != NULL;
234 lce = list_next(list_classpath_entries, lce)) {
235 #if defined(ENABLE_ZLIB)
236 if (lce->type == CLASSPATH_ARCHIVE) {
237 /* get the classes hashtable */
241 for (slot = 0; slot < ht->size; slot++) {
242 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
244 for (; htzfe; htzfe = htzfe->hashlink) {
247 /* skip all entries in META-INF and .properties,
250 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
251 strstr(u->text, ".properties") ||
252 strstr(u->text, ".png"))
255 /* load class from bootstrap classloader */
257 if (!load_class_bootstrap(u)) {
258 fprintf(stderr, "Error loading: ");
259 utf_fprint_printable_ascii_classname(stderr, u);
260 fprintf(stderr, "\n");
263 /* print out exception and cause */
265 exceptions_print_exception(*exceptionptr);
273 #if defined(ENABLE_ZLIB)
280 /* skipattributebody ***********************************************************
282 Skips an attribute after the 16 bit reference to attribute_name has
285 *******************************************************************************/
287 static bool skipattributebody(classbuffer *cb)
291 if (!suck_check_classbuffer_size(cb, 4))
296 if (!suck_check_classbuffer_size(cb, len))
299 suck_skip_nbytes(cb, len);
305 /************************* Function: skipattributes ****************************
307 skips num attribute structures
309 *******************************************************************************/
311 static bool skipattributes(classbuffer *cb, u4 num)
316 for (i = 0; i < num; i++) {
317 if (!suck_check_classbuffer_size(cb, 2 + 4))
323 if (!suck_check_classbuffer_size(cb, len))
326 suck_skip_nbytes(cb, len);
333 /* load_constantpool ***********************************************************
335 Loads the constantpool of a class, the entries are transformed into
336 a simpler format by resolving references (a detailed overview of
337 the compact structures can be found in global.h).
339 *******************************************************************************/
341 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
344 /* The following structures are used to save information which cannot be
345 processed during the first pass. After the complete constantpool has
346 been traversed the references can be resolved.
347 (only in specific order) */
349 /* CONSTANT_Class entries */
350 typedef struct forward_class {
351 struct forward_class *next;
356 /* CONSTANT_String */
357 typedef struct forward_string {
358 struct forward_string *next;
363 /* CONSTANT_NameAndType */
364 typedef struct forward_nameandtype {
365 struct forward_nameandtype *next;
369 } forward_nameandtype;
371 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
372 typedef struct forward_fieldmethint {
373 struct forward_fieldmethint *next;
377 u2 nameandtype_index;
378 } forward_fieldmethint;
384 forward_class *forward_classes = NULL;
385 forward_string *forward_strings = NULL;
386 forward_nameandtype *forward_nameandtypes = NULL;
387 forward_fieldmethint *forward_fieldmethints = NULL;
391 forward_nameandtype *nfn;
392 forward_fieldmethint *nff;
400 /* number of entries in the constant_pool table plus one */
401 if (!suck_check_classbuffer_size(cb, 2))
404 cpcount = c->cpcount = suck_u2(cb);
406 /* allocate memory */
407 cptags = c->cptags = MNEW(u1, cpcount);
408 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
411 exceptions_throw_classformaterror(c, "Illegal constant pool size");
415 #if defined(ENABLE_STATISTICS)
417 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
420 /* initialize constantpool */
421 for (idx = 0; idx < cpcount; idx++) {
422 cptags[idx] = CONSTANT_UNUSED;
427 /******* first pass *******/
428 /* entries which cannot be resolved now are written into
429 temporary structures and traversed again later */
432 while (idx < cpcount) {
435 /* get constant type */
436 if (!suck_check_classbuffer_size(cb, 1))
443 nfc = DNEW(forward_class);
445 nfc->next = forward_classes;
446 forward_classes = nfc;
448 nfc->thisindex = idx;
449 /* reference to CONSTANT_NameAndType */
450 if (!suck_check_classbuffer_size(cb, 2))
453 nfc->name_index = suck_u2(cb);
458 case CONSTANT_String:
459 nfs = DNEW(forward_string);
461 nfs->next = forward_strings;
462 forward_strings = nfs;
464 nfs->thisindex = idx;
466 /* reference to CONSTANT_Utf8_info with string characters */
467 if (!suck_check_classbuffer_size(cb, 2))
470 nfs->string_index = suck_u2(cb);
475 case CONSTANT_NameAndType:
476 nfn = DNEW(forward_nameandtype);
478 nfn->next = forward_nameandtypes;
479 forward_nameandtypes = nfn;
481 nfn->thisindex = idx;
483 if (!suck_check_classbuffer_size(cb, 2 + 2))
486 /* reference to CONSTANT_Utf8_info containing simple name */
487 nfn->name_index = suck_u2(cb);
489 /* reference to CONSTANT_Utf8_info containing field or method
491 nfn->sig_index = suck_u2(cb);
496 case CONSTANT_Fieldref:
497 case CONSTANT_Methodref:
498 case CONSTANT_InterfaceMethodref:
499 nff = DNEW(forward_fieldmethint);
501 nff->next = forward_fieldmethints;
502 forward_fieldmethints = nff;
504 nff->thisindex = idx;
508 if (!suck_check_classbuffer_size(cb, 2 + 2))
511 /* class or interface type that contains the declaration of the
513 nff->class_index = suck_u2(cb);
515 /* name and descriptor of the field or method */
516 nff->nameandtype_index = suck_u2(cb);
521 case CONSTANT_Integer: {
522 constant_integer *ci = NEW(constant_integer);
524 #if defined(ENABLE_STATISTICS)
526 count_const_pool_len += sizeof(constant_integer);
529 if (!suck_check_classbuffer_size(cb, 4))
532 ci->value = suck_s4(cb);
533 cptags[idx] = CONSTANT_Integer;
540 case CONSTANT_Float: {
541 constant_float *cf = NEW(constant_float);
543 #if defined(ENABLE_STATISTICS)
545 count_const_pool_len += sizeof(constant_float);
548 if (!suck_check_classbuffer_size(cb, 4))
551 cf->value = suck_float(cb);
552 cptags[idx] = CONSTANT_Float;
559 case CONSTANT_Long: {
560 constant_long *cl = NEW(constant_long);
562 #if defined(ENABLE_STATISTICS)
564 count_const_pool_len += sizeof(constant_long);
567 if (!suck_check_classbuffer_size(cb, 8))
570 cl->value = suck_s8(cb);
571 cptags[idx] = CONSTANT_Long;
575 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
581 case CONSTANT_Double: {
582 constant_double *cd = NEW(constant_double);
584 #if defined(ENABLE_STATISTICS)
586 count_const_pool_len += sizeof(constant_double);
589 if (!suck_check_classbuffer_size(cb, 8))
592 cd->value = suck_double(cb);
593 cptags[idx] = CONSTANT_Double;
597 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
603 case CONSTANT_Utf8: {
606 /* number of bytes in the bytes array (not string-length) */
607 if (!suck_check_classbuffer_size(cb, 2))
610 length = suck_u2(cb);
611 cptags[idx] = CONSTANT_Utf8;
613 /* validate the string */
614 if (!suck_check_classbuffer_size(cb, length))
617 #ifdef ENABLE_VERIFIER
619 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
621 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
624 #endif /* ENABLE_VERIFIER */
625 /* insert utf-string into the utf-symboltable */
626 cpinfos[idx] = utf_new((char *) cb->pos, length);
628 /* skip bytes of the string (buffer size check above) */
629 suck_skip_nbytes(cb, length);
635 exceptions_throw_classformaterror(c, "Illegal constant pool type");
641 /* resolve entries in temporary structures */
643 while (forward_classes) {
645 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
649 #ifdef ENABLE_VERIFIER
650 if (opt_verify && !is_valid_name_utf(name)) {
651 exceptions_throw_classformaterror(c, "Class reference with invalid name");
654 #endif /* ENABLE_VERIFIER */
656 /* add all class references to the descriptor_pool */
658 if (!descriptor_pool_add_class(descpool, name))
661 cptags[forward_classes->thisindex] = CONSTANT_Class;
666 if (!(tc = load_class_bootstrap(name)))
669 /* link the class later, because we cannot link the class currently
671 list_add_first(&unlinkedclasses, tc);
674 /* the classref is created later */
675 cpinfos[forward_classes->thisindex] = name;
677 nfc = forward_classes;
678 forward_classes = forward_classes->next;
681 while (forward_strings) {
683 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
687 /* resolve utf-string */
688 cptags[forward_strings->thisindex] = CONSTANT_String;
689 cpinfos[forward_strings->thisindex] = text;
691 nfs = forward_strings;
692 forward_strings = forward_strings->next;
695 while (forward_nameandtypes) {
696 constant_nameandtype *cn = NEW(constant_nameandtype);
698 #if defined(ENABLE_STATISTICS)
700 count_const_pool_len += sizeof(constant_nameandtype);
703 /* resolve simple name and descriptor */
704 cn->name = class_getconstant(c,
705 forward_nameandtypes->name_index,
710 cn->descriptor = class_getconstant(c,
711 forward_nameandtypes->sig_index,
716 #ifdef ENABLE_VERIFIER
719 if (!is_valid_name_utf(cn->name)) {
720 exceptions_throw_classformaterror(c,
721 "Illegal Field name \"%s\"",
727 /* disallow referencing <clinit> among others */
728 if (cn->name->text[0] == '<' && cn->name != utf_init) {
729 exceptions_throw_classformaterror(c, "Illegal reference to special method");
733 #endif /* ENABLE_VERIFIER */
735 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
736 cpinfos[forward_nameandtypes->thisindex] = cn;
738 nfn = forward_nameandtypes;
739 forward_nameandtypes = forward_nameandtypes->next;
742 while (forward_fieldmethints) {
743 constant_nameandtype *nat;
744 constant_FMIref *fmi = NEW(constant_FMIref);
746 #if defined(ENABLE_STATISTICS)
748 count_const_pool_len += sizeof(constant_FMIref);
750 /* resolve simple name and descriptor */
752 nat = class_getconstant(c,
753 forward_fieldmethints->nameandtype_index,
754 CONSTANT_NameAndType);
758 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
760 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
763 /* the classref is created later */
765 fmi->p.index = forward_fieldmethints->class_index;
766 fmi->name = nat->name;
767 fmi->descriptor = nat->descriptor;
769 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
770 cpinfos[forward_fieldmethints->thisindex] = fmi;
772 nff = forward_fieldmethints;
773 forward_fieldmethints = forward_fieldmethints->next;
776 /* everything was ok */
782 /* load_field ******************************************************************
784 Load everything about a class field from the class file and fill a
785 'fieldinfo' structure. For static fields, space in the data segment
788 *******************************************************************************/
790 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
792 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
797 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
802 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
805 f->flags = suck_u2(cb);
807 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
812 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
816 f->parseddesc = NULL;
818 if (!descriptor_pool_add(descpool, u, NULL))
821 /* descriptor_pool_add accepts method descriptors, so we have to check */
822 /* against them here before the call of descriptor_to_basic_type below. */
823 if (u->text[0] == '(') {
824 exceptions_throw_classformaterror(c, "Method descriptor used for field");
828 #ifdef ENABLE_VERIFIER
831 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
832 exceptions_throw_classformaterror(c,
833 "Illegal Field name \"%s\"",
838 /* check flag consistency */
839 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
841 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
842 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
843 exceptions_throw_classformaterror(c,
844 "Illegal field modifiers: 0x%X",
849 if (c->flags & ACC_INTERFACE) {
850 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
851 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
852 f->flags & ACC_TRANSIENT) {
853 exceptions_throw_classformaterror(c,
854 "Illegal field modifiers: 0x%X",
860 #endif /* ENABLE_VERIFIER */
862 f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
863 f->offset = 0; /* offset from start of object */
881 if (!(f->flags & ACC_STATIC))
882 c->flags |= ACC_CLASS_HAS_POINTERS;
895 /* read attributes */
896 if (!suck_check_classbuffer_size(cb, 2))
899 attrnum = suck_u2(cb);
900 for (i = 0; i < attrnum; i++) {
901 if (!suck_check_classbuffer_size(cb, 2))
904 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
907 if (u == utf_ConstantValue) {
908 if (!suck_check_classbuffer_size(cb, 4 + 2))
911 /* check attribute length */
913 if (suck_u4(cb) != 2) {
914 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
918 /* constant value attribute */
920 if (pindex != field_load_NOVALUE) {
921 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
925 /* index of value in constantpool */
927 pindex = suck_u2(cb);
929 /* initialize field with value from constantpool */
932 constant_integer *ci;
934 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
937 f->value.i = ci->value;
944 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
947 f->value.l = cl->value;
954 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
957 f->value.f = cf->value;
964 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
967 f->value.d = cd->value;
972 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
975 /* create javastring from compressed utf8-string */
976 f->value.a = literalstring_new(u);
980 log_text("Invalid Constant - Type");
983 else if (u == utf_Signature) {
984 if (!suck_check_classbuffer_size(cb, 4 + 2))
987 /* check attribute length */
989 if (suck_u4(cb) != 2) {
990 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
994 if (f->signature != NULL) {
995 exceptions_throw_classformaterror(c, "Multiple Signature attributes");
999 if (!(f->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1003 /* unknown attribute */
1004 if (!skipattributebody(cb))
1009 /* everything was ok */
1015 /* load_method *****************************************************************
1017 Loads a method from the class file and fills an existing
1018 'methodinfo' structure. For native methods, the function pointer
1019 field is set to the real function pointer, for JavaVM methods a
1020 pointer to the compiler is used preliminarily.
1022 *******************************************************************************/
1024 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1035 #if defined(ENABLE_THREADS)
1036 lock_init_object_lock(&m->header);
1039 #if defined(ENABLE_STATISTICS)
1041 count_all_methods++;
1044 /* all fields of m have been zeroed in load_class_from_classbuffer */
1048 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1051 m->flags = suck_u2(cb);
1053 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1058 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1063 if (!descriptor_pool_add(descpool, u, &argcount))
1066 #ifdef ENABLE_VERIFIER
1068 if (!is_valid_name_utf(m->name)) {
1069 exceptions_throw_classformaterror(c, "Method with invalid name");
1073 if (m->name->text[0] == '<' &&
1074 m->name != utf_init && m->name != utf_clinit) {
1075 exceptions_throw_classformaterror(c, "Method with invalid special name");
1079 #endif /* ENABLE_VERIFIER */
1081 if (!(m->flags & ACC_STATIC))
1082 argcount++; /* count the 'this' argument */
1084 #ifdef ENABLE_VERIFIER
1086 if (argcount > 255) {
1087 exceptions_throw_classformaterror(c, "Too many arguments in signature");
1091 /* check flag consistency */
1092 if (m->name != utf_clinit) {
1093 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1095 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1096 exceptions_throw_classformaterror(c,
1097 "Illegal method modifiers: 0x%X",
1102 if (m->flags & ACC_ABSTRACT) {
1103 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1104 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1105 exceptions_throw_classformaterror(c,
1106 "Illegal method modifiers: 0x%X",
1112 if (c->flags & ACC_INTERFACE) {
1113 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1114 exceptions_throw_classformaterror(c,
1115 "Illegal method modifiers: 0x%X",
1121 if (m->name == utf_init) {
1122 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1123 ACC_NATIVE | ACC_ABSTRACT)) {
1124 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1130 #endif /* ENABLE_VERIFIER */
1132 if (!suck_check_classbuffer_size(cb, 2))
1135 attrnum = suck_u2(cb);
1136 for (i = 0; i < attrnum; i++) {
1139 if (!suck_check_classbuffer_size(cb, 2))
1142 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1145 if (aname == utf_Code) {
1146 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1147 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1152 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1156 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1160 m->maxstack = suck_u2(cb);
1161 m->maxlocals = suck_u2(cb);
1163 if (m->maxlocals < argcount) {
1164 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1168 if (!suck_check_classbuffer_size(cb, 4))
1171 m->jcodelength = suck_u4(cb);
1173 if (m->jcodelength == 0) {
1174 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1178 if (m->jcodelength > 65535) {
1179 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1183 if (!suck_check_classbuffer_size(cb, m->jcodelength))
1186 m->jcode = MNEW(u1, m->jcodelength);
1187 suck_nbytes(m->jcode, cb, m->jcodelength);
1189 if (!suck_check_classbuffer_size(cb, 2))
1192 m->rawexceptiontablelength = suck_u2(cb);
1193 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
1196 m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
1198 #if defined(ENABLE_STATISTICS)
1200 count_vmcode_len += m->jcodelength + 18;
1201 count_extable_len +=
1202 m->rawexceptiontablelength * sizeof(raw_exception_entry);
1206 for (j = 0; j < m->rawexceptiontablelength; j++) {
1208 m->rawexceptiontable[j].startpc = suck_u2(cb);
1209 m->rawexceptiontable[j].endpc = suck_u2(cb);
1210 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
1214 m->rawexceptiontable[j].catchtype.any = NULL;
1217 /* the classref is created later */
1218 if (!(m->rawexceptiontable[j].catchtype.any =
1219 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1224 if (!suck_check_classbuffer_size(cb, 2))
1227 codeattrnum = suck_u2(cb);
1229 for (; codeattrnum > 0; codeattrnum--) {
1232 if (!suck_check_classbuffer_size(cb, 2))
1235 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1238 if (caname == utf_LineNumberTable) {
1241 if (!suck_check_classbuffer_size(cb, 4 + 2))
1245 m->linenumbercount = suck_u2(cb);
1247 if (!suck_check_classbuffer_size(cb,
1248 (2 + 2) * m->linenumbercount))
1251 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1253 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1254 m->linenumbers[lncid].start_pc = suck_u2(cb);
1255 m->linenumbers[lncid].line_number = suck_u2(cb);
1259 if (!skipattributes(cb, codeattrnum))
1265 if (!skipattributebody(cb))
1270 else if (aname == utf_Exceptions) {
1273 if (m->thrownexceptions) {
1274 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1278 if (!suck_check_classbuffer_size(cb, 4 + 2))
1281 suck_u4(cb); /* length */
1282 m->thrownexceptionscount = suck_u2(cb);
1284 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1287 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1289 for (j = 0; j < m->thrownexceptionscount; j++) {
1290 /* the classref is created later */
1291 if (!((m->thrownexceptions)[j].any =
1292 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1296 else if (aname == utf_Signature) {
1297 if (!suck_check_classbuffer_size(cb, 4 + 2))
1300 /* check attribute length */
1302 if (suck_u4(cb) != 2) {
1303 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1307 if (m->signature != NULL) {
1308 exceptions_throw_classformaterror(c, "Multiple Signature attributes");
1312 if (!(m->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1316 if (!skipattributebody(cb))
1321 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1322 exceptions_throw_classformaterror(c, "Missing Code attribute");
1326 /* everything was ok */
1332 /* load_attribute **************************************************************
1334 Read attributes from classfile.
1336 *******************************************************************************/
1338 static bool load_attributes(classbuffer *cb, u4 num)
1346 for (i = 0; i < num; i++) {
1347 /* retrieve attribute name */
1349 if (!suck_check_classbuffer_size(cb, 2))
1352 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1355 if (aname == utf_InnerClasses) {
1356 /* InnerClasses attribute */
1358 if (c->innerclass != NULL) {
1359 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1363 if (!suck_check_classbuffer_size(cb, 4 + 2))
1366 /* skip attribute length */
1369 /* number of records */
1370 c->innerclasscount = suck_u2(cb);
1372 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1375 /* allocate memory for innerclass structure */
1376 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1378 for (j = 0; j < c->innerclasscount; j++) {
1379 /* The innerclass structure contains a class with an encoded
1380 name, its defining scope, its simple name and a bitmask of
1381 the access flags. If an inner class is not a member, its
1382 outer_class is NULL, if a class is anonymous, its name is
1385 innerclassinfo *info = c->innerclass + j;
1387 info->inner_class.ref =
1388 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1389 info->outer_class.ref =
1390 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1392 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1393 info->flags = suck_u2(cb);
1396 else if (aname == utf_SourceFile) {
1397 /* SourceFile attribute */
1399 if (!suck_check_classbuffer_size(cb, 4 + 2))
1402 if (suck_u4(cb) != 2) {
1403 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1407 if (c->sourcefile != NULL) {
1408 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1412 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1415 else if (aname == utf_Signature) {
1416 /* Signature attribute */
1418 if (!suck_check_classbuffer_size(cb, 4 + 2))
1421 if (suck_u4(cb) != 2) {
1422 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1426 if (c->signature != NULL) {
1427 exceptions_throw_classformaterror(c, "Multiple Signature attributes");
1431 if (!(c->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1435 /* unknown attribute */
1437 if (!skipattributebody(cb))
1446 /* load_class_from_sysloader ***************************************************
1448 Load the class with the given name using the system class loader
1451 name.............the classname
1454 the loaded class, or
1455 NULL if an exception has been thrown
1457 *******************************************************************************/
1459 classinfo *load_class_from_sysloader(utf *name)
1462 java_objectheader *cl;
1465 assert(class_java_lang_Object);
1466 assert(class_java_lang_ClassLoader);
1467 assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
1469 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1470 utf_getSystemClassLoader,
1471 utf_void__java_lang_ClassLoader,
1472 class_java_lang_Object,
1478 cl = vm_call_method(m, NULL);
1483 c = load_class_from_classloader(name, cl);
1489 /* load_class_from_classloader *************************************************
1491 Load the class with the given name using the given user-defined class loader.
1494 name.............the classname
1495 cl...............user-defined class loader
1498 the loaded class, or
1499 NULL if an exception has been thrown
1501 *******************************************************************************/
1503 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1505 java_objectheader *o;
1508 java_lang_String *s;
1509 #if defined(ENABLE_RT_TIMING)
1510 struct timespec time_start, time_lookup, time_prepare, time_java,
1514 RT_TIMING_GET_TIME(time_start);
1518 /* lookup if this class has already been loaded */
1520 c = classcache_lookup(cl, name);
1522 RT_TIMING_GET_TIME(time_lookup);
1523 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
1528 /* if other class loader than bootstrap, call it */
1536 namelen = name->blength;
1538 /* handle array classes */
1539 if (text[0] == '[') {
1545 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1546 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1547 *exceptionptr = new_noclassdeffounderror(name);
1551 u = utf_new(text + 2, namelen - 3);
1553 if (!(comp = load_class_from_classloader(u, cl)))
1556 /* create the array class */
1558 c = class_array_of(comp, false);
1560 tmpc = classcache_store(cl, c, true);
1563 /* exception, free the loaded class */
1564 c->state &= ~CLASS_LOADING;
1571 /* load the component class */
1573 u = utf_new(text + 1, namelen - 1);
1575 if (!(comp = load_class_from_classloader(u, cl)))
1578 /* create the array class */
1580 c = class_array_of(comp, false);
1582 tmpc = classcache_store(cl, c, true);
1585 /* exception, free the loaded class */
1586 c->state &= ~CLASS_LOADING;
1593 /* primitive array classes are loaded by the bootstrap loader */
1595 c = load_class_bootstrap(name);
1601 assert(class_java_lang_Object);
1603 lc = class_resolveclassmethod(cl->vftbl->class,
1605 utf_java_lang_String__java_lang_Class,
1606 class_java_lang_Object,
1610 return false; /* exception */
1612 /* move return value into `o' and cast it afterwards to a classinfo* */
1614 s = javastring_new_slash_to_dot(name);
1616 RT_TIMING_GET_TIME(time_prepare);
1618 o = vm_call_method(lc, cl, s);
1620 RT_TIMING_GET_TIME(time_java);
1622 c = (classinfo *) o;
1625 /* Store this class in the loaded class cache. If another
1626 class with the same (initloader,name) pair has been
1627 stored earlier it will be returned by classcache_store
1628 In this case classcache_store may not free the class
1629 because it has already been exposed to Java code which
1630 may have kept references to that class. */
1632 tmpc = classcache_store(cl, c, false);
1635 /* exception, free the loaded class */
1636 c->state &= ~CLASS_LOADING;
1643 /* loadClass has thrown an exception. We must convert
1644 ClassNotFoundException into
1645 NoClassDefFoundException. */
1647 /* XXX Maybe we should have a flag that avoids this
1648 conversion for calling load_class_from_classloader from
1649 Class.forName. Currently we do a double conversion in
1652 classnotfoundexception_to_noclassdeffounderror();
1655 RT_TIMING_GET_TIME(time_cache);
1657 RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
1658 RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
1659 RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
1661 /* SUN compatible -verbose:class output */
1663 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1665 utf_display_printable_ascii_classname(name);
1669 #if defined(ENABLE_JVMTI)
1670 /* fire Class Load JVMTI event */
1671 if (jvmti) jvmti_ClassLoadPrepare(false, c);
1678 c = load_class_bootstrap(name);
1684 /* load_class_bootstrap ********************************************************
1686 Load the class with the given name using the bootstrap class loader.
1689 name.............the classname
1692 loaded classinfo, or
1693 NULL if an exception has been thrown
1696 load_class_bootstrap is synchronized. It can be treated as an
1699 *******************************************************************************/
1701 classinfo *load_class_bootstrap(utf *name)
1706 #if defined(ENABLE_RT_TIMING)
1707 struct timespec time_start, time_lookup, time_array, time_suck,
1708 time_load, time_cache;
1711 RT_TIMING_GET_TIME(time_start);
1717 /* lookup if this class has already been loaded */
1719 if ((r = classcache_lookup(NULL, name))) {
1721 RT_TIMING_GET_TIME(time_lookup);
1722 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1727 RT_TIMING_GET_TIME(time_lookup);
1728 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1730 /* create the classinfo */
1732 c = class_create_classinfo(name);
1734 /* handle array classes */
1736 if (name->text[0] == '[') {
1737 c = load_newly_created_array(c, NULL);
1740 assert(c->state & CLASS_LOADED);
1742 RT_TIMING_GET_TIME(time_array);
1743 RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
1748 #if defined(ENABLE_STATISTICS)
1751 if (opt_getcompilingtime)
1752 compilingtime_stop();
1754 if (opt_getloadingtime)
1755 loadingtime_start();
1758 /* load classdata, throw exception on error */
1760 if ((cb = suck_start(c)) == NULL) {
1761 /* this normally means, the classpath was not set properly */
1763 if (name == utf_java_lang_Object)
1764 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1765 "java/lang/Object");
1767 *exceptionptr = new_noclassdeffounderror(name);
1772 RT_TIMING_GET_TIME(time_suck);
1774 /* load the class from the buffer */
1776 r = load_class_from_classbuffer(cb);
1778 RT_TIMING_GET_TIME(time_load);
1781 /* the class could not be loaded, free the classinfo struct */
1786 /* Store this class in the loaded class cache this step also
1787 checks the loading constraints. If the class has been loaded
1788 before, the earlier loaded class is returned. */
1790 classinfo *res = classcache_store(NULL, c, true);
1800 RT_TIMING_GET_TIME(time_cache);
1802 /* SUN compatible -verbose:class output */
1804 if (opt_verboseclass && r) {
1806 utf_display_printable_ascii_classname(name);
1807 printf(" from %s]\n", cb->path);
1814 #if defined(ENABLE_STATISTICS)
1817 if (opt_getloadingtime)
1820 if (opt_getcompilingtime)
1821 compilingtime_start();
1824 RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
1825 RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
1826 RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
1827 RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
1833 /* load_class_from_classbuffer *************************************************
1835 Loads everything interesting about a class from the class file. The
1836 'classinfo' structure must have been allocated previously.
1838 The super class and the interfaces implemented by this class need
1839 not be loaded. The link is set later by the function 'class_link'.
1841 The loaded class is removed from the list 'unloadedclasses' and
1842 added to the list 'unlinkedclasses'.
1845 This function is NOT synchronized!
1847 *******************************************************************************/
1849 classinfo *load_class_from_classbuffer(classbuffer *cb)
1857 descriptor_pool *descpool;
1858 #if defined(ENABLE_STATISTICS)
1862 #if defined(ENABLE_RT_TIMING)
1863 struct timespec time_start, time_checks, time_ndpool, time_cpool,
1864 time_setup, time_fields, time_methods, time_classrefs,
1865 time_descs, time_setrefs, time_parsefds, time_parsemds,
1866 time_parsecpool, time_verify, time_attrs;
1869 RT_TIMING_GET_TIME(time_start);
1871 /* get the classbuffer's class */
1875 /* the class is already loaded */
1877 if (c->state & CLASS_LOADED)
1880 #if defined(ENABLE_STATISTICS)
1882 count_class_loads++;
1885 #if !defined(NDEBUG)
1886 /* output for debugging purposes */
1889 log_message_class("Loading class: ", c);
1892 /* mark start of dump memory area */
1894 dumpsize = dump_size();
1896 /* class is currently loading */
1898 c->state |= CLASS_LOADING;
1900 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1901 goto return_exception;
1903 /* check signature */
1905 if (suck_u4(cb) != MAGIC) {
1906 exceptions_throw_classformaterror(c, "Bad magic number");
1908 goto return_exception;
1916 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1918 new_unsupportedclassversionerror(c,
1919 "Unsupported major.minor version %d.%d",
1922 goto return_exception;
1924 RT_TIMING_GET_TIME(time_checks);
1926 /* create a new descriptor pool */
1928 descpool = descriptor_pool_new(c);
1930 RT_TIMING_GET_TIME(time_ndpool);
1932 /* load the constant pool */
1934 if (!load_constantpool(cb, descpool))
1935 goto return_exception;
1937 RT_TIMING_GET_TIME(time_cpool);
1941 if (!suck_check_classbuffer_size(cb, 2))
1942 goto return_exception;
1944 c->flags = suck_u2(cb);
1946 /* check ACC flags consistency */
1948 if (c->flags & ACC_INTERFACE) {
1949 if (!(c->flags & ACC_ABSTRACT)) {
1950 /* We work around this because interfaces in JDK 1.1 are
1951 * not declared abstract. */
1953 c->flags |= ACC_ABSTRACT;
1956 if (c->flags & ACC_FINAL) {
1957 exceptions_throw_classformaterror(c,
1958 "Illegal class modifiers: 0x%X",
1960 goto return_exception;
1963 if (c->flags & ACC_SUPER) {
1964 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1968 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1969 exceptions_throw_classformaterror(c,
1970 "Illegal class modifiers: 0x%X",
1972 goto return_exception;
1975 if (!suck_check_classbuffer_size(cb, 2 + 2))
1976 goto return_exception;
1981 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1982 goto return_exception;
1984 if (c->name == utf_not_named_yet) {
1985 /* we finally have a name for this class */
1987 class_set_packagename(c);
1989 } else if (name != c->name) {
1993 msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
1994 utf_bytes(name) + strlen(")") + strlen("0");
1996 msg = MNEW(char, msglen);
1998 utf_copy_classname(msg, c->name);
1999 strcat(msg, " (wrong name: ");
2000 utf_cat_classname(msg, name);
2004 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2006 MFREE(msg, char, msglen);
2008 goto return_exception;
2011 /* retrieve superclass */
2013 c->super.any = NULL;
2014 if ((i = suck_u2(cb))) {
2015 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2016 goto return_exception;
2018 /* java.lang.Object may not have a super class. */
2020 if (c->name == utf_java_lang_Object) {
2022 new_exception_message(string_java_lang_ClassFormatError,
2023 "java.lang.Object with superclass");
2025 goto return_exception;
2028 /* Interfaces must have java.lang.Object as super class. */
2030 if ((c->flags & ACC_INTERFACE) &&
2031 supername != utf_java_lang_Object) {
2033 new_exception_message(string_java_lang_ClassFormatError,
2034 "Interfaces must have java.lang.Object as superclass");
2036 goto return_exception;
2042 /* This is only allowed for java.lang.Object. */
2044 if (c->name != utf_java_lang_Object) {
2045 exceptions_throw_classformaterror(c, "Bad superclass index");
2046 goto return_exception;
2050 /* retrieve interfaces */
2052 if (!suck_check_classbuffer_size(cb, 2))
2053 goto return_exception;
2055 c->interfacescount = suck_u2(cb);
2057 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
2058 goto return_exception;
2060 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2061 for (i = 0; i < c->interfacescount; i++) {
2062 /* the classrefs are created later */
2063 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2064 goto return_exception;
2067 RT_TIMING_GET_TIME(time_setup);
2070 if (!suck_check_classbuffer_size(cb, 2))
2071 goto return_exception;
2073 c->fieldscount = suck_u2(cb);
2074 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2075 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2076 for (i = 0; i < c->fieldscount; i++) {
2077 if (!load_field(cb, &(c->fields[i]),descpool))
2078 goto return_exception;
2081 RT_TIMING_GET_TIME(time_fields);
2084 if (!suck_check_classbuffer_size(cb, 2))
2085 goto return_exception;
2087 c->methodscount = suck_u2(cb);
2088 c->methods = MNEW(methodinfo, c->methodscount);
2090 MZERO(c->methods, methodinfo, c->methodscount);
2092 for (i = 0; i < c->methodscount; i++) {
2093 if (!load_method(cb, &(c->methods[i]),descpool))
2094 goto return_exception;
2097 RT_TIMING_GET_TIME(time_methods);
2099 /* create the class reference table */
2102 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2104 RT_TIMING_GET_TIME(time_classrefs);
2106 /* allocate space for the parsed descriptors */
2108 descriptor_pool_alloc_parsed_descriptors(descpool);
2110 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2112 #if defined(ENABLE_STATISTICS)
2114 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2115 count_classref_len += classrefsize;
2116 count_parsed_desc_len += descsize;
2120 RT_TIMING_GET_TIME(time_descs);
2122 /* put the classrefs in the constant pool */
2123 for (i = 0; i < c->cpcount; i++) {
2124 if (c->cptags[i] == CONSTANT_Class) {
2125 utf *name = (utf *) c->cpinfos[i];
2126 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2130 /* set the super class reference */
2133 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2135 goto return_exception;
2138 /* set the super interfaces references */
2140 for (i = 0; i < c->interfacescount; i++) {
2141 c->interfaces[i].ref =
2142 descriptor_pool_lookup_classref(descpool,
2143 (utf *) c->interfaces[i].any);
2144 if (!c->interfaces[i].ref)
2145 goto return_exception;
2148 RT_TIMING_GET_TIME(time_setrefs);
2150 /* parse field descriptors */
2152 for (i = 0; i < c->fieldscount; i++) {
2153 c->fields[i].parseddesc =
2154 descriptor_pool_parse_field_descriptor(descpool,
2155 c->fields[i].descriptor);
2156 if (!c->fields[i].parseddesc)
2157 goto return_exception;
2160 RT_TIMING_GET_TIME(time_parsefds);
2162 /* parse method descriptors */
2164 for (i = 0; i < c->methodscount; i++) {
2165 methodinfo *m = &c->methods[i];
2167 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2168 m->flags, class_get_self_classref(m->class));
2170 goto return_exception;
2172 for (j = 0; j < m->rawexceptiontablelength; j++) {
2173 if (!m->rawexceptiontable[j].catchtype.any)
2175 if ((m->rawexceptiontable[j].catchtype.ref =
2176 descriptor_pool_lookup_classref(descpool,
2177 (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
2178 goto return_exception;
2181 for (j = 0; j < m->thrownexceptionscount; j++) {
2182 if (!m->thrownexceptions[j].any)
2184 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2185 (utf *) m->thrownexceptions[j].any)) == NULL)
2186 goto return_exception;
2190 RT_TIMING_GET_TIME(time_parsemds);
2192 /* parse the loaded descriptors */
2194 for (i = 0; i < c->cpcount; i++) {
2195 constant_FMIref *fmi;
2198 switch (c->cptags[i]) {
2199 case CONSTANT_Fieldref:
2200 fmi = (constant_FMIref *) c->cpinfos[i];
2201 fmi->parseddesc.fd =
2202 descriptor_pool_parse_field_descriptor(descpool,
2204 if (!fmi->parseddesc.fd)
2205 goto return_exception;
2206 index = fmi->p.index;
2208 (constant_classref *) class_getconstant(c, index,
2210 if (!fmi->p.classref)
2211 goto return_exception;
2213 case CONSTANT_Methodref:
2214 case CONSTANT_InterfaceMethodref:
2215 fmi = (constant_FMIref *) c->cpinfos[i];
2216 index = fmi->p.index;
2218 (constant_classref *) class_getconstant(c, index,
2220 if (!fmi->p.classref)
2221 goto return_exception;
2222 fmi->parseddesc.md =
2223 descriptor_pool_parse_method_descriptor(descpool,
2227 if (!fmi->parseddesc.md)
2228 goto return_exception;
2233 RT_TIMING_GET_TIME(time_parsecpool);
2235 #ifdef ENABLE_VERIFIER
2236 /* Check if all fields and methods can be uniquely
2237 * identified by (name,descriptor). */
2240 /* We use a hash table here to avoid making the
2241 * average case quadratic in # of methods, fields.
2243 static int shift = 0;
2245 u2 *next; /* for chaining colliding hash entries */
2251 /* Allocate hashtable */
2252 len = c->methodscount;
2253 if (len < c->fieldscount) len = c->fieldscount;
2255 hashtab = MNEW(u2,(hashlen + len));
2256 next = hashtab + hashlen;
2258 /* Determine bitshift (to get good hash values) */
2268 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2270 for (i = 0; i < c->fieldscount; ++i) {
2271 fieldinfo *fi = c->fields + i;
2273 /* It's ok if we lose bits here */
2274 index = ((((size_t) fi->name) +
2275 ((size_t) fi->descriptor)) >> shift) % hashlen;
2277 if ((old = hashtab[index])) {
2281 if (c->fields[old].name == fi->name &&
2282 c->fields[old].descriptor == fi->descriptor) {
2283 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2284 goto return_exception;
2286 } while ((old = next[old]));
2288 hashtab[index] = i + 1;
2292 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2294 for (i = 0; i < c->methodscount; ++i) {
2295 methodinfo *mi = c->methods + i;
2297 /* It's ok if we lose bits here */
2298 index = ((((size_t) mi->name) +
2299 ((size_t) mi->descriptor)) >> shift) % hashlen;
2303 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2304 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2308 if ((old = hashtab[index])) {
2312 if (c->methods[old].name == mi->name &&
2313 c->methods[old].descriptor == mi->descriptor) {
2314 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2315 goto return_exception;
2317 } while ((old = next[old]));
2319 hashtab[index] = i + 1;
2322 MFREE(hashtab, u2, (hashlen + len));
2324 #endif /* ENABLE_VERIFIER */
2326 RT_TIMING_GET_TIME(time_verify);
2328 #if defined(ENABLE_STATISTICS)
2330 size_classinfo += sizeof(classinfo*) * c->interfacescount;
2331 size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
2332 size_methodinfo += sizeof(methodinfo) * c->methodscount;
2336 /* load attribute structures */
2338 if (!suck_check_classbuffer_size(cb, 2))
2339 goto return_exception;
2341 if (!load_attributes(cb, suck_u2(cb)))
2342 goto return_exception;
2344 /* Pre Java 1.5 version don't check this. This implementation is like
2345 Java 1.5 do it: for class file version 45.3 we don't check it, older
2346 versions are checked.
2349 if (((ma == 45) && (mi > 3)) || (ma > 45)) {
2350 /* check if all data has been read */
2351 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2353 if (classdata_left > 0) {
2354 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2355 goto return_exception;
2359 RT_TIMING_GET_TIME(time_attrs);
2361 /* release dump area */
2363 dump_release(dumpsize);
2365 /* revert loading state and class is loaded */
2367 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2369 #if defined(ENABLE_JVMTI)
2370 /* fire Class Prepare JVMTI event */
2373 jvmti_ClassLoadPrepare(true, c);
2376 #if !defined(NDEBUG)
2378 log_message_class("Loading done class: ", c);
2381 RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
2382 RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
2383 RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
2384 RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
2385 RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
2386 RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
2387 RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
2388 RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
2389 RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
2390 RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
2391 RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
2392 RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
2393 RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
2394 RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
2395 RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
2400 /* release dump area */
2402 dump_release(dumpsize);
2404 /* an exception has been thrown */
2410 /* load_newly_created_array ****************************************************
2412 Load a newly created array class.
2415 c....................the array class C has been loaded
2416 other classinfo......the array class was found in the class cache,
2418 NULL.................an exception has been thrown
2421 This is an internal function. Do not use it unless you know exactly
2424 Use one of the load_class_... functions for general array class loading.
2426 *******************************************************************************/
2428 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2430 classinfo *comp = NULL;
2432 methoddesc *clonedesc;
2433 constant_classref *classrefs;
2438 text = c->name->text;
2439 namelen = c->name->blength;
2441 /* Check array class name */
2443 if (namelen < 2 || text[0] != '[') {
2444 *exceptionptr = new_noclassdeffounderror(c->name);
2448 /* Check the element type */
2452 /* c is an array of arrays. We have to create the component class. */
2454 u = utf_new(text + 1, namelen - 1);
2455 if (!(comp = load_class_from_classloader(u, loader)))
2458 assert(comp->state & CLASS_LOADED);
2464 /* the array's flags are that of the component class */
2465 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2466 c->classloader = comp->classloader;
2470 /* c is an array of objects. */
2472 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2473 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2474 *exceptionptr = new_noclassdeffounderror(c->name);
2478 u = utf_new(text + 2, namelen - 3);
2480 if (!(comp = load_class_from_classloader(u, loader)))
2483 assert(comp->state & CLASS_LOADED);
2489 /* the array's flags are that of the component class */
2490 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2491 c->classloader = comp->classloader;
2495 /* c is an array of a primitive type */
2497 /* check for cases like `[II' */
2499 *exceptionptr = new_noclassdeffounderror(c->name);
2503 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2504 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2505 c->classloader = NULL;
2508 assert(class_java_lang_Object);
2509 assert(class_java_lang_Cloneable);
2510 assert(class_java_io_Serializable);
2512 /* setup the array class */
2514 c->super.cls = class_java_lang_Object;
2516 c->interfacescount = 2;
2517 c->interfaces = MNEW(classref_or_classinfo, 2);
2522 tc = class_java_lang_Cloneable;
2523 assert(tc->state & CLASS_LOADED);
2524 list_add_first(&unlinkedclasses, tc);
2525 c->interfaces[0].cls = tc;
2527 tc = class_java_io_Serializable;
2528 assert(tc->state & CLASS_LOADED);
2529 list_add_first(&unlinkedclasses, tc);
2530 c->interfaces[1].cls = tc;
2533 c->interfaces[0].cls = class_java_lang_Cloneable;
2534 c->interfaces[1].cls = class_java_io_Serializable;
2537 c->methodscount = 1;
2538 c->methods = MNEW(methodinfo, c->methodscount);
2539 MZERO(c->methods, methodinfo, c->methodscount);
2541 classrefs = MNEW(constant_classref, 2);
2542 CLASSREF_INIT(classrefs[0], c, c->name);
2543 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2545 /* create descriptor for clone method */
2546 /* we need one paramslot which is reserved for the 'this' parameter */
2547 clonedesc = NEW(methoddesc);
2548 clonedesc->returntype.type = TYPE_ADR;
2549 clonedesc->returntype.classref = classrefs + 1;
2550 clonedesc->returntype.arraydim = 0;
2551 /* initialize params to "empty", add real params below in
2552 descriptor_params_from_paramtypes */
2553 clonedesc->paramcount = 0;
2554 clonedesc->paramslots = 0;
2555 clonedesc->paramtypes[0].classref = classrefs + 0;
2556 clonedesc->params = NULL;
2558 /* create methodinfo */
2561 MSET(clone, 0, methodinfo, 1);
2563 #if defined(ENABLE_THREADS)
2564 lock_init_object_lock(&clone->header);
2567 /* ATTENTION: if you delete the ACC_NATIVE below, set
2568 clone->maxlocals=1 (interpreter related) */
2570 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2571 clone->name = utf_clone;
2572 clone->descriptor = utf_void__java_lang_Object;
2573 clone->parseddesc = clonedesc;
2576 /* parse the descriptor to get the register allocation */
2578 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2582 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2584 /* XXX: field: length? */
2586 /* array classes are not loaded from class files */
2588 c->state |= CLASS_LOADED;
2589 c->parseddescs = (u1 *) clonedesc;
2590 c->parseddescsize = sizeof(methodinfo);
2591 c->classrefs = classrefs;
2592 c->classrefcount = 1;
2594 /* insert class into the loaded class cache */
2595 /* XXX free classinfo if NULL returned? */
2597 return classcache_store(loader, c, true);
2601 /* loader_close ****************************************************************
2603 Frees all resources.
2605 *******************************************************************************/
2607 void loader_close(void)
2614 * These are local overrides for various environment variables in Emacs.
2615 * Please do not remove this and leave it at the end of the file, where
2616 * Emacs will automagically detect them.
2617 * ---------------------------------------------------------------------
2620 * indent-tabs-mode: t
2624 * vim:noexpandtab:sw=4:ts=4: