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 4559 2006-03-05 23:24:50Z 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"
74 #if defined(ENABLE_ZLIB)
78 #include "vm/jit/asmpart.h"
79 #include "vm/jit/codegen-common.h"
82 /******************************************************************************/
84 /******************************************************************************/
91 #define LOADER_ASSERT(cond) assert(cond)
93 #define LOADER_ASSERT(cond)
97 /* loader_init *****************************************************************
99 Initializes all lists and loads all classes required for the system
102 *******************************************************************************/
104 bool loader_init(u1 *stackbottom)
106 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
107 list_classpath_entry *lce;
109 /* Initialize the monitor pointer for zip/jar file locking. */
111 for (lce = list_first(list_classpath_entries); lce != NULL;
112 lce = list_next(list_classpath_entries, lce))
113 if (lce->type == CLASSPATH_ARCHIVE)
114 initObjectLock((java_objectheader *) lce);
117 /* load some important classes */
119 if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
122 if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
125 if (!(class_java_lang_Cloneable =
126 load_class_bootstrap(utf_java_lang_Cloneable)))
129 if (!(class_java_io_Serializable =
130 load_class_bootstrap(utf_java_io_Serializable)))
134 /* load classes for wrapping primitive types */
136 if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
139 if (!(class_java_lang_Boolean =
140 load_class_bootstrap(utf_java_lang_Boolean)))
143 if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
146 if (!(class_java_lang_Character =
147 load_class_bootstrap(utf_java_lang_Character)))
150 if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
153 if (!(class_java_lang_Integer =
154 load_class_bootstrap(utf_java_lang_Integer)))
157 if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
160 if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
163 if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
167 /* load some other important classes */
169 if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
172 if (!(class_java_lang_ClassLoader =
173 load_class_bootstrap(utf_java_lang_ClassLoader)))
176 if (!(class_java_lang_SecurityManager =
177 load_class_bootstrap(utf_java_lang_SecurityManager)))
180 if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
183 if (!(class_java_lang_Thread =
184 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
187 if (!(class_java_lang_ThreadGroup =
188 load_class_bootstrap(utf_java_lang_ThreadGroup)))
191 if (!(class_java_lang_VMThread =
192 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
196 /* some classes which may be used more often */
198 if (!(class_java_lang_StackTraceElement =
199 load_class_bootstrap(utf_java_lang_StackTraceElement)))
202 if (!(class_java_lang_reflect_Constructor =
203 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
206 if (!(class_java_lang_reflect_Field =
207 load_class_bootstrap(utf_java_lang_reflect_Field)))
210 if (!(class_java_lang_reflect_Method =
211 load_class_bootstrap(utf_java_lang_reflect_Method)))
214 if (!(class_java_security_PrivilegedAction =
215 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
218 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
221 if (!(arrayclass_java_lang_Object =
222 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
225 #if defined(USE_THREADS)
226 if (stackbottom != 0)
234 /* loader_load_all_classes *****************************************************
236 Loads all classes specified in the BOOTCLASSPATH.
238 *******************************************************************************/
240 void loader_load_all_classes(void)
242 list_classpath_entry *lce;
243 #if defined(ENABLE_ZLIB)
246 hashtable_zipfile_entry *htzfe;
250 for (lce = list_first(list_classpath_entries); lce != NULL;
251 lce = list_next(list_classpath_entries, lce)) {
252 #if defined(ENABLE_ZLIB)
253 if (lce->type == CLASSPATH_ARCHIVE) {
254 /* get the classes hashtable */
258 for (slot = 0; slot < ht->size; slot++) {
259 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
261 for (; htzfe; htzfe = htzfe->hashlink) {
264 /* skip all entries in META-INF and .properties,
267 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
268 strstr(u->text, ".properties") ||
269 strstr(u->text, ".png"))
272 /* load class from bootstrap classloader */
274 if (!load_class_bootstrap(u)) {
275 fprintf(stderr, "Error loading: ");
276 utf_fprint_classname(stderr, u);
277 fprintf(stderr, "\n");
279 /* print out exception and cause */
281 exceptions_print_exception(*exceptionptr);
288 #if defined(ENABLE_ZLIB)
295 /* skipattributebody ***********************************************************
297 Skips an attribute after the 16 bit reference to attribute_name has
300 *******************************************************************************/
302 static bool skipattributebody(classbuffer *cb)
306 if (!suck_check_classbuffer_size(cb, 4))
311 if (!suck_check_classbuffer_size(cb, len))
314 suck_skip_nbytes(cb, len);
320 /************************* Function: skipattributes ****************************
322 skips num attribute structures
324 *******************************************************************************/
326 static bool skipattributes(classbuffer *cb, u4 num)
331 for (i = 0; i < num; i++) {
332 if (!suck_check_classbuffer_size(cb, 2 + 4))
338 if (!suck_check_classbuffer_size(cb, len))
341 suck_skip_nbytes(cb, len);
348 /* load_constantpool ***********************************************************
350 Loads the constantpool of a class, the entries are transformed into
351 a simpler format by resolving references (a detailed overview of
352 the compact structures can be found in global.h).
354 *******************************************************************************/
356 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
359 /* The following structures are used to save information which cannot be
360 processed during the first pass. After the complete constantpool has
361 been traversed the references can be resolved.
362 (only in specific order) */
364 /* CONSTANT_Class entries */
365 typedef struct forward_class {
366 struct forward_class *next;
371 /* CONSTANT_String */
372 typedef struct forward_string {
373 struct forward_string *next;
378 /* CONSTANT_NameAndType */
379 typedef struct forward_nameandtype {
380 struct forward_nameandtype *next;
384 } forward_nameandtype;
386 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
387 typedef struct forward_fieldmethint {
388 struct forward_fieldmethint *next;
392 u2 nameandtype_index;
393 } forward_fieldmethint;
399 forward_class *forward_classes = NULL;
400 forward_string *forward_strings = NULL;
401 forward_nameandtype *forward_nameandtypes = NULL;
402 forward_fieldmethint *forward_fieldmethints = NULL;
406 forward_nameandtype *nfn;
407 forward_fieldmethint *nff;
415 /* number of entries in the constant_pool table plus one */
416 if (!suck_check_classbuffer_size(cb, 2))
419 cpcount = c->cpcount = suck_u2(cb);
421 /* allocate memory */
422 cptags = c->cptags = MNEW(u1, cpcount);
423 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
426 exceptions_throw_classformaterror(c, "Illegal constant pool size");
430 #if defined(ENABLE_STATISTICS)
432 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
435 /* initialize constantpool */
436 for (idx = 0; idx < cpcount; idx++) {
437 cptags[idx] = CONSTANT_UNUSED;
442 /******* first pass *******/
443 /* entries which cannot be resolved now are written into
444 temporary structures and traversed again later */
447 while (idx < cpcount) {
450 /* get constant type */
451 if (!suck_check_classbuffer_size(cb, 1))
458 nfc = DNEW(forward_class);
460 nfc->next = forward_classes;
461 forward_classes = nfc;
463 nfc->thisindex = idx;
464 /* reference to CONSTANT_NameAndType */
465 if (!suck_check_classbuffer_size(cb, 2))
468 nfc->name_index = suck_u2(cb);
473 case CONSTANT_String:
474 nfs = DNEW(forward_string);
476 nfs->next = forward_strings;
477 forward_strings = nfs;
479 nfs->thisindex = idx;
481 /* reference to CONSTANT_Utf8_info with string characters */
482 if (!suck_check_classbuffer_size(cb, 2))
485 nfs->string_index = suck_u2(cb);
490 case CONSTANT_NameAndType:
491 nfn = DNEW(forward_nameandtype);
493 nfn->next = forward_nameandtypes;
494 forward_nameandtypes = nfn;
496 nfn->thisindex = idx;
498 if (!suck_check_classbuffer_size(cb, 2 + 2))
501 /* reference to CONSTANT_Utf8_info containing simple name */
502 nfn->name_index = suck_u2(cb);
504 /* reference to CONSTANT_Utf8_info containing field or method
506 nfn->sig_index = suck_u2(cb);
511 case CONSTANT_Fieldref:
512 case CONSTANT_Methodref:
513 case CONSTANT_InterfaceMethodref:
514 nff = DNEW(forward_fieldmethint);
516 nff->next = forward_fieldmethints;
517 forward_fieldmethints = nff;
519 nff->thisindex = idx;
523 if (!suck_check_classbuffer_size(cb, 2 + 2))
526 /* class or interface type that contains the declaration of the
528 nff->class_index = suck_u2(cb);
530 /* name and descriptor of the field or method */
531 nff->nameandtype_index = suck_u2(cb);
536 case CONSTANT_Integer: {
537 constant_integer *ci = NEW(constant_integer);
539 #if defined(ENABLE_STATISTICS)
541 count_const_pool_len += sizeof(constant_integer);
544 if (!suck_check_classbuffer_size(cb, 4))
547 ci->value = suck_s4(cb);
548 cptags[idx] = CONSTANT_Integer;
555 case CONSTANT_Float: {
556 constant_float *cf = NEW(constant_float);
558 #if defined(ENABLE_STATISTICS)
560 count_const_pool_len += sizeof(constant_float);
563 if (!suck_check_classbuffer_size(cb, 4))
566 cf->value = suck_float(cb);
567 cptags[idx] = CONSTANT_Float;
574 case CONSTANT_Long: {
575 constant_long *cl = NEW(constant_long);
577 #if defined(ENABLE_STATISTICS)
579 count_const_pool_len += sizeof(constant_long);
582 if (!suck_check_classbuffer_size(cb, 8))
585 cl->value = suck_s8(cb);
586 cptags[idx] = CONSTANT_Long;
590 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
596 case CONSTANT_Double: {
597 constant_double *cd = NEW(constant_double);
599 #if defined(ENABLE_STATISTICS)
601 count_const_pool_len += sizeof(constant_double);
604 if (!suck_check_classbuffer_size(cb, 8))
607 cd->value = suck_double(cb);
608 cptags[idx] = CONSTANT_Double;
612 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
618 case CONSTANT_Utf8: {
621 /* number of bytes in the bytes array (not string-length) */
622 if (!suck_check_classbuffer_size(cb, 2))
625 length = suck_u2(cb);
626 cptags[idx] = CONSTANT_Utf8;
628 /* validate the string */
629 if (!suck_check_classbuffer_size(cb, length))
632 #ifdef ENABLE_VERIFIER
634 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
636 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
639 #endif /* ENABLE_VERIFIER */
640 /* insert utf-string into the utf-symboltable */
641 cpinfos[idx] = utf_new((char *) cb->pos, length);
643 /* skip bytes of the string (buffer size check above) */
644 suck_skip_nbytes(cb, length);
650 exceptions_throw_classformaterror(c, "Illegal constant pool type");
656 /* resolve entries in temporary structures */
658 while (forward_classes) {
660 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
664 #ifdef ENABLE_VERIFIER
665 if (opt_verify && !is_valid_name_utf(name)) {
666 exceptions_throw_classformaterror(c, "Class reference with invalid name");
669 #endif /* ENABLE_VERIFIER */
671 /* add all class references to the descriptor_pool */
673 if (!descriptor_pool_add_class(descpool, name))
676 cptags[forward_classes->thisindex] = CONSTANT_Class;
681 if (!(tc = load_class_bootstrap(name)))
684 /* link the class later, because we cannot link the class currently
686 list_addfirst(&unlinkedclasses, tc);
689 /* the classref is created later */
690 cpinfos[forward_classes->thisindex] = name;
692 nfc = forward_classes;
693 forward_classes = forward_classes->next;
696 while (forward_strings) {
698 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
702 /* resolve utf-string */
703 cptags[forward_strings->thisindex] = CONSTANT_String;
704 cpinfos[forward_strings->thisindex] = text;
706 nfs = forward_strings;
707 forward_strings = forward_strings->next;
710 while (forward_nameandtypes) {
711 constant_nameandtype *cn = NEW(constant_nameandtype);
713 #if defined(ENABLE_STATISTICS)
715 count_const_pool_len += sizeof(constant_nameandtype);
718 /* resolve simple name and descriptor */
719 cn->name = class_getconstant(c,
720 forward_nameandtypes->name_index,
725 cn->descriptor = class_getconstant(c,
726 forward_nameandtypes->sig_index,
731 #ifdef ENABLE_VERIFIER
734 if (!is_valid_name_utf(cn->name)) {
735 exceptions_throw_classformaterror(c,
736 "Illegal Field name \"%s\"",
742 /* disallow referencing <clinit> among others */
743 if (cn->name->text[0] == '<' && cn->name != utf_init) {
744 exceptions_throw_classformaterror(c, "Illegal reference to special method");
748 #endif /* ENABLE_VERIFIER */
750 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
751 cpinfos[forward_nameandtypes->thisindex] = cn;
753 nfn = forward_nameandtypes;
754 forward_nameandtypes = forward_nameandtypes->next;
757 while (forward_fieldmethints) {
758 constant_nameandtype *nat;
759 constant_FMIref *fmi = NEW(constant_FMIref);
761 #if defined(ENABLE_STATISTICS)
763 count_const_pool_len += sizeof(constant_FMIref);
765 /* resolve simple name and descriptor */
767 nat = class_getconstant(c,
768 forward_fieldmethints->nameandtype_index,
769 CONSTANT_NameAndType);
773 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
775 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
778 /* the classref is created later */
780 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
781 fmi->name = nat->name;
782 fmi->descriptor = nat->descriptor;
784 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
785 cpinfos[forward_fieldmethints->thisindex] = fmi;
787 nff = forward_fieldmethints;
788 forward_fieldmethints = forward_fieldmethints->next;
791 /* everything was ok */
797 /* load_field ******************************************************************
799 Load everything about a class field from the class file and fill a
800 'fieldinfo' structure. For static fields, space in the data segment
803 *******************************************************************************/
805 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
807 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
812 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
817 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
820 f->flags = suck_u2(cb);
822 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
827 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
831 f->parseddesc = NULL;
833 if (!descriptor_pool_add(descpool, u, NULL))
836 /* descriptor_pool_add accepts method descriptors, so we have to check */
837 /* against them here before the call of descriptor_to_basic_type below. */
838 if (u->text[0] == '(') {
839 exceptions_throw_classformaterror(c, "Method descriptor used for field");
843 #ifdef ENABLE_VERIFIER
846 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
847 exceptions_throw_classformaterror(c,
848 "Illegal Field name \"%s\"",
853 /* check flag consistency */
854 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
856 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
857 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
858 exceptions_throw_classformaterror(c,
859 "Illegal field modifiers: 0x%X",
864 if (c->flags & ACC_INTERFACE) {
865 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
866 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
867 f->flags & ACC_TRANSIENT) {
868 exceptions_throw_classformaterror(c,
869 "Illegal field modifiers: 0x%X",
875 #endif /* ENABLE_VERIFIER */
877 f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
878 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 cl = vm_call_method(m, 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;
1457 java_lang_String *s;
1459 LOADER_ASSERT(name);
1461 /* lookup if this class has already been loaded */
1463 c = classcache_lookup(cl, name);
1468 /* if other class loader than bootstrap, call it */
1476 namelen = name->blength;
1478 /* handle array classes */
1479 if (text[0] == '[') {
1485 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1486 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1487 *exceptionptr = new_noclassdeffounderror(name);
1491 u = utf_new(text + 2, namelen - 3);
1493 if (!(comp = load_class_from_classloader(u, cl)))
1496 /* create the array class */
1498 c = class_array_of(comp, false);
1500 tmpc = classcache_store(cl, c, true);
1503 /* exception, free the loaded class */
1504 c->state &= ~CLASS_LOADING;
1511 /* load the component class */
1513 u = utf_new(text + 1, namelen - 1);
1515 if (!(comp = load_class_from_classloader(u, cl)))
1518 /* create the array class */
1520 c = class_array_of(comp, false);
1522 tmpc = classcache_store(cl, c, true);
1525 /* exception, free the loaded class */
1526 c->state &= ~CLASS_LOADING;
1533 /* primitive array classes are loaded by the bootstrap loader */
1535 c = load_class_bootstrap(name);
1541 LOADER_ASSERT(class_java_lang_Object);
1543 lc = class_resolveclassmethod(cl->vftbl->class,
1545 utf_java_lang_String__java_lang_Class,
1546 class_java_lang_Object,
1550 return false; /* exception */
1552 /* move return value into `o' and cast it afterwards to a classinfo* */
1554 s = javastring_new_slash_to_dot(name);
1556 o = vm_call_method(lc, cl, s);
1558 c = (classinfo *) o;
1561 /* Store this class in the loaded class cache. If another
1562 class with the same (initloader,name) pair has been
1563 stored earlier it will be returned by classcache_store
1564 In this case classcache_store may not free the class
1565 because it has already been exposed to Java code which
1566 may have kept references to that class. */
1568 tmpc = classcache_store(cl, c, false);
1571 /* exception, free the loaded class */
1572 c->state &= ~CLASS_LOADING;
1579 /* loadClass has thrown an exception. We must convert
1580 ClassNotFoundException into
1581 NoClassDefFoundException. */
1583 /* XXX Maybe we should have a flag that avoids this
1584 conversion for calling load_class_from_classloader from
1585 Class.forName. Currently we do a double conversion in
1588 classnotfoundexception_to_noclassdeffounderror();
1591 /* SUN compatible -verbose:class output */
1593 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1595 utf_display_classname(name);
1602 c = load_class_bootstrap(name);
1608 /* load_class_bootstrap ********************************************************
1610 Load the class with the given name using the bootstrap class loader.
1613 name.............the classname
1616 loaded classinfo, or
1617 NULL if an exception has been thrown
1620 load_class_bootstrap is synchronized. It can be treated as an
1623 *******************************************************************************/
1625 classinfo *load_class_bootstrap(utf *name)
1633 LOADER_ASSERT(name);
1635 /* lookup if this class has already been loaded */
1637 if ((r = classcache_lookup(NULL, name)))
1640 /* create the classinfo */
1642 c = class_create_classinfo(name);
1644 /* handle array classes */
1646 if (name->text[0] == '[') {
1647 c = load_newly_created_array(c, NULL);
1650 LOADER_ASSERT(c->state & CLASS_LOADED);
1654 #if defined(ENABLE_STATISTICS)
1657 if (getcompilingtime)
1658 compilingtime_stop();
1661 loadingtime_start();
1664 /* load classdata, throw exception on error */
1666 if ((cb = suck_start(c)) == NULL) {
1667 /* this normally means, the classpath was not set properly */
1669 if (name == utf_java_lang_Object)
1670 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1671 "java/lang/Object");
1673 *exceptionptr = new_noclassdeffounderror(name);
1678 /* load the class from the buffer */
1680 r = load_class_from_classbuffer(cb);
1683 /* the class could not be loaded, free the classinfo struct */
1688 /* Store this class in the loaded class cache this step also
1689 checks the loading constraints. If the class has been loaded
1690 before, the earlier loaded class is returned. */
1692 classinfo *res = classcache_store(NULL, c, true);
1702 /* SUN compatible -verbose:class output */
1704 if (opt_verboseclass && r) {
1706 utf_display_classname(name);
1707 printf(" from %s]\n", cb->path);
1714 #if defined(ENABLE_STATISTICS)
1720 if (getcompilingtime)
1721 compilingtime_start();
1728 /* load_class_from_classbuffer *************************************************
1730 Loads everything interesting about a class from the class file. The
1731 'classinfo' structure must have been allocated previously.
1733 The super class and the interfaces implemented by this class need
1734 not be loaded. The link is set later by the function 'class_link'.
1736 The loaded class is removed from the list 'unloadedclasses' and
1737 added to the list 'unlinkedclasses'.
1740 This function is NOT synchronized!
1742 *******************************************************************************/
1744 classinfo *load_class_from_classbuffer(classbuffer *cb)
1752 descriptor_pool *descpool;
1753 #if defined(ENABLE_STATISTICS)
1758 /* get the classbuffer's class */
1762 /* the class is already loaded */
1764 if (c->state & CLASS_LOADED)
1767 #if defined(ENABLE_STATISTICS)
1769 count_class_loads++;
1772 #if !defined(NDEBUG)
1773 /* output for debugging purposes */
1776 log_message_class("Loading class: ", c);
1779 /* mark start of dump memory area */
1781 dumpsize = dump_size();
1783 /* class is currently loading */
1785 c->state |= CLASS_LOADING;
1787 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1788 goto return_exception;
1790 /* check signature */
1792 if (suck_u4(cb) != MAGIC) {
1793 exceptions_throw_classformaterror(c, "Bad magic number");
1795 goto return_exception;
1803 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1805 new_unsupportedclassversionerror(c,
1806 "Unsupported major.minor version %d.%d",
1809 goto return_exception;
1812 /* create a new descriptor pool */
1814 descpool = descriptor_pool_new(c);
1816 /* load the constant pool */
1818 if (!load_constantpool(cb, descpool))
1819 goto return_exception;
1823 if (!suck_check_classbuffer_size(cb, 2))
1824 goto return_exception;
1826 c->flags = suck_u2(cb);
1828 /* check ACC flags consistency */
1830 if (c->flags & ACC_INTERFACE) {
1831 if (!(c->flags & ACC_ABSTRACT)) {
1832 /* We work around this because interfaces in JDK 1.1 are
1833 * not declared abstract. */
1835 c->flags |= ACC_ABSTRACT;
1838 if (c->flags & ACC_FINAL) {
1839 exceptions_throw_classformaterror(c,
1840 "Illegal class modifiers: 0x%X",
1842 goto return_exception;
1845 if (c->flags & ACC_SUPER) {
1846 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1850 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1851 exceptions_throw_classformaterror(c,
1852 "Illegal class modifiers: 0x%X",
1854 goto return_exception;
1857 if (!suck_check_classbuffer_size(cb, 2 + 2))
1858 goto return_exception;
1863 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1864 goto return_exception;
1866 if (c->name == utf_not_named_yet) {
1867 /* we finally have a name for this class */
1869 class_set_packagename(c);
1871 } else if (name != c->name) {
1875 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1876 utf_strlen(name) + strlen(")") + strlen("0");
1878 msg = MNEW(char, msglen);
1880 utf_sprint(msg, c->name);
1881 strcat(msg, " (wrong name: ");
1882 utf_strcat(msg, name);
1886 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1888 MFREE(msg, char, msglen);
1890 goto return_exception;
1893 /* retrieve superclass */
1895 c->super.any = NULL;
1896 if ((i = suck_u2(cb))) {
1897 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1898 goto return_exception;
1900 /* java.lang.Object may not have a super class. */
1902 if (c->name == utf_java_lang_Object) {
1904 new_exception_message(string_java_lang_ClassFormatError,
1905 "java.lang.Object with superclass");
1907 goto return_exception;
1910 /* Interfaces must have java.lang.Object as super class. */
1912 if ((c->flags & ACC_INTERFACE) &&
1913 supername != utf_java_lang_Object) {
1915 new_exception_message(string_java_lang_ClassFormatError,
1916 "Interfaces must have java.lang.Object as superclass");
1918 goto return_exception;
1924 /* This is only allowed for java.lang.Object. */
1926 if (c->name != utf_java_lang_Object) {
1927 exceptions_throw_classformaterror(c, "Bad superclass index");
1928 goto return_exception;
1932 /* retrieve interfaces */
1934 if (!suck_check_classbuffer_size(cb, 2))
1935 goto return_exception;
1937 c->interfacescount = suck_u2(cb);
1939 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1940 goto return_exception;
1942 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1943 for (i = 0; i < c->interfacescount; i++) {
1944 /* the classrefs are created later */
1945 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1946 goto return_exception;
1950 if (!suck_check_classbuffer_size(cb, 2))
1951 goto return_exception;
1953 c->fieldscount = suck_u2(cb);
1954 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
1955 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
1956 for (i = 0; i < c->fieldscount; i++) {
1957 if (!load_field(cb, &(c->fields[i]),descpool))
1958 goto return_exception;
1962 if (!suck_check_classbuffer_size(cb, 2))
1963 goto return_exception;
1965 c->methodscount = suck_u2(cb);
1966 /* c->methods = GCNEW(methodinfo, c->methodscount); */
1967 c->methods = MNEW(methodinfo, c->methodscount);
1968 for (i = 0; i < c->methodscount; i++) {
1969 if (!load_method(cb, &(c->methods[i]),descpool))
1970 goto return_exception;
1973 /* create the class reference table */
1976 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
1978 /* allocate space for the parsed descriptors */
1980 descriptor_pool_alloc_parsed_descriptors(descpool);
1982 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
1984 #if defined(ENABLE_STATISTICS)
1986 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
1987 count_classref_len += classrefsize;
1988 count_parsed_desc_len += descsize;
1992 /* put the classrefs in the constant pool */
1993 for (i = 0; i < c->cpcount; i++) {
1994 if (c->cptags[i] == CONSTANT_Class) {
1995 utf *name = (utf *) c->cpinfos[i];
1996 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2000 /* set the super class reference */
2003 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2005 goto return_exception;
2008 /* set the super interfaces references */
2010 for (i = 0; i < c->interfacescount; i++) {
2011 c->interfaces[i].ref =
2012 descriptor_pool_lookup_classref(descpool,
2013 (utf *) c->interfaces[i].any);
2014 if (!c->interfaces[i].ref)
2015 goto return_exception;
2018 /* parse field descriptors */
2020 for (i = 0; i < c->fieldscount; i++) {
2021 c->fields[i].parseddesc =
2022 descriptor_pool_parse_field_descriptor(descpool,
2023 c->fields[i].descriptor);
2024 if (!c->fields[i].parseddesc)
2025 goto return_exception;
2028 /* parse method descriptors */
2030 for (i = 0; i < c->methodscount; i++) {
2031 methodinfo *m = &c->methods[i];
2033 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2034 m->flags, class_get_self_classref(m->class));
2036 goto return_exception;
2038 for (j = 0; j < m->exceptiontablelength; j++) {
2039 if (!m->exceptiontable[j].catchtype.any)
2041 if ((m->exceptiontable[j].catchtype.ref =
2042 descriptor_pool_lookup_classref(descpool,
2043 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2044 goto return_exception;
2047 for (j = 0; j < m->thrownexceptionscount; j++) {
2048 if (!m->thrownexceptions[j].any)
2050 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2051 (utf *) m->thrownexceptions[j].any)) == NULL)
2052 goto return_exception;
2056 /* parse the loaded descriptors */
2058 for (i = 0; i < c->cpcount; i++) {
2059 constant_FMIref *fmi;
2062 switch (c->cptags[i]) {
2063 case CONSTANT_Fieldref:
2064 fmi = (constant_FMIref *) c->cpinfos[i];
2065 fmi->parseddesc.fd =
2066 descriptor_pool_parse_field_descriptor(descpool,
2068 if (!fmi->parseddesc.fd)
2069 goto return_exception;
2070 index = (int) (size_t) fmi->classref;
2072 (constant_classref *) class_getconstant(c, index,
2075 goto return_exception;
2077 case CONSTANT_Methodref:
2078 case CONSTANT_InterfaceMethodref:
2079 fmi = (constant_FMIref *) c->cpinfos[i];
2080 index = (int) (size_t) fmi->classref;
2082 (constant_classref *) class_getconstant(c, index,
2085 goto return_exception;
2086 fmi->parseddesc.md =
2087 descriptor_pool_parse_method_descriptor(descpool,
2091 if (!fmi->parseddesc.md)
2092 goto return_exception;
2097 #ifdef ENABLE_VERIFIER
2098 /* Check if all fields and methods can be uniquely
2099 * identified by (name,descriptor). */
2102 /* We use a hash table here to avoid making the
2103 * average case quadratic in # of methods, fields.
2105 static int shift = 0;
2107 u2 *next; /* for chaining colliding hash entries */
2113 /* Allocate hashtable */
2114 len = c->methodscount;
2115 if (len < c->fieldscount) len = c->fieldscount;
2117 hashtab = MNEW(u2,(hashlen + len));
2118 next = hashtab + hashlen;
2120 /* Determine bitshift (to get good hash values) */
2130 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2132 for (i = 0; i < c->fieldscount; ++i) {
2133 fieldinfo *fi = c->fields + i;
2135 /* It's ok if we lose bits here */
2136 index = ((((size_t) fi->name) +
2137 ((size_t) fi->descriptor)) >> shift) % hashlen;
2139 if ((old = hashtab[index])) {
2143 if (c->fields[old].name == fi->name &&
2144 c->fields[old].descriptor == fi->descriptor) {
2145 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2146 goto return_exception;
2148 } while ((old = next[old]));
2150 hashtab[index] = i + 1;
2154 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2156 for (i = 0; i < c->methodscount; ++i) {
2157 methodinfo *mi = c->methods + i;
2159 /* It's ok if we lose bits here */
2160 index = ((((size_t) mi->name) +
2161 ((size_t) mi->descriptor)) >> shift) % hashlen;
2165 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2166 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2170 if ((old = hashtab[index])) {
2174 if (c->methods[old].name == mi->name &&
2175 c->methods[old].descriptor == mi->descriptor) {
2176 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2177 goto return_exception;
2179 } while ((old = next[old]));
2181 hashtab[index] = i + 1;
2184 MFREE(hashtab, u2, (hashlen + len));
2186 #endif /* ENABLE_VERIFIER */
2188 #if defined(ENABLE_STATISTICS)
2190 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2191 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2192 count_class_infos += sizeof(methodinfo) * c->methodscount;
2196 /* load attribute structures */
2198 if (!suck_check_classbuffer_size(cb, 2))
2199 goto return_exception;
2201 if (!load_attributes(cb, suck_u2(cb)))
2202 goto return_exception;
2205 /* Pre java 1.5 version don't check this. This implementation is like
2206 java 1.5 do it: for class file version 45.3 we don't check it, older
2207 versions are checked.
2209 if ((ma == 45 && mi > 3) || ma > 45) {
2210 /* check if all data has been read */
2211 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2213 if (classdata_left > 0) {
2214 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2215 goto return_exception;
2220 /* release dump area */
2222 dump_release(dumpsize);
2224 /* revert loading state and class is loaded */
2226 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2228 #if !defined(NDEBUG)
2230 log_message_class("Loading done class: ", c);
2236 /* release dump area */
2238 dump_release(dumpsize);
2240 /* an exception has been thrown */
2246 /* load_newly_created_array ****************************************************
2248 Load a newly created array class.
2251 c....................the array class C has been loaded
2252 other classinfo......the array class was found in the class cache,
2254 NULL.................an exception has been thrown
2257 This is an internal function. Do not use it unless you know exactly
2260 Use one of the load_class_... functions for general array class loading.
2262 *******************************************************************************/
2264 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2266 classinfo *comp = NULL;
2268 methoddesc *clonedesc;
2269 constant_classref *classrefs;
2274 text = c->name->text;
2275 namelen = c->name->blength;
2277 /* Check array class name */
2279 if (namelen < 2 || text[0] != '[') {
2280 *exceptionptr = new_noclassdeffounderror(c->name);
2284 /* Check the element type */
2288 /* c is an array of arrays. We have to create the component class. */
2290 u = utf_new(text + 1, namelen - 1);
2291 if (!(comp = load_class_from_classloader(u, loader)))
2294 LOADER_ASSERT(comp->state & CLASS_LOADED);
2300 /* the array's flags are that of the component class */
2301 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2302 c->classloader = comp->classloader;
2306 /* c is an array of objects. */
2308 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2309 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2310 *exceptionptr = new_noclassdeffounderror(c->name);
2314 u = utf_new(text + 2, namelen - 3);
2316 if (!(comp = load_class_from_classloader(u, loader)))
2319 LOADER_ASSERT(comp->state & CLASS_LOADED);
2325 /* the array's flags are that of the component class */
2326 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2327 c->classloader = comp->classloader;
2331 /* c is an array of a primitive type */
2333 /* check for cases like `[II' */
2335 *exceptionptr = new_noclassdeffounderror(c->name);
2339 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2340 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2341 c->classloader = NULL;
2344 LOADER_ASSERT(class_java_lang_Object);
2345 LOADER_ASSERT(class_java_lang_Cloneable);
2346 LOADER_ASSERT(class_java_io_Serializable);
2348 /* setup the array class */
2350 c->super.cls = class_java_lang_Object;
2352 c->interfacescount = 2;
2353 c->interfaces = MNEW(classref_or_classinfo, 2);
2358 tc = class_java_lang_Cloneable;
2359 LOADER_ASSERT(tc->state & CLASS_LOADED);
2360 list_addfirst(&unlinkedclasses, tc);
2361 c->interfaces[0].cls = tc;
2363 tc = class_java_io_Serializable;
2364 LOADER_ASSERT(tc->state & CLASS_LOADED);
2365 list_addfirst(&unlinkedclasses, tc);
2366 c->interfaces[1].cls = tc;
2369 c->interfaces[0].cls = class_java_lang_Cloneable;
2370 c->interfaces[1].cls = class_java_io_Serializable;
2373 c->methodscount = 1;
2374 c->methods = MNEW(methodinfo, c->methodscount);
2376 classrefs = MNEW(constant_classref, 2);
2377 CLASSREF_INIT(classrefs[0], c, c->name);
2378 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2380 /* create descriptor for clone method */
2381 /* we need one paramslot which is reserved for the 'this' parameter */
2382 clonedesc = NEW(methoddesc);
2383 clonedesc->returntype.type = TYPE_ADDRESS;
2384 clonedesc->returntype.classref = classrefs + 1;
2385 clonedesc->returntype.arraydim = 0;
2386 /* initialize params to "empty", add real params below in
2387 descriptor_params_from_paramtypes */
2388 clonedesc->paramcount = 0;
2389 clonedesc->paramslots = 0;
2390 clonedesc->paramtypes[0].classref = classrefs + 0;
2392 /* create methodinfo */
2395 MSET(clone, 0, methodinfo, 1);
2397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2398 initObjectLock(&clone->header);
2401 /* ATTENTION: if you delete the ACC_NATIVE below, set
2402 clone->maxlocals=1 (interpreter related) */
2404 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2405 clone->name = utf_clone;
2406 clone->descriptor = utf_void__java_lang_Object;
2407 clone->parseddesc = clonedesc;
2410 /* parse the descriptor to get the register allocation */
2412 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2416 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2418 /* XXX: field: length? */
2420 /* array classes are not loaded from class files */
2422 c->state |= CLASS_LOADED;
2423 c->parseddescs = (u1 *) clonedesc;
2424 c->parseddescsize = sizeof(methodinfo);
2425 c->classrefs = classrefs;
2426 c->classrefcount = 1;
2428 /* insert class into the loaded class cache */
2429 /* XXX free classinfo if NULL returned? */
2431 return classcache_store(loader, c, true);
2435 /* loader_close ****************************************************************
2437 Frees all resources.
2439 *******************************************************************************/
2441 void loader_close(void)
2448 * These are local overrides for various environment variables in Emacs.
2449 * Please do not remove this and leave it at the end of the file, where
2450 * Emacs will automagically detect them.
2451 * ---------------------------------------------------------------------
2454 * indent-tabs-mode: t
2458 * vim:noexpandtab:sw=4:ts=4: