1 /* src/vm/loader.c - class loader functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: loader.c 4127 2006-01-10 20:56:16Z 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;
244 hashtable_zipfile_entry *htzfe;
247 for (lce = list_first(list_classpath_entries); lce != NULL;
248 lce = list_next(list_classpath_entries, lce)) {
249 #if defined(ENABLE_ZLIB)
250 if (lce->type == CLASSPATH_ARCHIVE) {
251 /* get the classes hashtable */
255 for (slot = 0; slot < ht->size; slot++) {
256 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
258 for (; htzfe; htzfe = htzfe->hashlink) {
261 /* skip all entries in META-INF and .properties,
264 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
265 strstr(u->text, ".properties") ||
266 strstr(u->text, ".png"))
269 /* load class from bootstrap classloader */
271 if (!load_class_bootstrap(u)) {
272 fprintf(stderr, "Error loading: ");
273 utf_fprint_classname(stderr, u);
274 fprintf(stderr, "\n");
276 /* print out exception and cause */
278 exceptions_print_exception(*exceptionptr);
285 #if defined(ENABLE_ZLIB)
292 /******************************************************************************/
293 /******************* Some support functions ***********************************/
294 /******************************************************************************/
296 void fprintflags (FILE *fp, u2 f)
298 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
299 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
300 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
301 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
302 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
303 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
304 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
305 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
306 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
307 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
308 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
312 /********** internal function: printflags (only for debugging) ***************/
314 void printflags(u2 f)
316 fprintflags(stdout,f);
320 /********************** Function: skipattributebody ****************************
322 skips an attribute after the 16 bit reference to attribute_name has already
325 *******************************************************************************/
327 static bool skipattributebody(classbuffer *cb)
331 if (!suck_check_classbuffer_size(cb, 4))
336 if (!suck_check_classbuffer_size(cb, len))
339 suck_skip_nbytes(cb, len);
345 /************************* Function: skipattributes ****************************
347 skips num attribute structures
349 *******************************************************************************/
351 static bool skipattributes(classbuffer *cb, u4 num)
356 for (i = 0; i < num; i++) {
357 if (!suck_check_classbuffer_size(cb, 2 + 4))
363 if (!suck_check_classbuffer_size(cb, len))
366 suck_skip_nbytes(cb, len);
373 /* load_constantpool ***********************************************************
375 Loads the constantpool of a class, the entries are transformed into
376 a simpler format by resolving references (a detailed overview of
377 the compact structures can be found in global.h).
379 *******************************************************************************/
381 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
384 /* The following structures are used to save information which cannot be
385 processed during the first pass. After the complete constantpool has
386 been traversed the references can be resolved.
387 (only in specific order) */
389 /* CONSTANT_Class entries */
390 typedef struct forward_class {
391 struct forward_class *next;
396 /* CONSTANT_String */
397 typedef struct forward_string {
398 struct forward_string *next;
403 /* CONSTANT_NameAndType */
404 typedef struct forward_nameandtype {
405 struct forward_nameandtype *next;
409 } forward_nameandtype;
411 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
412 typedef struct forward_fieldmethint {
413 struct forward_fieldmethint *next;
417 u2 nameandtype_index;
418 } forward_fieldmethint;
424 forward_class *forward_classes = NULL;
425 forward_string *forward_strings = NULL;
426 forward_nameandtype *forward_nameandtypes = NULL;
427 forward_fieldmethint *forward_fieldmethints = NULL;
431 forward_nameandtype *nfn;
432 forward_fieldmethint *nff;
440 /* number of entries in the constant_pool table plus one */
441 if (!suck_check_classbuffer_size(cb, 2))
444 cpcount = c->cpcount = suck_u2(cb);
446 /* allocate memory */
447 cptags = c->cptags = MNEW(u1, cpcount);
448 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
451 exceptions_throw_classformaterror(c, "Illegal constant pool size");
455 #if defined(ENABLE_STATISTICS)
457 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
460 /* initialize constantpool */
461 for (idx = 0; idx < cpcount; idx++) {
462 cptags[idx] = CONSTANT_UNUSED;
467 /******* first pass *******/
468 /* entries which cannot be resolved now are written into
469 temporary structures and traversed again later */
472 while (idx < cpcount) {
475 /* get constant type */
476 if (!suck_check_classbuffer_size(cb, 1))
483 nfc = DNEW(forward_class);
485 nfc->next = forward_classes;
486 forward_classes = nfc;
488 nfc->thisindex = idx;
489 /* reference to CONSTANT_NameAndType */
490 if (!suck_check_classbuffer_size(cb, 2))
493 nfc->name_index = suck_u2(cb);
498 case CONSTANT_String:
499 nfs = DNEW(forward_string);
501 nfs->next = forward_strings;
502 forward_strings = nfs;
504 nfs->thisindex = idx;
506 /* reference to CONSTANT_Utf8_info with string characters */
507 if (!suck_check_classbuffer_size(cb, 2))
510 nfs->string_index = suck_u2(cb);
515 case CONSTANT_NameAndType:
516 nfn = DNEW(forward_nameandtype);
518 nfn->next = forward_nameandtypes;
519 forward_nameandtypes = nfn;
521 nfn->thisindex = idx;
523 if (!suck_check_classbuffer_size(cb, 2 + 2))
526 /* reference to CONSTANT_Utf8_info containing simple name */
527 nfn->name_index = suck_u2(cb);
529 /* reference to CONSTANT_Utf8_info containing field or method
531 nfn->sig_index = suck_u2(cb);
536 case CONSTANT_Fieldref:
537 case CONSTANT_Methodref:
538 case CONSTANT_InterfaceMethodref:
539 nff = DNEW(forward_fieldmethint);
541 nff->next = forward_fieldmethints;
542 forward_fieldmethints = nff;
544 nff->thisindex = idx;
548 if (!suck_check_classbuffer_size(cb, 2 + 2))
551 /* class or interface type that contains the declaration of the
553 nff->class_index = suck_u2(cb);
555 /* name and descriptor of the field or method */
556 nff->nameandtype_index = suck_u2(cb);
561 case CONSTANT_Integer: {
562 constant_integer *ci = NEW(constant_integer);
564 #if defined(ENABLE_STATISTICS)
566 count_const_pool_len += sizeof(constant_integer);
569 if (!suck_check_classbuffer_size(cb, 4))
572 ci->value = suck_s4(cb);
573 cptags[idx] = CONSTANT_Integer;
580 case CONSTANT_Float: {
581 constant_float *cf = NEW(constant_float);
583 #if defined(ENABLE_STATISTICS)
585 count_const_pool_len += sizeof(constant_float);
588 if (!suck_check_classbuffer_size(cb, 4))
591 cf->value = suck_float(cb);
592 cptags[idx] = CONSTANT_Float;
599 case CONSTANT_Long: {
600 constant_long *cl = NEW(constant_long);
602 #if defined(ENABLE_STATISTICS)
604 count_const_pool_len += sizeof(constant_long);
607 if (!suck_check_classbuffer_size(cb, 8))
610 cl->value = suck_s8(cb);
611 cptags[idx] = CONSTANT_Long;
615 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
621 case CONSTANT_Double: {
622 constant_double *cd = NEW(constant_double);
624 #if defined(ENABLE_STATISTICS)
626 count_const_pool_len += sizeof(constant_double);
629 if (!suck_check_classbuffer_size(cb, 8))
632 cd->value = suck_double(cb);
633 cptags[idx] = CONSTANT_Double;
637 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
643 case CONSTANT_Utf8: {
646 /* number of bytes in the bytes array (not string-length) */
647 if (!suck_check_classbuffer_size(cb, 2))
650 length = suck_u2(cb);
651 cptags[idx] = CONSTANT_Utf8;
653 /* validate the string */
654 if (!suck_check_classbuffer_size(cb, length))
657 #ifdef ENABLE_VERIFIER
659 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
661 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
664 #endif /* ENABLE_VERIFIER */
665 /* insert utf-string into the utf-symboltable */
666 cpinfos[idx] = utf_new((char *) cb->pos, length);
668 /* skip bytes of the string (buffer size check above) */
669 suck_skip_nbytes(cb, length);
675 exceptions_throw_classformaterror(c, "Illegal constant pool type");
681 /* resolve entries in temporary structures */
683 while (forward_classes) {
685 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
689 #ifdef ENABLE_VERIFIER
690 if (opt_verify && !is_valid_name_utf(name)) {
691 exceptions_throw_classformaterror(c, "Class reference with invalid name");
694 #endif /* ENABLE_VERIFIER */
696 /* add all class references to the descriptor_pool */
698 if (!descriptor_pool_add_class(descpool, name))
701 cptags[forward_classes->thisindex] = CONSTANT_Class;
706 if (!(tc = load_class_bootstrap(name)))
709 /* link the class later, because we cannot link the class currently
711 list_addfirst(&unlinkedclasses, tc);
714 /* the classref is created later */
715 cpinfos[forward_classes->thisindex] = name;
717 nfc = forward_classes;
718 forward_classes = forward_classes->next;
721 while (forward_strings) {
723 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
727 /* resolve utf-string */
728 cptags[forward_strings->thisindex] = CONSTANT_String;
729 cpinfos[forward_strings->thisindex] = text;
731 nfs = forward_strings;
732 forward_strings = forward_strings->next;
735 while (forward_nameandtypes) {
736 constant_nameandtype *cn = NEW(constant_nameandtype);
738 #if defined(ENABLE_STATISTICS)
740 count_const_pool_len += sizeof(constant_nameandtype);
743 /* resolve simple name and descriptor */
744 cn->name = class_getconstant(c,
745 forward_nameandtypes->name_index,
750 cn->descriptor = class_getconstant(c,
751 forward_nameandtypes->sig_index,
756 #ifdef ENABLE_VERIFIER
759 if (!is_valid_name_utf(cn->name)) {
760 exceptions_throw_classformaterror(c,
761 "Illegal Field name \"%s\"",
767 /* disallow referencing <clinit> among others */
768 if (cn->name->text[0] == '<' && cn->name != utf_init) {
769 exceptions_throw_classformaterror(c, "Illegal reference to special method");
773 #endif /* ENABLE_VERIFIER */
775 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
776 cpinfos[forward_nameandtypes->thisindex] = cn;
778 nfn = forward_nameandtypes;
779 forward_nameandtypes = forward_nameandtypes->next;
782 while (forward_fieldmethints) {
783 constant_nameandtype *nat;
784 constant_FMIref *fmi = NEW(constant_FMIref);
786 #if defined(ENABLE_STATISTICS)
788 count_const_pool_len += sizeof(constant_FMIref);
790 /* resolve simple name and descriptor */
792 nat = class_getconstant(c,
793 forward_fieldmethints->nameandtype_index,
794 CONSTANT_NameAndType);
798 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
800 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
803 /* the classref is created later */
805 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
806 fmi->name = nat->name;
807 fmi->descriptor = nat->descriptor;
809 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
810 cpinfos[forward_fieldmethints->thisindex] = fmi;
812 nff = forward_fieldmethints;
813 forward_fieldmethints = forward_fieldmethints->next;
816 /* everything was ok */
822 /* load_field ******************************************************************
824 Load everything about a class field from the class file and fill a
825 'fieldinfo' structure. For static fields, space in the data segment
828 *******************************************************************************/
830 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
832 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
837 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
842 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
845 f->flags = suck_u2(cb);
847 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
852 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
856 f->parseddesc = NULL;
858 if (!descriptor_pool_add(descpool, u, NULL))
861 /* descriptor_pool_add accepts method descriptors, so we have to check */
862 /* against them here before the call of descriptor_to_basic_type below. */
863 if (u->text[0] == '(') {
864 exceptions_throw_classformaterror(c, "Method descriptor used for field");
868 #ifdef ENABLE_VERIFIER
871 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
872 exceptions_throw_classformaterror(c,
873 "Illegal Field name \"%s\"",
878 /* check flag consistency */
879 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
881 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
882 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
883 exceptions_throw_classformaterror(c,
884 "Illegal field modifiers: 0x%X",
889 if (c->flags & ACC_INTERFACE) {
890 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
891 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
892 f->flags & ACC_TRANSIENT) {
893 exceptions_throw_classformaterror(c,
894 "Illegal field modifiers: 0x%X",
900 #endif /* ENABLE_VERIFIER */
902 f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
903 f->offset = 0; /* offset from start of object */
908 case TYPE_INT: f->value.i = 0; break;
909 case TYPE_FLOAT: f->value.f = 0.0; break;
910 case TYPE_DOUBLE: f->value.d = 0.0; break;
911 case TYPE_ADDRESS: f->value.a = NULL; break;
914 f->value.l = 0; break;
916 f->value.l.low = 0; f->value.l.high = 0; break;
920 /* read attributes */
921 if (!suck_check_classbuffer_size(cb, 2))
924 attrnum = suck_u2(cb);
925 for (i = 0; i < attrnum; i++) {
926 if (!suck_check_classbuffer_size(cb, 2))
929 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
932 if (u == utf_ConstantValue) {
933 if (!suck_check_classbuffer_size(cb, 4 + 2))
936 /* check attribute length */
937 if (suck_u4(cb) != 2) {
938 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
942 /* constant value attribute */
943 if (pindex != field_load_NOVALUE) {
944 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
948 /* index of value in constantpool */
949 pindex = suck_u2(cb);
951 /* initialize field with value from constantpool */
954 constant_integer *ci;
956 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
959 f->value.i = ci->value;
966 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
969 f->value.l = cl->value;
976 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
979 f->value.f = cf->value;
986 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
989 f->value.d = cd->value;
994 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
997 /* create javastring from compressed utf8-string */
998 f->value.a = literalstring_new(u);
1002 log_text("Invalid Constant - Type");
1006 /* unknown attribute */
1007 if (!skipattributebody(cb))
1012 /* everything was ok */
1018 /* load_method *****************************************************************
1020 Loads a method from the class file and fills an existing
1021 'methodinfo' structure. For native methods, the function pointer
1022 field is set to the real function pointer, for JavaVM methods a
1023 pointer to the compiler is used preliminarily.
1025 *******************************************************************************/
1027 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1038 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1039 initObjectLock(&m->header);
1042 #if defined(ENABLE_STATISTICS)
1044 count_all_methods++;
1047 m->thrownexceptionscount = 0;
1048 m->linenumbercount = 0;
1051 m->nativelyoverloaded = false;
1053 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1056 m->flags = suck_u2(cb);
1058 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1063 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1067 m->parseddesc = NULL;
1069 if (!descriptor_pool_add(descpool, u, &argcount))
1072 #ifdef ENABLE_VERIFIER
1074 if (!is_valid_name_utf(m->name)) {
1075 exceptions_throw_classformaterror(c, "Method with invalid name");
1079 if (m->name->text[0] == '<' &&
1080 m->name != utf_init && m->name != utf_clinit) {
1081 exceptions_throw_classformaterror(c, "Method with invalid special name");
1085 #endif /* ENABLE_VERIFIER */
1087 if (!(m->flags & ACC_STATIC))
1088 argcount++; /* count the 'this' argument */
1090 #ifdef ENABLE_VERIFIER
1092 if (argcount > 255) {
1093 exceptions_throw_classformaterror(c, "Too many arguments in signature");
1097 /* check flag consistency */
1098 if (m->name != utf_clinit) {
1099 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1101 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1102 exceptions_throw_classformaterror(c,
1103 "Illegal method modifiers: 0x%X",
1108 if (m->flags & ACC_ABSTRACT) {
1109 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1110 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1111 exceptions_throw_classformaterror(c,
1112 "Illegal method modifiers: 0x%X",
1118 if (c->flags & ACC_INTERFACE) {
1119 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1120 exceptions_throw_classformaterror(c,
1121 "Illegal method modifiers: 0x%X",
1127 if (m->name == utf_init) {
1128 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1129 ACC_NATIVE | ACC_ABSTRACT)) {
1130 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1136 #endif /* ENABLE_VERIFIER */
1139 m->basicblockcount = 0;
1140 m->basicblocks = NULL;
1141 m->basicblockindex = NULL;
1142 m->instructioncount = 0;
1143 m->instructions = NULL;
1146 m->exceptiontable = NULL;
1147 m->stubroutine = NULL;
1149 m->entrypoint = NULL;
1150 m->methodUsed = NOTUSED;
1153 m->subRedefsUsed = 0;
1157 if (!suck_check_classbuffer_size(cb, 2))
1160 attrnum = suck_u2(cb);
1161 for (i = 0; i < attrnum; i++) {
1164 if (!suck_check_classbuffer_size(cb, 2))
1167 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1170 if (aname == utf_Code) {
1171 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1172 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1177 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1181 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1185 m->maxstack = suck_u2(cb);
1186 m->maxlocals = suck_u2(cb);
1188 if (m->maxlocals < argcount) {
1189 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1193 if (!suck_check_classbuffer_size(cb, 4))
1196 m->jcodelength = suck_u4(cb);
1198 if (m->jcodelength == 0) {
1199 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1203 if (m->jcodelength > 65535) {
1204 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1208 if (!suck_check_classbuffer_size(cb, m->jcodelength))
1211 m->jcode = MNEW(u1, m->jcodelength);
1212 suck_nbytes(m->jcode, cb, m->jcodelength);
1214 if (!suck_check_classbuffer_size(cb, 2))
1217 m->exceptiontablelength = suck_u2(cb);
1218 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1221 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1223 #if defined(ENABLE_STATISTICS)
1225 count_vmcode_len += m->jcodelength + 18;
1226 count_extable_len +=
1227 m->exceptiontablelength * sizeof(exceptiontable);
1231 for (j = 0; j < m->exceptiontablelength; j++) {
1233 m->exceptiontable[j].startpc = suck_u2(cb);
1234 m->exceptiontable[j].endpc = suck_u2(cb);
1235 m->exceptiontable[j].handlerpc = suck_u2(cb);
1239 m->exceptiontable[j].catchtype.any = NULL;
1242 /* the classref is created later */
1243 if (!(m->exceptiontable[j].catchtype.any =
1244 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1249 if (!suck_check_classbuffer_size(cb, 2))
1252 codeattrnum = suck_u2(cb);
1254 for (; codeattrnum > 0; codeattrnum--) {
1257 if (!suck_check_classbuffer_size(cb, 2))
1260 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1263 if (caname == utf_LineNumberTable) {
1266 if (!suck_check_classbuffer_size(cb, 4 + 2))
1270 m->linenumbercount = suck_u2(cb);
1272 if (!suck_check_classbuffer_size(cb,
1273 (2 + 2) * m->linenumbercount))
1276 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1278 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1279 m->linenumbers[lncid].start_pc = suck_u2(cb);
1280 m->linenumbers[lncid].line_number = suck_u2(cb);
1284 if (!skipattributes(cb, codeattrnum))
1290 if (!skipattributebody(cb))
1295 } else if (aname == utf_Exceptions) {
1298 if (m->thrownexceptions) {
1299 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1303 if (!suck_check_classbuffer_size(cb, 4 + 2))
1306 suck_u4(cb); /* length */
1307 m->thrownexceptionscount = suck_u2(cb);
1309 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1312 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1314 for (j = 0; j < m->thrownexceptionscount; j++) {
1315 /* the classref is created later */
1316 if (!((m->thrownexceptions)[j].any =
1317 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1322 if (!skipattributebody(cb))
1327 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1328 exceptions_throw_classformaterror(c, "Missing Code attribute");
1332 /* everything was ok */
1338 /* load_attribute **************************************************************
1340 Read attributes from classfile.
1342 *******************************************************************************/
1344 static bool load_attributes(classbuffer *cb, u4 num)
1352 for (i = 0; i < num; i++) {
1353 /* retrieve attribute name */
1354 if (!suck_check_classbuffer_size(cb, 2))
1357 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1360 if (aname == utf_InnerClasses) {
1361 /* innerclasses attribute */
1362 if (c->innerclass) {
1363 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1367 if (!suck_check_classbuffer_size(cb, 4 + 2))
1370 /* skip attribute length */
1373 /* number of records */
1374 c->innerclasscount = suck_u2(cb);
1376 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1379 /* allocate memory for innerclass structure */
1380 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1382 for (j = 0; j < c->innerclasscount; j++) {
1383 /* The innerclass structure contains a class with an encoded
1384 name, its defining scope, its simple name and a bitmask of
1385 the access flags. If an inner class is not a member, its
1386 outer_class is NULL, if a class is anonymous, its name is
1389 innerclassinfo *info = c->innerclass + j;
1391 info->inner_class.ref =
1392 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1393 info->outer_class.ref =
1394 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1396 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1397 info->flags = suck_u2(cb);
1400 } else if (aname == utf_SourceFile) {
1401 if (!suck_check_classbuffer_size(cb, 4 + 2))
1404 if (suck_u4(cb) != 2) {
1405 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1409 if (c->sourcefile) {
1410 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1414 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1418 /* unknown attribute */
1419 if (!skipattributebody(cb))
1428 /* load_class_from_sysloader ***************************************************
1430 Load the class with the given name using the system class loader
1433 name.............the classname
1436 the loaded class, or
1437 NULL if an exception has been thrown
1439 *******************************************************************************/
1441 classinfo *load_class_from_sysloader(utf *name)
1444 java_objectheader *cl;
1447 LOADER_ASSERT(class_java_lang_Object);
1448 LOADER_ASSERT(class_java_lang_ClassLoader);
1449 LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1451 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1452 utf_getSystemClassLoader,
1453 utf_void__java_lang_ClassLoader,
1454 class_java_lang_Object,
1460 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1465 c = load_class_from_classloader(name, cl);
1471 /* load_class_from_classloader *************************************************
1473 Load the class with the given name using the given user-defined class loader.
1476 name.............the classname
1477 cl...............user-defined class loader
1480 the loaded class, or
1481 NULL if an exception has been thrown
1483 *******************************************************************************/
1485 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1490 LOADER_ASSERT(name);
1492 /* lookup if this class has already been loaded */
1494 c = classcache_lookup(cl, name);
1499 /* if other class loader than bootstrap, call it */
1507 namelen = name->blength;
1509 /* handle array classes */
1510 if (text[0] == '[') {
1516 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1517 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1518 *exceptionptr = new_noclassdeffounderror(name);
1522 u = utf_new(text + 2, namelen - 3);
1524 if (!(comp = load_class_from_classloader(u, cl)))
1527 /* create the array class */
1529 c = class_array_of(comp, false);
1531 tmpc = classcache_store(cl, c, true);
1534 /* exception, free the loaded class */
1535 c->state &= ~CLASS_LOADING;
1542 /* load the component class */
1544 u = utf_new(text + 1, namelen - 1);
1546 if (!(comp = load_class_from_classloader(u, cl)))
1549 /* create the array class */
1551 c = class_array_of(comp, false);
1553 tmpc = classcache_store(cl, c, true);
1556 /* exception, free the loaded class */
1557 c->state &= ~CLASS_LOADING;
1564 /* primitive array classes are loaded by the bootstrap loader */
1566 c = load_class_bootstrap(name);
1572 LOADER_ASSERT(class_java_lang_Object);
1574 lc = class_resolveclassmethod(cl->vftbl->class,
1576 utf_java_lang_String__java_lang_Class,
1577 class_java_lang_Object,
1581 return false; /* exception */
1583 c = (classinfo *) asm_calljavafunction(lc,
1585 javastring_new_slash_to_dot(name),
1589 /* Store this class in the loaded class cache. If another
1590 class with the same (initloader,name) pair has been
1591 stored earlier it will be returned by classcache_store
1592 In this case classcache_store may not free the class
1593 because it has already been exposed to Java code which
1594 may have kept references to that class. */
1596 tmpc = classcache_store(cl, c, false);
1599 /* exception, free the loaded class */
1600 c->state &= ~CLASS_LOADING;
1607 /* loadClass has thrown an exception */
1608 /* we must convert ClassNotFoundException into NoClassDefFoundException */
1609 /* XXX maybe we should have a flag that avoids this conversion */
1610 /* for calling load_class_from_classloader from Class.forName */
1611 /* Currently we do a double conversion in these cases */
1612 classnotfoundexception_to_noclassdeffounderror();
1615 /* SUN compatible -verbose:class output */
1617 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1619 utf_display_classname(name);
1626 c = load_class_bootstrap(name);
1632 /* load_class_bootstrap ********************************************************
1634 Load the class with the given name using the bootstrap class loader.
1637 name.............the classname
1640 loaded classinfo, or
1641 NULL if an exception has been thrown
1644 load_class_bootstrap is synchronized. It can be treated as an
1647 *******************************************************************************/
1649 classinfo *load_class_bootstrap(utf *name)
1657 LOADER_ASSERT(name);
1659 /* lookup if this class has already been loaded */
1661 if ((r = classcache_lookup(NULL, name)))
1664 /* create the classinfo */
1666 c = class_create_classinfo(name);
1668 /* handle array classes */
1670 if (name->text[0] == '[') {
1671 c = load_newly_created_array(c, NULL);
1674 LOADER_ASSERT(c->state & CLASS_LOADED);
1678 #if defined(ENABLE_STATISTICS)
1681 if (getcompilingtime)
1682 compilingtime_stop();
1685 loadingtime_start();
1688 /* load classdata, throw exception on error */
1690 if ((cb = suck_start(c)) == NULL) {
1691 /* this normally means, the classpath was not set properly */
1693 if (name == utf_java_lang_Object)
1694 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1695 "java/lang/Object");
1697 *exceptionptr = new_noclassdeffounderror(name);
1702 /* load the class from the buffer */
1704 r = load_class_from_classbuffer(cb);
1707 /* the class could not be loaded, free the classinfo struct */
1712 /* Store this class in the loaded class cache this step also
1713 checks the loading constraints. If the class has been loaded
1714 before, the earlier loaded class is returned. */
1716 classinfo *res = classcache_store(NULL, c, true);
1726 /* SUN compatible -verbose:class output */
1728 if (opt_verboseclass && r) {
1730 utf_display_classname(name);
1731 printf(" from %s]\n", cb->path);
1738 #if defined(ENABLE_STATISTICS)
1744 if (getcompilingtime)
1745 compilingtime_start();
1752 /* load_class_from_classbuffer *************************************************
1754 Loads everything interesting about a class from the class file. The
1755 'classinfo' structure must have been allocated previously.
1757 The super class and the interfaces implemented by this class need
1758 not be loaded. The link is set later by the function 'class_link'.
1760 The loaded class is removed from the list 'unloadedclasses' and
1761 added to the list 'unlinkedclasses'.
1764 This function is NOT synchronized!
1766 *******************************************************************************/
1768 classinfo *load_class_from_classbuffer(classbuffer *cb)
1776 descriptor_pool *descpool;
1777 #if defined(ENABLE_STATISTICS)
1782 /* get the classbuffer's class */
1786 /* the class is already loaded */
1788 if (c->state & CLASS_LOADED)
1791 #if defined(ENABLE_STATISTICS)
1793 count_class_loads++;
1796 #if !defined(NDEBUG)
1797 /* output for debugging purposes */
1800 log_message_class("Loading class: ", c);
1803 /* mark start of dump memory area */
1805 dumpsize = dump_size();
1807 /* class is currently loading */
1809 c->state |= CLASS_LOADING;
1811 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1812 goto return_exception;
1814 /* check signature */
1816 if (suck_u4(cb) != MAGIC) {
1817 exceptions_throw_classformaterror(c, "Bad magic number");
1819 goto return_exception;
1827 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1829 new_unsupportedclassversionerror(c,
1830 "Unsupported major.minor version %d.%d",
1833 goto return_exception;
1836 /* create a new descriptor pool */
1838 descpool = descriptor_pool_new(c);
1840 /* load the constant pool */
1842 if (!load_constantpool(cb, descpool))
1843 goto return_exception;
1845 c->classUsed = NOTUSED; /* not used initially CO-RT */
1850 if (!suck_check_classbuffer_size(cb, 2))
1851 goto return_exception;
1853 c->flags = suck_u2(cb);
1855 /* check ACC flags consistency */
1857 if (c->flags & ACC_INTERFACE) {
1858 if (!(c->flags & ACC_ABSTRACT)) {
1859 /* We work around this because interfaces in JDK 1.1 are
1860 * not declared abstract. */
1862 c->flags |= ACC_ABSTRACT;
1865 if (c->flags & ACC_FINAL) {
1866 exceptions_throw_classformaterror(c,
1867 "Illegal class modifiers: 0x%X",
1869 goto return_exception;
1872 if (c->flags & ACC_SUPER) {
1873 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1877 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1878 exceptions_throw_classformaterror(c,
1879 "Illegal class modifiers: 0x%X",
1881 goto return_exception;
1884 if (!suck_check_classbuffer_size(cb, 2 + 2))
1885 goto return_exception;
1890 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1891 goto return_exception;
1893 if (c->name == utf_not_named_yet) {
1894 /* we finally have a name for this class */
1896 class_set_packagename(c);
1898 } else if (name != c->name) {
1902 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1903 utf_strlen(name) + strlen(")") + strlen("0");
1905 msg = MNEW(char, msglen);
1907 utf_sprint(msg, c->name);
1908 strcat(msg, " (wrong name: ");
1909 utf_strcat(msg, name);
1913 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1915 MFREE(msg, char, msglen);
1917 goto return_exception;
1920 /* retrieve superclass */
1922 c->super.any = NULL;
1923 if ((i = suck_u2(cb))) {
1924 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1925 goto return_exception;
1927 /* java.lang.Object may not have a super class. */
1929 if (c->name == utf_java_lang_Object) {
1931 new_exception_message(string_java_lang_ClassFormatError,
1932 "java.lang.Object with superclass");
1934 goto return_exception;
1937 /* Interfaces must have java.lang.Object as super class. */
1939 if ((c->flags & ACC_INTERFACE) &&
1940 supername != utf_java_lang_Object) {
1942 new_exception_message(string_java_lang_ClassFormatError,
1943 "Interfaces must have java.lang.Object as superclass");
1945 goto return_exception;
1951 /* This is only allowed for java.lang.Object. */
1953 if (c->name != utf_java_lang_Object) {
1954 exceptions_throw_classformaterror(c, "Bad superclass index");
1955 goto return_exception;
1959 /* retrieve interfaces */
1961 if (!suck_check_classbuffer_size(cb, 2))
1962 goto return_exception;
1964 c->interfacescount = suck_u2(cb);
1966 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1967 goto return_exception;
1969 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1970 for (i = 0; i < c->interfacescount; i++) {
1971 /* the classrefs are created later */
1972 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1973 goto return_exception;
1977 if (!suck_check_classbuffer_size(cb, 2))
1978 goto return_exception;
1980 c->fieldscount = suck_u2(cb);
1981 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
1982 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
1983 for (i = 0; i < c->fieldscount; i++) {
1984 if (!load_field(cb, &(c->fields[i]),descpool))
1985 goto return_exception;
1989 if (!suck_check_classbuffer_size(cb, 2))
1990 goto return_exception;
1992 c->methodscount = suck_u2(cb);
1993 /* c->methods = GCNEW(methodinfo, c->methodscount); */
1994 c->methods = MNEW(methodinfo, c->methodscount);
1995 for (i = 0; i < c->methodscount; i++) {
1996 if (!load_method(cb, &(c->methods[i]),descpool))
1997 goto return_exception;
2000 /* create the class reference table */
2003 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2005 /* allocate space for the parsed descriptors */
2007 descriptor_pool_alloc_parsed_descriptors(descpool);
2009 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2011 #if defined(ENABLE_STATISTICS)
2013 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2014 count_classref_len += classrefsize;
2015 count_parsed_desc_len += descsize;
2019 /* put the classrefs in the constant pool */
2020 for (i = 0; i < c->cpcount; i++) {
2021 if (c->cptags[i] == CONSTANT_Class) {
2022 utf *name = (utf *) c->cpinfos[i];
2023 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2027 /* set the super class reference */
2030 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2032 goto return_exception;
2035 /* set the super interfaces references */
2037 for (i = 0; i < c->interfacescount; i++) {
2038 c->interfaces[i].ref =
2039 descriptor_pool_lookup_classref(descpool,
2040 (utf *) c->interfaces[i].any);
2041 if (!c->interfaces[i].ref)
2042 goto return_exception;
2045 /* parse field descriptors */
2047 for (i = 0; i < c->fieldscount; i++) {
2048 c->fields[i].parseddesc =
2049 descriptor_pool_parse_field_descriptor(descpool,
2050 c->fields[i].descriptor);
2051 if (!c->fields[i].parseddesc)
2052 goto return_exception;
2055 /* parse method descriptors */
2057 for (i = 0; i < c->methodscount; i++) {
2058 methodinfo *m = &c->methods[i];
2060 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2061 m->flags, class_get_self_classref(m->class));
2063 goto return_exception;
2065 for (j = 0; j < m->exceptiontablelength; j++) {
2066 if (!m->exceptiontable[j].catchtype.any)
2068 if ((m->exceptiontable[j].catchtype.ref =
2069 descriptor_pool_lookup_classref(descpool,
2070 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2071 goto return_exception;
2074 for (j = 0; j < m->thrownexceptionscount; j++) {
2075 if (!m->thrownexceptions[j].any)
2077 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2078 (utf *) m->thrownexceptions[j].any)) == NULL)
2079 goto return_exception;
2083 /* parse the loaded descriptors */
2085 for (i = 0; i < c->cpcount; i++) {
2086 constant_FMIref *fmi;
2089 switch (c->cptags[i]) {
2090 case CONSTANT_Fieldref:
2091 fmi = (constant_FMIref *) c->cpinfos[i];
2092 fmi->parseddesc.fd =
2093 descriptor_pool_parse_field_descriptor(descpool,
2095 if (!fmi->parseddesc.fd)
2096 goto return_exception;
2097 index = (int) (size_t) fmi->classref;
2099 (constant_classref *) class_getconstant(c, index,
2102 goto return_exception;
2104 case CONSTANT_Methodref:
2105 case CONSTANT_InterfaceMethodref:
2106 fmi = (constant_FMIref *) c->cpinfos[i];
2107 index = (int) (size_t) fmi->classref;
2109 (constant_classref *) class_getconstant(c, index,
2112 goto return_exception;
2113 fmi->parseddesc.md =
2114 descriptor_pool_parse_method_descriptor(descpool,
2118 if (!fmi->parseddesc.md)
2119 goto return_exception;
2124 #ifdef ENABLE_VERIFIER
2125 /* Check if all fields and methods can be uniquely
2126 * identified by (name,descriptor). */
2129 /* We use a hash table here to avoid making the
2130 * average case quadratic in # of methods, fields.
2132 static int shift = 0;
2134 u2 *next; /* for chaining colliding hash entries */
2140 /* Allocate hashtable */
2141 len = c->methodscount;
2142 if (len < c->fieldscount) len = c->fieldscount;
2144 hashtab = MNEW(u2,(hashlen + len));
2145 next = hashtab + hashlen;
2147 /* Determine bitshift (to get good hash values) */
2157 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2159 for (i = 0; i < c->fieldscount; ++i) {
2160 fieldinfo *fi = c->fields + i;
2162 /* It's ok if we lose bits here */
2163 index = ((((size_t) fi->name) +
2164 ((size_t) fi->descriptor)) >> shift) % hashlen;
2166 if ((old = hashtab[index])) {
2170 if (c->fields[old].name == fi->name &&
2171 c->fields[old].descriptor == fi->descriptor) {
2172 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2173 goto return_exception;
2175 } while ((old = next[old]));
2177 hashtab[index] = i + 1;
2181 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2183 for (i = 0; i < c->methodscount; ++i) {
2184 methodinfo *mi = c->methods + i;
2186 /* It's ok if we lose bits here */
2187 index = ((((size_t) mi->name) +
2188 ((size_t) mi->descriptor)) >> shift) % hashlen;
2192 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2193 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2197 if ((old = hashtab[index])) {
2201 if (c->methods[old].name == mi->name &&
2202 c->methods[old].descriptor == mi->descriptor) {
2203 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2204 goto return_exception;
2206 } while ((old = next[old]));
2208 hashtab[index] = i + 1;
2211 MFREE(hashtab, u2, (hashlen + len));
2213 #endif /* ENABLE_VERIFIER */
2215 #if defined(ENABLE_STATISTICS)
2217 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2218 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2219 count_class_infos += sizeof(methodinfo) * c->methodscount;
2223 /* load attribute structures */
2225 if (!suck_check_classbuffer_size(cb, 2))
2226 goto return_exception;
2228 if (!load_attributes(cb, suck_u2(cb)))
2229 goto return_exception;
2232 /* Pre java 1.5 version don't check this. This implementation is like
2233 java 1.5 do it: for class file version 45.3 we don't check it, older
2234 versions are checked.
2236 if ((ma == 45 && mi > 3) || ma > 45) {
2237 /* check if all data has been read */
2238 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2240 if (classdata_left > 0) {
2241 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2242 goto return_exception;
2247 /* release dump area */
2249 dump_release(dumpsize);
2251 /* revert loading state and class is loaded */
2253 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2255 #if !defined(NDEBUG)
2257 log_message_class("Loading done class: ", c);
2263 /* release dump area */
2265 dump_release(dumpsize);
2267 /* an exception has been thrown */
2273 /* load_newly_created_array ****************************************************
2275 Load a newly created array class.
2278 c....................the array class C has been loaded
2279 other classinfo......the array class was found in the class cache,
2281 NULL.................an exception has been thrown
2284 This is an internal function. Do not use it unless you know exactly
2287 Use one of the load_class_... functions for general array class loading.
2289 *******************************************************************************/
2291 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2293 classinfo *comp = NULL;
2295 methoddesc *clonedesc;
2296 constant_classref *classrefs;
2301 text = c->name->text;
2302 namelen = c->name->blength;
2304 /* Check array class name */
2306 if (namelen < 2 || text[0] != '[') {
2307 *exceptionptr = new_noclassdeffounderror(c->name);
2311 /* Check the element type */
2315 /* c is an array of arrays. We have to create the component class. */
2317 u = utf_new(text + 1, namelen - 1);
2318 if (!(comp = load_class_from_classloader(u, loader)))
2321 LOADER_ASSERT(comp->state & CLASS_LOADED);
2327 /* the array's flags are that of the component class */
2328 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2329 c->classloader = comp->classloader;
2333 /* c is an array of objects. */
2335 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2336 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2337 *exceptionptr = new_noclassdeffounderror(c->name);
2341 u = utf_new(text + 2, namelen - 3);
2343 if (!(comp = load_class_from_classloader(u, loader)))
2346 LOADER_ASSERT(comp->state & CLASS_LOADED);
2352 /* the array's flags are that of the component class */
2353 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2354 c->classloader = comp->classloader;
2358 /* c is an array of a primitive type */
2360 /* check for cases like `[II' */
2362 *exceptionptr = new_noclassdeffounderror(c->name);
2366 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2367 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2368 c->classloader = NULL;
2371 LOADER_ASSERT(class_java_lang_Object);
2372 LOADER_ASSERT(class_java_lang_Cloneable);
2373 LOADER_ASSERT(class_java_io_Serializable);
2375 /* setup the array class */
2377 c->super.cls = class_java_lang_Object;
2379 c->interfacescount = 2;
2380 c->interfaces = MNEW(classref_or_classinfo, 2);
2385 tc = class_java_lang_Cloneable;
2386 LOADER_ASSERT(tc->state & CLASS_LOADED);
2387 list_addfirst(&unlinkedclasses, tc);
2388 c->interfaces[0].cls = tc;
2390 tc = class_java_io_Serializable;
2391 LOADER_ASSERT(tc->state & CLASS_LOADED);
2392 list_addfirst(&unlinkedclasses, tc);
2393 c->interfaces[1].cls = tc;
2396 c->interfaces[0].cls = class_java_lang_Cloneable;
2397 c->interfaces[1].cls = class_java_io_Serializable;
2400 c->methodscount = 1;
2401 c->methods = MNEW(methodinfo, c->methodscount);
2403 classrefs = MNEW(constant_classref, 2);
2404 CLASSREF_INIT(classrefs[0], c, c->name);
2405 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2407 /* create descriptor for clone method */
2408 /* we need one paramslot which is reserved for the 'this' parameter */
2409 clonedesc = NEW(methoddesc);
2410 clonedesc->returntype.type = TYPE_ADDRESS;
2411 clonedesc->returntype.classref = classrefs + 1;
2412 clonedesc->returntype.arraydim = 0;
2413 /* initialize params to "empty", add real params below in
2414 descriptor_params_from_paramtypes */
2415 clonedesc->paramcount = 0;
2416 clonedesc->paramslots = 0;
2417 clonedesc->paramtypes[0].classref = classrefs + 0;
2419 /* create methodinfo */
2422 MSET(clone, 0, methodinfo, 1);
2424 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2425 initObjectLock(&clone->header);
2428 /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter
2430 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2431 clone->name = utf_clone;
2432 clone->descriptor = utf_void__java_lang_Object;
2433 clone->parseddesc = clonedesc;
2435 clone->monoPoly = MONO;
2437 /* parse the descriptor to get the register allocation */
2439 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2443 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2445 /* XXX: field: length? */
2447 /* array classes are not loaded from class files */
2449 c->state |= CLASS_LOADED;
2450 c->parseddescs = (u1 *) clonedesc;
2451 c->parseddescsize = sizeof(methodinfo);
2452 c->classrefs = classrefs;
2453 c->classrefcount = 1;
2455 /* insert class into the loaded class cache */
2456 /* XXX free classinfo if NULL returned? */
2458 return classcache_store(loader, c, true);
2462 /* loader_close ****************************************************************
2464 Frees all resources.
2466 *******************************************************************************/
2468 void loader_close(void)
2475 * These are local overrides for various environment variables in Emacs.
2476 * Please do not remove this and leave it at the end of the file, where
2477 * Emacs will automagically detect them.
2478 * ---------------------------------------------------------------------
2481 * indent-tabs-mode: t