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
29 Changes: Andreas Krall
35 $Id: loader.c 4402 2006-02-02 08:51:32Z twisti $
48 #include "mm/memory.h"
49 #include "native/native.h"
50 #include "native/include/java_lang_Throwable.h"
52 #if defined(USE_THREADS)
53 # if defined(NATIVE_THREADS)
54 # include "threads/native/threads.h"
56 # include "threads/green/threads.h"
57 # include "threads/green/locks.h"
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/classcache.h"
64 #include "vm/exceptions.h"
65 #include "vm/global.h"
66 #include "vm/linker.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/statistics.h"
70 #include "vm/stringlocal.h"
73 #if defined(ENABLE_ZLIB)
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/codegen-common.h"
81 /******************************************************************************/
83 /******************************************************************************/
90 #define LOADER_ASSERT(cond) assert(cond)
92 #define LOADER_ASSERT(cond)
96 /* loader_init *****************************************************************
98 Initializes all lists and loads all classes required for the system
101 *******************************************************************************/
103 bool loader_init(u1 *stackbottom)
105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
106 list_classpath_entry *lce;
108 /* Initialize the monitor pointer for zip/jar file locking. */
110 for (lce = list_first(list_classpath_entries); lce != NULL;
111 lce = list_next(list_classpath_entries, lce))
112 if (lce->type == CLASSPATH_ARCHIVE)
113 initObjectLock((java_objectheader *) lce);
116 /* load some important classes */
118 if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
121 if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
124 if (!(class_java_lang_Cloneable =
125 load_class_bootstrap(utf_java_lang_Cloneable)))
128 if (!(class_java_io_Serializable =
129 load_class_bootstrap(utf_java_io_Serializable)))
133 /* load classes for wrapping primitive types */
135 if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
138 if (!(class_java_lang_Boolean =
139 load_class_bootstrap(utf_java_lang_Boolean)))
142 if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
145 if (!(class_java_lang_Character =
146 load_class_bootstrap(utf_java_lang_Character)))
149 if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
152 if (!(class_java_lang_Integer =
153 load_class_bootstrap(utf_java_lang_Integer)))
156 if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
159 if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
162 if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
166 /* load some other important classes */
168 if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
171 if (!(class_java_lang_ClassLoader =
172 load_class_bootstrap(utf_java_lang_ClassLoader)))
175 if (!(class_java_lang_SecurityManager =
176 load_class_bootstrap(utf_java_lang_SecurityManager)))
179 if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
182 if (!(class_java_lang_Thread =
183 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
186 if (!(class_java_lang_ThreadGroup =
187 load_class_bootstrap(utf_java_lang_ThreadGroup)))
190 if (!(class_java_lang_VMThread =
191 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
195 /* some classes which may be used more often */
197 if (!(class_java_lang_StackTraceElement =
198 load_class_bootstrap(utf_java_lang_StackTraceElement)))
201 if (!(class_java_lang_reflect_Constructor =
202 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
205 if (!(class_java_lang_reflect_Field =
206 load_class_bootstrap(utf_java_lang_reflect_Field)))
209 if (!(class_java_lang_reflect_Method =
210 load_class_bootstrap(utf_java_lang_reflect_Method)))
213 if (!(class_java_security_PrivilegedAction =
214 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
217 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
220 if (!(arrayclass_java_lang_Object =
221 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
224 #if defined(USE_THREADS)
225 if (stackbottom != 0)
233 /* loader_load_all_classes *****************************************************
235 Loads all classes specified in the BOOTCLASSPATH.
237 *******************************************************************************/
239 void loader_load_all_classes(void)
241 list_classpath_entry *lce;
242 #if defined(ENABLE_ZLIB)
245 hashtable_zipfile_entry *htzfe;
249 for (lce = list_first(list_classpath_entries); lce != NULL;
250 lce = list_next(list_classpath_entries, lce)) {
251 #if defined(ENABLE_ZLIB)
252 if (lce->type == CLASSPATH_ARCHIVE) {
253 /* get the classes hashtable */
257 for (slot = 0; slot < ht->size; slot++) {
258 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
260 for (; htzfe; htzfe = htzfe->hashlink) {
263 /* skip all entries in META-INF and .properties,
266 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
267 strstr(u->text, ".properties") ||
268 strstr(u->text, ".png"))
271 /* load class from bootstrap classloader */
273 if (!load_class_bootstrap(u)) {
274 fprintf(stderr, "Error loading: ");
275 utf_fprint_classname(stderr, u);
276 fprintf(stderr, "\n");
278 /* print out exception and cause */
280 exceptions_print_exception(*exceptionptr);
287 #if defined(ENABLE_ZLIB)
294 /* skipattributebody ***********************************************************
296 Skips an attribute after the 16 bit reference to attribute_name has
299 *******************************************************************************/
301 static bool skipattributebody(classbuffer *cb)
305 if (!suck_check_classbuffer_size(cb, 4))
310 if (!suck_check_classbuffer_size(cb, len))
313 suck_skip_nbytes(cb, len);
319 /************************* Function: skipattributes ****************************
321 skips num attribute structures
323 *******************************************************************************/
325 static bool skipattributes(classbuffer *cb, u4 num)
330 for (i = 0; i < num; i++) {
331 if (!suck_check_classbuffer_size(cb, 2 + 4))
337 if (!suck_check_classbuffer_size(cb, len))
340 suck_skip_nbytes(cb, len);
347 /* load_constantpool ***********************************************************
349 Loads the constantpool of a class, the entries are transformed into
350 a simpler format by resolving references (a detailed overview of
351 the compact structures can be found in global.h).
353 *******************************************************************************/
355 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
358 /* The following structures are used to save information which cannot be
359 processed during the first pass. After the complete constantpool has
360 been traversed the references can be resolved.
361 (only in specific order) */
363 /* CONSTANT_Class entries */
364 typedef struct forward_class {
365 struct forward_class *next;
370 /* CONSTANT_String */
371 typedef struct forward_string {
372 struct forward_string *next;
377 /* CONSTANT_NameAndType */
378 typedef struct forward_nameandtype {
379 struct forward_nameandtype *next;
383 } forward_nameandtype;
385 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
386 typedef struct forward_fieldmethint {
387 struct forward_fieldmethint *next;
391 u2 nameandtype_index;
392 } forward_fieldmethint;
398 forward_class *forward_classes = NULL;
399 forward_string *forward_strings = NULL;
400 forward_nameandtype *forward_nameandtypes = NULL;
401 forward_fieldmethint *forward_fieldmethints = NULL;
405 forward_nameandtype *nfn;
406 forward_fieldmethint *nff;
414 /* number of entries in the constant_pool table plus one */
415 if (!suck_check_classbuffer_size(cb, 2))
418 cpcount = c->cpcount = suck_u2(cb);
420 /* allocate memory */
421 cptags = c->cptags = MNEW(u1, cpcount);
422 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
425 exceptions_throw_classformaterror(c, "Illegal constant pool size");
429 #if defined(ENABLE_STATISTICS)
431 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
434 /* initialize constantpool */
435 for (idx = 0; idx < cpcount; idx++) {
436 cptags[idx] = CONSTANT_UNUSED;
441 /******* first pass *******/
442 /* entries which cannot be resolved now are written into
443 temporary structures and traversed again later */
446 while (idx < cpcount) {
449 /* get constant type */
450 if (!suck_check_classbuffer_size(cb, 1))
457 nfc = DNEW(forward_class);
459 nfc->next = forward_classes;
460 forward_classes = nfc;
462 nfc->thisindex = idx;
463 /* reference to CONSTANT_NameAndType */
464 if (!suck_check_classbuffer_size(cb, 2))
467 nfc->name_index = suck_u2(cb);
472 case CONSTANT_String:
473 nfs = DNEW(forward_string);
475 nfs->next = forward_strings;
476 forward_strings = nfs;
478 nfs->thisindex = idx;
480 /* reference to CONSTANT_Utf8_info with string characters */
481 if (!suck_check_classbuffer_size(cb, 2))
484 nfs->string_index = suck_u2(cb);
489 case CONSTANT_NameAndType:
490 nfn = DNEW(forward_nameandtype);
492 nfn->next = forward_nameandtypes;
493 forward_nameandtypes = nfn;
495 nfn->thisindex = idx;
497 if (!suck_check_classbuffer_size(cb, 2 + 2))
500 /* reference to CONSTANT_Utf8_info containing simple name */
501 nfn->name_index = suck_u2(cb);
503 /* reference to CONSTANT_Utf8_info containing field or method
505 nfn->sig_index = suck_u2(cb);
510 case CONSTANT_Fieldref:
511 case CONSTANT_Methodref:
512 case CONSTANT_InterfaceMethodref:
513 nff = DNEW(forward_fieldmethint);
515 nff->next = forward_fieldmethints;
516 forward_fieldmethints = nff;
518 nff->thisindex = idx;
522 if (!suck_check_classbuffer_size(cb, 2 + 2))
525 /* class or interface type that contains the declaration of the
527 nff->class_index = suck_u2(cb);
529 /* name and descriptor of the field or method */
530 nff->nameandtype_index = suck_u2(cb);
535 case CONSTANT_Integer: {
536 constant_integer *ci = NEW(constant_integer);
538 #if defined(ENABLE_STATISTICS)
540 count_const_pool_len += sizeof(constant_integer);
543 if (!suck_check_classbuffer_size(cb, 4))
546 ci->value = suck_s4(cb);
547 cptags[idx] = CONSTANT_Integer;
554 case CONSTANT_Float: {
555 constant_float *cf = NEW(constant_float);
557 #if defined(ENABLE_STATISTICS)
559 count_const_pool_len += sizeof(constant_float);
562 if (!suck_check_classbuffer_size(cb, 4))
565 cf->value = suck_float(cb);
566 cptags[idx] = CONSTANT_Float;
573 case CONSTANT_Long: {
574 constant_long *cl = NEW(constant_long);
576 #if defined(ENABLE_STATISTICS)
578 count_const_pool_len += sizeof(constant_long);
581 if (!suck_check_classbuffer_size(cb, 8))
584 cl->value = suck_s8(cb);
585 cptags[idx] = CONSTANT_Long;
589 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
595 case CONSTANT_Double: {
596 constant_double *cd = NEW(constant_double);
598 #if defined(ENABLE_STATISTICS)
600 count_const_pool_len += sizeof(constant_double);
603 if (!suck_check_classbuffer_size(cb, 8))
606 cd->value = suck_double(cb);
607 cptags[idx] = CONSTANT_Double;
611 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
617 case CONSTANT_Utf8: {
620 /* number of bytes in the bytes array (not string-length) */
621 if (!suck_check_classbuffer_size(cb, 2))
624 length = suck_u2(cb);
625 cptags[idx] = CONSTANT_Utf8;
627 /* validate the string */
628 if (!suck_check_classbuffer_size(cb, length))
631 #ifdef ENABLE_VERIFIER
633 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
635 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
638 #endif /* ENABLE_VERIFIER */
639 /* insert utf-string into the utf-symboltable */
640 cpinfos[idx] = utf_new((char *) cb->pos, length);
642 /* skip bytes of the string (buffer size check above) */
643 suck_skip_nbytes(cb, length);
649 exceptions_throw_classformaterror(c, "Illegal constant pool type");
655 /* resolve entries in temporary structures */
657 while (forward_classes) {
659 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
663 #ifdef ENABLE_VERIFIER
664 if (opt_verify && !is_valid_name_utf(name)) {
665 exceptions_throw_classformaterror(c, "Class reference with invalid name");
668 #endif /* ENABLE_VERIFIER */
670 /* add all class references to the descriptor_pool */
672 if (!descriptor_pool_add_class(descpool, name))
675 cptags[forward_classes->thisindex] = CONSTANT_Class;
680 if (!(tc = load_class_bootstrap(name)))
683 /* link the class later, because we cannot link the class currently
685 list_addfirst(&unlinkedclasses, tc);
688 /* the classref is created later */
689 cpinfos[forward_classes->thisindex] = name;
691 nfc = forward_classes;
692 forward_classes = forward_classes->next;
695 while (forward_strings) {
697 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
701 /* resolve utf-string */
702 cptags[forward_strings->thisindex] = CONSTANT_String;
703 cpinfos[forward_strings->thisindex] = text;
705 nfs = forward_strings;
706 forward_strings = forward_strings->next;
709 while (forward_nameandtypes) {
710 constant_nameandtype *cn = NEW(constant_nameandtype);
712 #if defined(ENABLE_STATISTICS)
714 count_const_pool_len += sizeof(constant_nameandtype);
717 /* resolve simple name and descriptor */
718 cn->name = class_getconstant(c,
719 forward_nameandtypes->name_index,
724 cn->descriptor = class_getconstant(c,
725 forward_nameandtypes->sig_index,
730 #ifdef ENABLE_VERIFIER
733 if (!is_valid_name_utf(cn->name)) {
734 exceptions_throw_classformaterror(c,
735 "Illegal Field name \"%s\"",
741 /* disallow referencing <clinit> among others */
742 if (cn->name->text[0] == '<' && cn->name != utf_init) {
743 exceptions_throw_classformaterror(c, "Illegal reference to special method");
747 #endif /* ENABLE_VERIFIER */
749 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
750 cpinfos[forward_nameandtypes->thisindex] = cn;
752 nfn = forward_nameandtypes;
753 forward_nameandtypes = forward_nameandtypes->next;
756 while (forward_fieldmethints) {
757 constant_nameandtype *nat;
758 constant_FMIref *fmi = NEW(constant_FMIref);
760 #if defined(ENABLE_STATISTICS)
762 count_const_pool_len += sizeof(constant_FMIref);
764 /* resolve simple name and descriptor */
766 nat = class_getconstant(c,
767 forward_fieldmethints->nameandtype_index,
768 CONSTANT_NameAndType);
772 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
774 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
777 /* the classref is created later */
779 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
780 fmi->name = nat->name;
781 fmi->descriptor = nat->descriptor;
783 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
784 cpinfos[forward_fieldmethints->thisindex] = fmi;
786 nff = forward_fieldmethints;
787 forward_fieldmethints = forward_fieldmethints->next;
790 /* everything was ok */
796 /* load_field ******************************************************************
798 Load everything about a class field from the class file and fill a
799 'fieldinfo' structure. For static fields, space in the data segment
802 *******************************************************************************/
804 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
806 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
811 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
816 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
819 f->flags = suck_u2(cb);
821 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
826 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
830 f->parseddesc = NULL;
832 if (!descriptor_pool_add(descpool, u, NULL))
835 /* descriptor_pool_add accepts method descriptors, so we have to check */
836 /* against them here before the call of descriptor_to_basic_type below. */
837 if (u->text[0] == '(') {
838 exceptions_throw_classformaterror(c, "Method descriptor used for field");
842 #ifdef ENABLE_VERIFIER
845 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
846 exceptions_throw_classformaterror(c,
847 "Illegal Field name \"%s\"",
852 /* check flag consistency */
853 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
855 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
856 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
857 exceptions_throw_classformaterror(c,
858 "Illegal field modifiers: 0x%X",
863 if (c->flags & ACC_INTERFACE) {
864 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
865 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
866 f->flags & ACC_TRANSIENT) {
867 exceptions_throw_classformaterror(c,
868 "Illegal field modifiers: 0x%X",
874 #endif /* ENABLE_VERIFIER */
876 f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
877 f->offset = 0; /* offset from start of object */
882 case TYPE_INT: f->value.i = 0; break;
883 case TYPE_FLOAT: f->value.f = 0.0; break;
884 case TYPE_DOUBLE: f->value.d = 0.0; break;
885 case TYPE_ADDRESS: f->value.a = NULL; break;
888 f->value.l = 0; break;
890 f->value.l.low = 0; f->value.l.high = 0; break;
894 /* read attributes */
895 if (!suck_check_classbuffer_size(cb, 2))
898 attrnum = suck_u2(cb);
899 for (i = 0; i < attrnum; i++) {
900 if (!suck_check_classbuffer_size(cb, 2))
903 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
906 if (u == utf_ConstantValue) {
907 if (!suck_check_classbuffer_size(cb, 4 + 2))
910 /* check attribute length */
911 if (suck_u4(cb) != 2) {
912 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
916 /* constant value attribute */
917 if (pindex != field_load_NOVALUE) {
918 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
922 /* index of value in constantpool */
923 pindex = suck_u2(cb);
925 /* initialize field with value from constantpool */
928 constant_integer *ci;
930 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
933 f->value.i = ci->value;
940 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
943 f->value.l = cl->value;
950 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
953 f->value.f = cf->value;
960 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
963 f->value.d = cd->value;
968 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
971 /* create javastring from compressed utf8-string */
972 f->value.a = literalstring_new(u);
976 log_text("Invalid Constant - Type");
980 /* unknown attribute */
981 if (!skipattributebody(cb))
986 /* everything was ok */
992 /* load_method *****************************************************************
994 Loads a method from the class file and fills an existing
995 'methodinfo' structure. For native methods, the function pointer
996 field is set to the real function pointer, for JavaVM methods a
997 pointer to the compiler is used preliminarily.
999 *******************************************************************************/
1001 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1012 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1013 initObjectLock(&m->header);
1016 #if defined(ENABLE_STATISTICS)
1018 count_all_methods++;
1021 m->thrownexceptionscount = 0;
1022 m->linenumbercount = 0;
1026 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1029 m->flags = suck_u2(cb);
1031 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1036 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1040 m->parseddesc = NULL;
1042 if (!descriptor_pool_add(descpool, u, &argcount))
1045 #ifdef ENABLE_VERIFIER
1047 if (!is_valid_name_utf(m->name)) {
1048 exceptions_throw_classformaterror(c, "Method with invalid name");
1052 if (m->name->text[0] == '<' &&
1053 m->name != utf_init && m->name != utf_clinit) {
1054 exceptions_throw_classformaterror(c, "Method with invalid special name");
1058 #endif /* ENABLE_VERIFIER */
1060 if (!(m->flags & ACC_STATIC))
1061 argcount++; /* count the 'this' argument */
1063 #ifdef ENABLE_VERIFIER
1065 if (argcount > 255) {
1066 exceptions_throw_classformaterror(c, "Too many arguments in signature");
1070 /* check flag consistency */
1071 if (m->name != utf_clinit) {
1072 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1074 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1075 exceptions_throw_classformaterror(c,
1076 "Illegal method modifiers: 0x%X",
1081 if (m->flags & ACC_ABSTRACT) {
1082 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1083 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1084 exceptions_throw_classformaterror(c,
1085 "Illegal method modifiers: 0x%X",
1091 if (c->flags & ACC_INTERFACE) {
1092 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1093 exceptions_throw_classformaterror(c,
1094 "Illegal method modifiers: 0x%X",
1100 if (m->name == utf_init) {
1101 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1102 ACC_NATIVE | ACC_ABSTRACT)) {
1103 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1109 #endif /* ENABLE_VERIFIER */
1112 m->basicblockcount = 0;
1113 m->basicblocks = NULL;
1114 m->basicblockindex = NULL;
1115 m->instructioncount = 0;
1116 m->instructions = NULL;
1119 m->exceptiontable = NULL;
1120 m->stubroutine = NULL;
1122 m->entrypoint = NULL;
1124 if (!suck_check_classbuffer_size(cb, 2))
1127 attrnum = suck_u2(cb);
1128 for (i = 0; i < attrnum; i++) {
1131 if (!suck_check_classbuffer_size(cb, 2))
1134 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1137 if (aname == utf_Code) {
1138 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1139 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1144 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1148 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1152 m->maxstack = suck_u2(cb);
1153 m->maxlocals = suck_u2(cb);
1155 if (m->maxlocals < argcount) {
1156 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1160 if (!suck_check_classbuffer_size(cb, 4))
1163 m->jcodelength = suck_u4(cb);
1165 if (m->jcodelength == 0) {
1166 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1170 if (m->jcodelength > 65535) {
1171 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1175 if (!suck_check_classbuffer_size(cb, m->jcodelength))
1178 m->jcode = MNEW(u1, m->jcodelength);
1179 suck_nbytes(m->jcode, cb, m->jcodelength);
1181 if (!suck_check_classbuffer_size(cb, 2))
1184 m->exceptiontablelength = suck_u2(cb);
1185 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1188 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1190 #if defined(ENABLE_STATISTICS)
1192 count_vmcode_len += m->jcodelength + 18;
1193 count_extable_len +=
1194 m->exceptiontablelength * sizeof(exceptiontable);
1198 for (j = 0; j < m->exceptiontablelength; j++) {
1200 m->exceptiontable[j].startpc = suck_u2(cb);
1201 m->exceptiontable[j].endpc = suck_u2(cb);
1202 m->exceptiontable[j].handlerpc = suck_u2(cb);
1206 m->exceptiontable[j].catchtype.any = NULL;
1209 /* the classref is created later */
1210 if (!(m->exceptiontable[j].catchtype.any =
1211 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1216 if (!suck_check_classbuffer_size(cb, 2))
1219 codeattrnum = suck_u2(cb);
1221 for (; codeattrnum > 0; codeattrnum--) {
1224 if (!suck_check_classbuffer_size(cb, 2))
1227 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1230 if (caname == utf_LineNumberTable) {
1233 if (!suck_check_classbuffer_size(cb, 4 + 2))
1237 m->linenumbercount = suck_u2(cb);
1239 if (!suck_check_classbuffer_size(cb,
1240 (2 + 2) * m->linenumbercount))
1243 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1245 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1246 m->linenumbers[lncid].start_pc = suck_u2(cb);
1247 m->linenumbers[lncid].line_number = suck_u2(cb);
1251 if (!skipattributes(cb, codeattrnum))
1257 if (!skipattributebody(cb))
1262 } else if (aname == utf_Exceptions) {
1265 if (m->thrownexceptions) {
1266 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1270 if (!suck_check_classbuffer_size(cb, 4 + 2))
1273 suck_u4(cb); /* length */
1274 m->thrownexceptionscount = suck_u2(cb);
1276 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1279 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1281 for (j = 0; j < m->thrownexceptionscount; j++) {
1282 /* the classref is created later */
1283 if (!((m->thrownexceptions)[j].any =
1284 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1289 if (!skipattributebody(cb))
1294 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1295 exceptions_throw_classformaterror(c, "Missing Code attribute");
1299 /* everything was ok */
1305 /* load_attribute **************************************************************
1307 Read attributes from classfile.
1309 *******************************************************************************/
1311 static bool load_attributes(classbuffer *cb, u4 num)
1319 for (i = 0; i < num; i++) {
1320 /* retrieve attribute name */
1321 if (!suck_check_classbuffer_size(cb, 2))
1324 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1327 if (aname == utf_InnerClasses) {
1328 /* innerclasses attribute */
1329 if (c->innerclass) {
1330 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1334 if (!suck_check_classbuffer_size(cb, 4 + 2))
1337 /* skip attribute length */
1340 /* number of records */
1341 c->innerclasscount = suck_u2(cb);
1343 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1346 /* allocate memory for innerclass structure */
1347 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1349 for (j = 0; j < c->innerclasscount; j++) {
1350 /* The innerclass structure contains a class with an encoded
1351 name, its defining scope, its simple name and a bitmask of
1352 the access flags. If an inner class is not a member, its
1353 outer_class is NULL, if a class is anonymous, its name is
1356 innerclassinfo *info = c->innerclass + j;
1358 info->inner_class.ref =
1359 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1360 info->outer_class.ref =
1361 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1363 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1364 info->flags = suck_u2(cb);
1367 } else if (aname == utf_SourceFile) {
1368 if (!suck_check_classbuffer_size(cb, 4 + 2))
1371 if (suck_u4(cb) != 2) {
1372 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1376 if (c->sourcefile) {
1377 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1381 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1385 /* unknown attribute */
1386 if (!skipattributebody(cb))
1395 /* load_class_from_sysloader ***************************************************
1397 Load the class with the given name using the system class loader
1400 name.............the classname
1403 the loaded class, or
1404 NULL if an exception has been thrown
1406 *******************************************************************************/
1408 classinfo *load_class_from_sysloader(utf *name)
1411 java_objectheader *cl;
1414 LOADER_ASSERT(class_java_lang_Object);
1415 LOADER_ASSERT(class_java_lang_ClassLoader);
1416 LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1418 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1419 utf_getSystemClassLoader,
1420 utf_void__java_lang_ClassLoader,
1421 class_java_lang_Object,
1427 ASM_CALLJAVAFUNCTION_ADR(cl, m, NULL, NULL, NULL, NULL);
1432 c = load_class_from_classloader(name, cl);
1438 /* load_class_from_classloader *************************************************
1440 Load the class with the given name using the given user-defined class loader.
1443 name.............the classname
1444 cl...............user-defined class loader
1447 the loaded class, or
1448 NULL if an exception has been thrown
1450 *******************************************************************************/
1452 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1454 java_objectheader *o;
1458 LOADER_ASSERT(name);
1460 /* lookup if this class has already been loaded */
1462 c = classcache_lookup(cl, name);
1467 /* if other class loader than bootstrap, call it */
1475 namelen = name->blength;
1477 /* handle array classes */
1478 if (text[0] == '[') {
1484 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1485 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1486 *exceptionptr = new_noclassdeffounderror(name);
1490 u = utf_new(text + 2, namelen - 3);
1492 if (!(comp = load_class_from_classloader(u, cl)))
1495 /* create the array class */
1497 c = class_array_of(comp, false);
1499 tmpc = classcache_store(cl, c, true);
1502 /* exception, free the loaded class */
1503 c->state &= ~CLASS_LOADING;
1510 /* load the component class */
1512 u = utf_new(text + 1, namelen - 1);
1514 if (!(comp = load_class_from_classloader(u, cl)))
1517 /* create the array class */
1519 c = class_array_of(comp, false);
1521 tmpc = classcache_store(cl, c, true);
1524 /* exception, free the loaded class */
1525 c->state &= ~CLASS_LOADING;
1532 /* primitive array classes are loaded by the bootstrap loader */
1534 c = load_class_bootstrap(name);
1540 LOADER_ASSERT(class_java_lang_Object);
1542 lc = class_resolveclassmethod(cl->vftbl->class,
1544 utf_java_lang_String__java_lang_Class,
1545 class_java_lang_Object,
1549 return false; /* exception */
1551 /* move return value into `o' and cast it afterwards to a classinfo* */
1553 ASM_CALLJAVAFUNCTION_ADR(o, lc, cl,
1554 javastring_new_slash_to_dot(name),
1557 c = (classinfo *) o;
1560 /* Store this class in the loaded class cache. If another
1561 class with the same (initloader,name) pair has been
1562 stored earlier it will be returned by classcache_store
1563 In this case classcache_store may not free the class
1564 because it has already been exposed to Java code which
1565 may have kept references to that class. */
1567 tmpc = classcache_store(cl, c, false);
1570 /* exception, free the loaded class */
1571 c->state &= ~CLASS_LOADING;
1578 /* loadClass has thrown an exception */
1579 /* we must convert ClassNotFoundException into NoClassDefFoundException */
1580 /* XXX maybe we should have a flag that avoids this conversion */
1581 /* for calling load_class_from_classloader from Class.forName */
1582 /* Currently we do a double conversion in these cases */
1583 classnotfoundexception_to_noclassdeffounderror();
1586 /* SUN compatible -verbose:class output */
1588 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1590 utf_display_classname(name);
1597 c = load_class_bootstrap(name);
1603 /* load_class_bootstrap ********************************************************
1605 Load the class with the given name using the bootstrap class loader.
1608 name.............the classname
1611 loaded classinfo, or
1612 NULL if an exception has been thrown
1615 load_class_bootstrap is synchronized. It can be treated as an
1618 *******************************************************************************/
1620 classinfo *load_class_bootstrap(utf *name)
1628 LOADER_ASSERT(name);
1630 /* lookup if this class has already been loaded */
1632 if ((r = classcache_lookup(NULL, name)))
1635 /* create the classinfo */
1637 c = class_create_classinfo(name);
1639 /* handle array classes */
1641 if (name->text[0] == '[') {
1642 c = load_newly_created_array(c, NULL);
1645 LOADER_ASSERT(c->state & CLASS_LOADED);
1649 #if defined(ENABLE_STATISTICS)
1652 if (getcompilingtime)
1653 compilingtime_stop();
1656 loadingtime_start();
1659 /* load classdata, throw exception on error */
1661 if ((cb = suck_start(c)) == NULL) {
1662 /* this normally means, the classpath was not set properly */
1664 if (name == utf_java_lang_Object)
1665 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1666 "java/lang/Object");
1668 *exceptionptr = new_noclassdeffounderror(name);
1673 /* load the class from the buffer */
1675 r = load_class_from_classbuffer(cb);
1678 /* the class could not be loaded, free the classinfo struct */
1683 /* Store this class in the loaded class cache this step also
1684 checks the loading constraints. If the class has been loaded
1685 before, the earlier loaded class is returned. */
1687 classinfo *res = classcache_store(NULL, c, true);
1697 /* SUN compatible -verbose:class output */
1699 if (opt_verboseclass && r) {
1701 utf_display_classname(name);
1702 printf(" from %s]\n", cb->path);
1709 #if defined(ENABLE_STATISTICS)
1715 if (getcompilingtime)
1716 compilingtime_start();
1723 /* load_class_from_classbuffer *************************************************
1725 Loads everything interesting about a class from the class file. The
1726 'classinfo' structure must have been allocated previously.
1728 The super class and the interfaces implemented by this class need
1729 not be loaded. The link is set later by the function 'class_link'.
1731 The loaded class is removed from the list 'unloadedclasses' and
1732 added to the list 'unlinkedclasses'.
1735 This function is NOT synchronized!
1737 *******************************************************************************/
1739 classinfo *load_class_from_classbuffer(classbuffer *cb)
1747 descriptor_pool *descpool;
1748 #if defined(ENABLE_STATISTICS)
1753 /* get the classbuffer's class */
1757 /* the class is already loaded */
1759 if (c->state & CLASS_LOADED)
1762 #if defined(ENABLE_STATISTICS)
1764 count_class_loads++;
1767 #if !defined(NDEBUG)
1768 /* output for debugging purposes */
1771 log_message_class("Loading class: ", c);
1774 /* mark start of dump memory area */
1776 dumpsize = dump_size();
1778 /* class is currently loading */
1780 c->state |= CLASS_LOADING;
1782 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1783 goto return_exception;
1785 /* check signature */
1787 if (suck_u4(cb) != MAGIC) {
1788 exceptions_throw_classformaterror(c, "Bad magic number");
1790 goto return_exception;
1798 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1800 new_unsupportedclassversionerror(c,
1801 "Unsupported major.minor version %d.%d",
1804 goto return_exception;
1807 /* create a new descriptor pool */
1809 descpool = descriptor_pool_new(c);
1811 /* load the constant pool */
1813 if (!load_constantpool(cb, descpool))
1814 goto return_exception;
1818 if (!suck_check_classbuffer_size(cb, 2))
1819 goto return_exception;
1821 c->flags = suck_u2(cb);
1823 /* check ACC flags consistency */
1825 if (c->flags & ACC_INTERFACE) {
1826 if (!(c->flags & ACC_ABSTRACT)) {
1827 /* We work around this because interfaces in JDK 1.1 are
1828 * not declared abstract. */
1830 c->flags |= ACC_ABSTRACT;
1833 if (c->flags & ACC_FINAL) {
1834 exceptions_throw_classformaterror(c,
1835 "Illegal class modifiers: 0x%X",
1837 goto return_exception;
1840 if (c->flags & ACC_SUPER) {
1841 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1845 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1846 exceptions_throw_classformaterror(c,
1847 "Illegal class modifiers: 0x%X",
1849 goto return_exception;
1852 if (!suck_check_classbuffer_size(cb, 2 + 2))
1853 goto return_exception;
1858 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1859 goto return_exception;
1861 if (c->name == utf_not_named_yet) {
1862 /* we finally have a name for this class */
1864 class_set_packagename(c);
1866 } else if (name != c->name) {
1870 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1871 utf_strlen(name) + strlen(")") + strlen("0");
1873 msg = MNEW(char, msglen);
1875 utf_sprint(msg, c->name);
1876 strcat(msg, " (wrong name: ");
1877 utf_strcat(msg, name);
1881 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1883 MFREE(msg, char, msglen);
1885 goto return_exception;
1888 /* retrieve superclass */
1890 c->super.any = NULL;
1891 if ((i = suck_u2(cb))) {
1892 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1893 goto return_exception;
1895 /* java.lang.Object may not have a super class. */
1897 if (c->name == utf_java_lang_Object) {
1899 new_exception_message(string_java_lang_ClassFormatError,
1900 "java.lang.Object with superclass");
1902 goto return_exception;
1905 /* Interfaces must have java.lang.Object as super class. */
1907 if ((c->flags & ACC_INTERFACE) &&
1908 supername != utf_java_lang_Object) {
1910 new_exception_message(string_java_lang_ClassFormatError,
1911 "Interfaces must have java.lang.Object as superclass");
1913 goto return_exception;
1919 /* This is only allowed for java.lang.Object. */
1921 if (c->name != utf_java_lang_Object) {
1922 exceptions_throw_classformaterror(c, "Bad superclass index");
1923 goto return_exception;
1927 /* retrieve interfaces */
1929 if (!suck_check_classbuffer_size(cb, 2))
1930 goto return_exception;
1932 c->interfacescount = suck_u2(cb);
1934 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1935 goto return_exception;
1937 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1938 for (i = 0; i < c->interfacescount; i++) {
1939 /* the classrefs are created later */
1940 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1941 goto return_exception;
1945 if (!suck_check_classbuffer_size(cb, 2))
1946 goto return_exception;
1948 c->fieldscount = suck_u2(cb);
1949 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
1950 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
1951 for (i = 0; i < c->fieldscount; i++) {
1952 if (!load_field(cb, &(c->fields[i]),descpool))
1953 goto return_exception;
1957 if (!suck_check_classbuffer_size(cb, 2))
1958 goto return_exception;
1960 c->methodscount = suck_u2(cb);
1961 /* c->methods = GCNEW(methodinfo, c->methodscount); */
1962 c->methods = MNEW(methodinfo, c->methodscount);
1963 for (i = 0; i < c->methodscount; i++) {
1964 if (!load_method(cb, &(c->methods[i]),descpool))
1965 goto return_exception;
1968 /* create the class reference table */
1971 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
1973 /* allocate space for the parsed descriptors */
1975 descriptor_pool_alloc_parsed_descriptors(descpool);
1977 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
1979 #if defined(ENABLE_STATISTICS)
1981 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
1982 count_classref_len += classrefsize;
1983 count_parsed_desc_len += descsize;
1987 /* put the classrefs in the constant pool */
1988 for (i = 0; i < c->cpcount; i++) {
1989 if (c->cptags[i] == CONSTANT_Class) {
1990 utf *name = (utf *) c->cpinfos[i];
1991 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
1995 /* set the super class reference */
1998 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2000 goto return_exception;
2003 /* set the super interfaces references */
2005 for (i = 0; i < c->interfacescount; i++) {
2006 c->interfaces[i].ref =
2007 descriptor_pool_lookup_classref(descpool,
2008 (utf *) c->interfaces[i].any);
2009 if (!c->interfaces[i].ref)
2010 goto return_exception;
2013 /* parse field descriptors */
2015 for (i = 0; i < c->fieldscount; i++) {
2016 c->fields[i].parseddesc =
2017 descriptor_pool_parse_field_descriptor(descpool,
2018 c->fields[i].descriptor);
2019 if (!c->fields[i].parseddesc)
2020 goto return_exception;
2023 /* parse method descriptors */
2025 for (i = 0; i < c->methodscount; i++) {
2026 methodinfo *m = &c->methods[i];
2028 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2029 m->flags, class_get_self_classref(m->class));
2031 goto return_exception;
2033 for (j = 0; j < m->exceptiontablelength; j++) {
2034 if (!m->exceptiontable[j].catchtype.any)
2036 if ((m->exceptiontable[j].catchtype.ref =
2037 descriptor_pool_lookup_classref(descpool,
2038 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2039 goto return_exception;
2042 for (j = 0; j < m->thrownexceptionscount; j++) {
2043 if (!m->thrownexceptions[j].any)
2045 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2046 (utf *) m->thrownexceptions[j].any)) == NULL)
2047 goto return_exception;
2051 /* parse the loaded descriptors */
2053 for (i = 0; i < c->cpcount; i++) {
2054 constant_FMIref *fmi;
2057 switch (c->cptags[i]) {
2058 case CONSTANT_Fieldref:
2059 fmi = (constant_FMIref *) c->cpinfos[i];
2060 fmi->parseddesc.fd =
2061 descriptor_pool_parse_field_descriptor(descpool,
2063 if (!fmi->parseddesc.fd)
2064 goto return_exception;
2065 index = (int) (size_t) fmi->classref;
2067 (constant_classref *) class_getconstant(c, index,
2070 goto return_exception;
2072 case CONSTANT_Methodref:
2073 case CONSTANT_InterfaceMethodref:
2074 fmi = (constant_FMIref *) c->cpinfos[i];
2075 index = (int) (size_t) fmi->classref;
2077 (constant_classref *) class_getconstant(c, index,
2080 goto return_exception;
2081 fmi->parseddesc.md =
2082 descriptor_pool_parse_method_descriptor(descpool,
2086 if (!fmi->parseddesc.md)
2087 goto return_exception;
2092 #ifdef ENABLE_VERIFIER
2093 /* Check if all fields and methods can be uniquely
2094 * identified by (name,descriptor). */
2097 /* We use a hash table here to avoid making the
2098 * average case quadratic in # of methods, fields.
2100 static int shift = 0;
2102 u2 *next; /* for chaining colliding hash entries */
2108 /* Allocate hashtable */
2109 len = c->methodscount;
2110 if (len < c->fieldscount) len = c->fieldscount;
2112 hashtab = MNEW(u2,(hashlen + len));
2113 next = hashtab + hashlen;
2115 /* Determine bitshift (to get good hash values) */
2125 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2127 for (i = 0; i < c->fieldscount; ++i) {
2128 fieldinfo *fi = c->fields + i;
2130 /* It's ok if we lose bits here */
2131 index = ((((size_t) fi->name) +
2132 ((size_t) fi->descriptor)) >> shift) % hashlen;
2134 if ((old = hashtab[index])) {
2138 if (c->fields[old].name == fi->name &&
2139 c->fields[old].descriptor == fi->descriptor) {
2140 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2141 goto return_exception;
2143 } while ((old = next[old]));
2145 hashtab[index] = i + 1;
2149 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2151 for (i = 0; i < c->methodscount; ++i) {
2152 methodinfo *mi = c->methods + i;
2154 /* It's ok if we lose bits here */
2155 index = ((((size_t) mi->name) +
2156 ((size_t) mi->descriptor)) >> shift) % hashlen;
2160 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2161 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2165 if ((old = hashtab[index])) {
2169 if (c->methods[old].name == mi->name &&
2170 c->methods[old].descriptor == mi->descriptor) {
2171 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2172 goto return_exception;
2174 } while ((old = next[old]));
2176 hashtab[index] = i + 1;
2179 MFREE(hashtab, u2, (hashlen + len));
2181 #endif /* ENABLE_VERIFIER */
2183 #if defined(ENABLE_STATISTICS)
2185 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2186 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2187 count_class_infos += sizeof(methodinfo) * c->methodscount;
2191 /* load attribute structures */
2193 if (!suck_check_classbuffer_size(cb, 2))
2194 goto return_exception;
2196 if (!load_attributes(cb, suck_u2(cb)))
2197 goto return_exception;
2200 /* Pre java 1.5 version don't check this. This implementation is like
2201 java 1.5 do it: for class file version 45.3 we don't check it, older
2202 versions are checked.
2204 if ((ma == 45 && mi > 3) || ma > 45) {
2205 /* check if all data has been read */
2206 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2208 if (classdata_left > 0) {
2209 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2210 goto return_exception;
2215 /* release dump area */
2217 dump_release(dumpsize);
2219 /* revert loading state and class is loaded */
2221 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2223 #if !defined(NDEBUG)
2225 log_message_class("Loading done class: ", c);
2231 /* release dump area */
2233 dump_release(dumpsize);
2235 /* an exception has been thrown */
2241 /* load_newly_created_array ****************************************************
2243 Load a newly created array class.
2246 c....................the array class C has been loaded
2247 other classinfo......the array class was found in the class cache,
2249 NULL.................an exception has been thrown
2252 This is an internal function. Do not use it unless you know exactly
2255 Use one of the load_class_... functions for general array class loading.
2257 *******************************************************************************/
2259 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2261 classinfo *comp = NULL;
2263 methoddesc *clonedesc;
2264 constant_classref *classrefs;
2269 text = c->name->text;
2270 namelen = c->name->blength;
2272 /* Check array class name */
2274 if (namelen < 2 || text[0] != '[') {
2275 *exceptionptr = new_noclassdeffounderror(c->name);
2279 /* Check the element type */
2283 /* c is an array of arrays. We have to create the component class. */
2285 u = utf_new(text + 1, namelen - 1);
2286 if (!(comp = load_class_from_classloader(u, loader)))
2289 LOADER_ASSERT(comp->state & CLASS_LOADED);
2295 /* the array's flags are that of the component class */
2296 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2297 c->classloader = comp->classloader;
2301 /* c is an array of objects. */
2303 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2304 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2305 *exceptionptr = new_noclassdeffounderror(c->name);
2309 u = utf_new(text + 2, namelen - 3);
2311 if (!(comp = load_class_from_classloader(u, loader)))
2314 LOADER_ASSERT(comp->state & CLASS_LOADED);
2320 /* the array's flags are that of the component class */
2321 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2322 c->classloader = comp->classloader;
2326 /* c is an array of a primitive type */
2328 /* check for cases like `[II' */
2330 *exceptionptr = new_noclassdeffounderror(c->name);
2334 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2335 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2336 c->classloader = NULL;
2339 LOADER_ASSERT(class_java_lang_Object);
2340 LOADER_ASSERT(class_java_lang_Cloneable);
2341 LOADER_ASSERT(class_java_io_Serializable);
2343 /* setup the array class */
2345 c->super.cls = class_java_lang_Object;
2347 c->interfacescount = 2;
2348 c->interfaces = MNEW(classref_or_classinfo, 2);
2353 tc = class_java_lang_Cloneable;
2354 LOADER_ASSERT(tc->state & CLASS_LOADED);
2355 list_addfirst(&unlinkedclasses, tc);
2356 c->interfaces[0].cls = tc;
2358 tc = class_java_io_Serializable;
2359 LOADER_ASSERT(tc->state & CLASS_LOADED);
2360 list_addfirst(&unlinkedclasses, tc);
2361 c->interfaces[1].cls = tc;
2364 c->interfaces[0].cls = class_java_lang_Cloneable;
2365 c->interfaces[1].cls = class_java_io_Serializable;
2368 c->methodscount = 1;
2369 c->methods = MNEW(methodinfo, c->methodscount);
2371 classrefs = MNEW(constant_classref, 2);
2372 CLASSREF_INIT(classrefs[0], c, c->name);
2373 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2375 /* create descriptor for clone method */
2376 /* we need one paramslot which is reserved for the 'this' parameter */
2377 clonedesc = NEW(methoddesc);
2378 clonedesc->returntype.type = TYPE_ADDRESS;
2379 clonedesc->returntype.classref = classrefs + 1;
2380 clonedesc->returntype.arraydim = 0;
2381 /* initialize params to "empty", add real params below in
2382 descriptor_params_from_paramtypes */
2383 clonedesc->paramcount = 0;
2384 clonedesc->paramslots = 0;
2385 clonedesc->paramtypes[0].classref = classrefs + 0;
2387 /* create methodinfo */
2390 MSET(clone, 0, methodinfo, 1);
2392 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2393 initObjectLock(&clone->header);
2396 /* ATTENTION: if you delete the ACC_NATIVE below, set
2397 clone->maxlocals=1 (interpreter related) */
2399 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2400 clone->name = utf_clone;
2401 clone->descriptor = utf_void__java_lang_Object;
2402 clone->parseddesc = clonedesc;
2405 /* parse the descriptor to get the register allocation */
2407 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2411 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2413 /* XXX: field: length? */
2415 /* array classes are not loaded from class files */
2417 c->state |= CLASS_LOADED;
2418 c->parseddescs = (u1 *) clonedesc;
2419 c->parseddescsize = sizeof(methodinfo);
2420 c->classrefs = classrefs;
2421 c->classrefcount = 1;
2423 /* insert class into the loaded class cache */
2424 /* XXX free classinfo if NULL returned? */
2426 return classcache_store(loader, c, true);
2430 /* loader_close ****************************************************************
2432 Frees all resources.
2434 *******************************************************************************/
2436 void loader_close(void)
2443 * These are local overrides for various environment variables in Emacs.
2444 * Please do not remove this and leave it at the end of the file, where
2445 * Emacs will automagically detect them.
2446 * ---------------------------------------------------------------------
2449 * indent-tabs-mode: t