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 4829 2006-04-24 17:16:45Z edwin $
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"
80 #include "vm/rt-timing.h"
83 /******************************************************************************/
85 /******************************************************************************/
92 #define LOADER_ASSERT(cond) assert(cond)
94 #define LOADER_ASSERT(cond)
98 /* loader_init *****************************************************************
100 Initializes all lists and loads all classes required for the system
103 *******************************************************************************/
105 bool loader_init(u1 *stackbottom)
107 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
108 list_classpath_entry *lce;
110 /* Initialize the monitor pointer for zip/jar file locking. */
112 for (lce = list_first(list_classpath_entries); lce != NULL;
113 lce = list_next(list_classpath_entries, lce))
114 if (lce->type == CLASSPATH_ARCHIVE)
115 initObjectLock((java_objectheader *) lce);
118 /* load some important classes */
120 if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
123 if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
126 if (!(class_java_lang_Cloneable =
127 load_class_bootstrap(utf_java_lang_Cloneable)))
130 if (!(class_java_io_Serializable =
131 load_class_bootstrap(utf_java_io_Serializable)))
135 /* load classes for wrapping primitive types */
137 if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
140 if (!(class_java_lang_Boolean =
141 load_class_bootstrap(utf_java_lang_Boolean)))
144 if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
147 if (!(class_java_lang_Character =
148 load_class_bootstrap(utf_java_lang_Character)))
151 if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
154 if (!(class_java_lang_Integer =
155 load_class_bootstrap(utf_java_lang_Integer)))
158 if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
161 if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
164 if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
168 /* load some other important classes */
170 if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
173 if (!(class_java_lang_ClassLoader =
174 load_class_bootstrap(utf_java_lang_ClassLoader)))
177 if (!(class_java_lang_SecurityManager =
178 load_class_bootstrap(utf_java_lang_SecurityManager)))
181 if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
184 if (!(class_java_lang_Thread =
185 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
188 if (!(class_java_lang_ThreadGroup =
189 load_class_bootstrap(utf_java_lang_ThreadGroup)))
192 if (!(class_java_lang_VMThread =
193 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
197 /* some classes which may be used more often */
199 if (!(class_java_lang_StackTraceElement =
200 load_class_bootstrap(utf_java_lang_StackTraceElement)))
203 if (!(class_java_lang_reflect_Constructor =
204 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
207 if (!(class_java_lang_reflect_Field =
208 load_class_bootstrap(utf_java_lang_reflect_Field)))
211 if (!(class_java_lang_reflect_Method =
212 load_class_bootstrap(utf_java_lang_reflect_Method)))
215 if (!(class_java_security_PrivilegedAction =
216 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
219 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
222 if (!(arrayclass_java_lang_Object =
223 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
226 #if defined(USE_THREADS)
227 if (stackbottom != 0)
235 /* loader_load_all_classes *****************************************************
237 Loads all classes specified in the BOOTCLASSPATH.
239 *******************************************************************************/
241 void loader_load_all_classes(void)
243 list_classpath_entry *lce;
244 #if defined(ENABLE_ZLIB)
247 hashtable_zipfile_entry *htzfe;
251 for (lce = list_first(list_classpath_entries); lce != NULL;
252 lce = list_next(list_classpath_entries, lce)) {
253 #if defined(ENABLE_ZLIB)
254 if (lce->type == CLASSPATH_ARCHIVE) {
255 /* get the classes hashtable */
259 for (slot = 0; slot < ht->size; slot++) {
260 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
262 for (; htzfe; htzfe = htzfe->hashlink) {
265 /* skip all entries in META-INF and .properties,
268 if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
269 strstr(u->text, ".properties") ||
270 strstr(u->text, ".png"))
273 /* load class from bootstrap classloader */
275 if (!load_class_bootstrap(u)) {
276 fprintf(stderr, "Error loading: ");
277 utf_fprint_classname(stderr, u);
278 fprintf(stderr, "\n");
281 /* print out exception and cause */
283 exceptions_print_exception(*exceptionptr);
291 #if defined(ENABLE_ZLIB)
298 /* skipattributebody ***********************************************************
300 Skips an attribute after the 16 bit reference to attribute_name has
303 *******************************************************************************/
305 static bool skipattributebody(classbuffer *cb)
309 if (!suck_check_classbuffer_size(cb, 4))
314 if (!suck_check_classbuffer_size(cb, len))
317 suck_skip_nbytes(cb, len);
323 /************************* Function: skipattributes ****************************
325 skips num attribute structures
327 *******************************************************************************/
329 static bool skipattributes(classbuffer *cb, u4 num)
334 for (i = 0; i < num; i++) {
335 if (!suck_check_classbuffer_size(cb, 2 + 4))
341 if (!suck_check_classbuffer_size(cb, len))
344 suck_skip_nbytes(cb, len);
351 /* load_constantpool ***********************************************************
353 Loads the constantpool of a class, the entries are transformed into
354 a simpler format by resolving references (a detailed overview of
355 the compact structures can be found in global.h).
357 *******************************************************************************/
359 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
362 /* The following structures are used to save information which cannot be
363 processed during the first pass. After the complete constantpool has
364 been traversed the references can be resolved.
365 (only in specific order) */
367 /* CONSTANT_Class entries */
368 typedef struct forward_class {
369 struct forward_class *next;
374 /* CONSTANT_String */
375 typedef struct forward_string {
376 struct forward_string *next;
381 /* CONSTANT_NameAndType */
382 typedef struct forward_nameandtype {
383 struct forward_nameandtype *next;
387 } forward_nameandtype;
389 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
390 typedef struct forward_fieldmethint {
391 struct forward_fieldmethint *next;
395 u2 nameandtype_index;
396 } forward_fieldmethint;
402 forward_class *forward_classes = NULL;
403 forward_string *forward_strings = NULL;
404 forward_nameandtype *forward_nameandtypes = NULL;
405 forward_fieldmethint *forward_fieldmethints = NULL;
409 forward_nameandtype *nfn;
410 forward_fieldmethint *nff;
418 /* number of entries in the constant_pool table plus one */
419 if (!suck_check_classbuffer_size(cb, 2))
422 cpcount = c->cpcount = suck_u2(cb);
424 /* allocate memory */
425 cptags = c->cptags = MNEW(u1, cpcount);
426 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
429 exceptions_throw_classformaterror(c, "Illegal constant pool size");
433 #if defined(ENABLE_STATISTICS)
435 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
438 /* initialize constantpool */
439 for (idx = 0; idx < cpcount; idx++) {
440 cptags[idx] = CONSTANT_UNUSED;
445 /******* first pass *******/
446 /* entries which cannot be resolved now are written into
447 temporary structures and traversed again later */
450 while (idx < cpcount) {
453 /* get constant type */
454 if (!suck_check_classbuffer_size(cb, 1))
461 nfc = DNEW(forward_class);
463 nfc->next = forward_classes;
464 forward_classes = nfc;
466 nfc->thisindex = idx;
467 /* reference to CONSTANT_NameAndType */
468 if (!suck_check_classbuffer_size(cb, 2))
471 nfc->name_index = suck_u2(cb);
476 case CONSTANT_String:
477 nfs = DNEW(forward_string);
479 nfs->next = forward_strings;
480 forward_strings = nfs;
482 nfs->thisindex = idx;
484 /* reference to CONSTANT_Utf8_info with string characters */
485 if (!suck_check_classbuffer_size(cb, 2))
488 nfs->string_index = suck_u2(cb);
493 case CONSTANT_NameAndType:
494 nfn = DNEW(forward_nameandtype);
496 nfn->next = forward_nameandtypes;
497 forward_nameandtypes = nfn;
499 nfn->thisindex = idx;
501 if (!suck_check_classbuffer_size(cb, 2 + 2))
504 /* reference to CONSTANT_Utf8_info containing simple name */
505 nfn->name_index = suck_u2(cb);
507 /* reference to CONSTANT_Utf8_info containing field or method
509 nfn->sig_index = suck_u2(cb);
514 case CONSTANT_Fieldref:
515 case CONSTANT_Methodref:
516 case CONSTANT_InterfaceMethodref:
517 nff = DNEW(forward_fieldmethint);
519 nff->next = forward_fieldmethints;
520 forward_fieldmethints = nff;
522 nff->thisindex = idx;
526 if (!suck_check_classbuffer_size(cb, 2 + 2))
529 /* class or interface type that contains the declaration of the
531 nff->class_index = suck_u2(cb);
533 /* name and descriptor of the field or method */
534 nff->nameandtype_index = suck_u2(cb);
539 case CONSTANT_Integer: {
540 constant_integer *ci = NEW(constant_integer);
542 #if defined(ENABLE_STATISTICS)
544 count_const_pool_len += sizeof(constant_integer);
547 if (!suck_check_classbuffer_size(cb, 4))
550 ci->value = suck_s4(cb);
551 cptags[idx] = CONSTANT_Integer;
558 case CONSTANT_Float: {
559 constant_float *cf = NEW(constant_float);
561 #if defined(ENABLE_STATISTICS)
563 count_const_pool_len += sizeof(constant_float);
566 if (!suck_check_classbuffer_size(cb, 4))
569 cf->value = suck_float(cb);
570 cptags[idx] = CONSTANT_Float;
577 case CONSTANT_Long: {
578 constant_long *cl = NEW(constant_long);
580 #if defined(ENABLE_STATISTICS)
582 count_const_pool_len += sizeof(constant_long);
585 if (!suck_check_classbuffer_size(cb, 8))
588 cl->value = suck_s8(cb);
589 cptags[idx] = CONSTANT_Long;
593 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
599 case CONSTANT_Double: {
600 constant_double *cd = NEW(constant_double);
602 #if defined(ENABLE_STATISTICS)
604 count_const_pool_len += sizeof(constant_double);
607 if (!suck_check_classbuffer_size(cb, 8))
610 cd->value = suck_double(cb);
611 cptags[idx] = CONSTANT_Double;
615 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
621 case CONSTANT_Utf8: {
624 /* number of bytes in the bytes array (not string-length) */
625 if (!suck_check_classbuffer_size(cb, 2))
628 length = suck_u2(cb);
629 cptags[idx] = CONSTANT_Utf8;
631 /* validate the string */
632 if (!suck_check_classbuffer_size(cb, length))
635 #ifdef ENABLE_VERIFIER
637 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
639 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
642 #endif /* ENABLE_VERIFIER */
643 /* insert utf-string into the utf-symboltable */
644 cpinfos[idx] = utf_new((char *) cb->pos, length);
646 /* skip bytes of the string (buffer size check above) */
647 suck_skip_nbytes(cb, length);
653 exceptions_throw_classformaterror(c, "Illegal constant pool type");
659 /* resolve entries in temporary structures */
661 while (forward_classes) {
663 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
667 #ifdef ENABLE_VERIFIER
668 if (opt_verify && !is_valid_name_utf(name)) {
669 exceptions_throw_classformaterror(c, "Class reference with invalid name");
672 #endif /* ENABLE_VERIFIER */
674 /* add all class references to the descriptor_pool */
676 if (!descriptor_pool_add_class(descpool, name))
679 cptags[forward_classes->thisindex] = CONSTANT_Class;
684 if (!(tc = load_class_bootstrap(name)))
687 /* link the class later, because we cannot link the class currently
689 list_addfirst(&unlinkedclasses, tc);
692 /* the classref is created later */
693 cpinfos[forward_classes->thisindex] = name;
695 nfc = forward_classes;
696 forward_classes = forward_classes->next;
699 while (forward_strings) {
701 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
705 /* resolve utf-string */
706 cptags[forward_strings->thisindex] = CONSTANT_String;
707 cpinfos[forward_strings->thisindex] = text;
709 nfs = forward_strings;
710 forward_strings = forward_strings->next;
713 while (forward_nameandtypes) {
714 constant_nameandtype *cn = NEW(constant_nameandtype);
716 #if defined(ENABLE_STATISTICS)
718 count_const_pool_len += sizeof(constant_nameandtype);
721 /* resolve simple name and descriptor */
722 cn->name = class_getconstant(c,
723 forward_nameandtypes->name_index,
728 cn->descriptor = class_getconstant(c,
729 forward_nameandtypes->sig_index,
734 #ifdef ENABLE_VERIFIER
737 if (!is_valid_name_utf(cn->name)) {
738 exceptions_throw_classformaterror(c,
739 "Illegal Field name \"%s\"",
745 /* disallow referencing <clinit> among others */
746 if (cn->name->text[0] == '<' && cn->name != utf_init) {
747 exceptions_throw_classformaterror(c, "Illegal reference to special method");
751 #endif /* ENABLE_VERIFIER */
753 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
754 cpinfos[forward_nameandtypes->thisindex] = cn;
756 nfn = forward_nameandtypes;
757 forward_nameandtypes = forward_nameandtypes->next;
760 while (forward_fieldmethints) {
761 constant_nameandtype *nat;
762 constant_FMIref *fmi = NEW(constant_FMIref);
764 #if defined(ENABLE_STATISTICS)
766 count_const_pool_len += sizeof(constant_FMIref);
768 /* resolve simple name and descriptor */
770 nat = class_getconstant(c,
771 forward_fieldmethints->nameandtype_index,
772 CONSTANT_NameAndType);
776 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
778 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
781 /* the classref is created later */
783 fmi->p.index = forward_fieldmethints->class_index;
784 fmi->name = nat->name;
785 fmi->descriptor = nat->descriptor;
787 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
788 cpinfos[forward_fieldmethints->thisindex] = fmi;
790 nff = forward_fieldmethints;
791 forward_fieldmethints = forward_fieldmethints->next;
794 /* everything was ok */
800 /* load_field ******************************************************************
802 Load everything about a class field from the class file and fill a
803 'fieldinfo' structure. For static fields, space in the data segment
806 *******************************************************************************/
808 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
810 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
815 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
820 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
823 f->flags = suck_u2(cb);
825 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
830 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
834 f->parseddesc = NULL;
836 if (!descriptor_pool_add(descpool, u, NULL))
839 /* descriptor_pool_add accepts method descriptors, so we have to check */
840 /* against them here before the call of descriptor_to_basic_type below. */
841 if (u->text[0] == '(') {
842 exceptions_throw_classformaterror(c, "Method descriptor used for field");
846 #ifdef ENABLE_VERIFIER
849 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
850 exceptions_throw_classformaterror(c,
851 "Illegal Field name \"%s\"",
856 /* check flag consistency */
857 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
859 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
860 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
861 exceptions_throw_classformaterror(c,
862 "Illegal field modifiers: 0x%X",
867 if (c->flags & ACC_INTERFACE) {
868 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
869 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
870 f->flags & ACC_TRANSIENT) {
871 exceptions_throw_classformaterror(c,
872 "Illegal field modifiers: 0x%X",
878 #endif /* ENABLE_VERIFIER */
880 f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
881 f->offset = 0; /* offset from start of object */
885 case TYPE_INT: f->value.i = 0; break;
886 case TYPE_FLOAT: f->value.f = 0.0; break;
887 case TYPE_DOUBLE: f->value.d = 0.0; break;
888 case TYPE_ADDRESS: f->value.a = NULL;
889 if (!(f->flags & ACC_STATIC))
890 c->flags |= ACC_CLASS_HAS_POINTERS;
894 f->value.l = 0; break;
896 f->value.l.low = 0; f->value.l.high = 0; break;
900 /* read attributes */
901 if (!suck_check_classbuffer_size(cb, 2))
904 attrnum = suck_u2(cb);
905 for (i = 0; i < attrnum; i++) {
906 if (!suck_check_classbuffer_size(cb, 2))
909 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
912 if (u == utf_ConstantValue) {
913 if (!suck_check_classbuffer_size(cb, 4 + 2))
916 /* check attribute length */
917 if (suck_u4(cb) != 2) {
918 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
922 /* constant value attribute */
923 if (pindex != field_load_NOVALUE) {
924 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
928 /* index of value in constantpool */
929 pindex = suck_u2(cb);
931 /* initialize field with value from constantpool */
934 constant_integer *ci;
936 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
939 f->value.i = ci->value;
946 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
949 f->value.l = cl->value;
956 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
959 f->value.f = cf->value;
966 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
969 f->value.d = cd->value;
974 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
977 /* create javastring from compressed utf8-string */
978 f->value.a = literalstring_new(u);
982 log_text("Invalid Constant - Type");
986 /* unknown attribute */
987 if (!skipattributebody(cb))
992 /* everything was ok */
998 /* load_method *****************************************************************
1000 Loads a method from the class file and fills an existing
1001 'methodinfo' structure. For native methods, the function pointer
1002 field is set to the real function pointer, for JavaVM methods a
1003 pointer to the compiler is used preliminarily.
1005 *******************************************************************************/
1007 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1018 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1019 initObjectLock(&m->header);
1022 #if defined(ENABLE_STATISTICS)
1024 count_all_methods++;
1027 m->thrownexceptionscount = 0;
1028 m->linenumbercount = 0;
1032 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1035 m->flags = suck_u2(cb);
1037 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1042 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1046 m->parseddesc = NULL;
1048 if (!descriptor_pool_add(descpool, u, &argcount))
1051 #ifdef ENABLE_VERIFIER
1053 if (!is_valid_name_utf(m->name)) {
1054 exceptions_throw_classformaterror(c, "Method with invalid name");
1058 if (m->name->text[0] == '<' &&
1059 m->name != utf_init && m->name != utf_clinit) {
1060 exceptions_throw_classformaterror(c, "Method with invalid special name");
1064 #endif /* ENABLE_VERIFIER */
1066 if (!(m->flags & ACC_STATIC))
1067 argcount++; /* count the 'this' argument */
1069 #ifdef ENABLE_VERIFIER
1071 if (argcount > 255) {
1072 exceptions_throw_classformaterror(c, "Too many arguments in signature");
1076 /* check flag consistency */
1077 if (m->name != utf_clinit) {
1078 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1080 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1081 exceptions_throw_classformaterror(c,
1082 "Illegal method modifiers: 0x%X",
1087 if (m->flags & ACC_ABSTRACT) {
1088 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1089 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1090 exceptions_throw_classformaterror(c,
1091 "Illegal method modifiers: 0x%X",
1097 if (c->flags & ACC_INTERFACE) {
1098 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1099 exceptions_throw_classformaterror(c,
1100 "Illegal method modifiers: 0x%X",
1106 if (m->name == utf_init) {
1107 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1108 ACC_NATIVE | ACC_ABSTRACT)) {
1109 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1115 #endif /* ENABLE_VERIFIER */
1118 m->basicblockcount = 0;
1119 m->basicblocks = NULL;
1120 m->basicblockindex = NULL;
1121 m->instructioncount = 0;
1122 m->instructions = NULL;
1125 m->exceptiontable = NULL;
1126 m->stubroutine = NULL;
1129 if (!suck_check_classbuffer_size(cb, 2))
1132 attrnum = suck_u2(cb);
1133 for (i = 0; i < attrnum; i++) {
1136 if (!suck_check_classbuffer_size(cb, 2))
1139 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1142 if (aname == utf_Code) {
1143 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1144 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1149 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1153 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1157 m->maxstack = suck_u2(cb);
1158 m->maxlocals = suck_u2(cb);
1160 if (m->maxlocals < argcount) {
1161 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1165 if (!suck_check_classbuffer_size(cb, 4))
1168 m->jcodelength = suck_u4(cb);
1170 if (m->jcodelength == 0) {
1171 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1175 if (m->jcodelength > 65535) {
1176 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1180 if (!suck_check_classbuffer_size(cb, m->jcodelength))
1183 m->jcode = MNEW(u1, m->jcodelength);
1184 suck_nbytes(m->jcode, cb, m->jcodelength);
1186 if (!suck_check_classbuffer_size(cb, 2))
1189 m->exceptiontablelength = suck_u2(cb);
1190 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1193 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1195 #if defined(ENABLE_STATISTICS)
1197 count_vmcode_len += m->jcodelength + 18;
1198 count_extable_len +=
1199 m->exceptiontablelength * sizeof(exceptiontable);
1203 for (j = 0; j < m->exceptiontablelength; j++) {
1205 m->exceptiontable[j].startpc = suck_u2(cb);
1206 m->exceptiontable[j].endpc = suck_u2(cb);
1207 m->exceptiontable[j].handlerpc = suck_u2(cb);
1211 m->exceptiontable[j].catchtype.any = NULL;
1214 /* the classref is created later */
1215 if (!(m->exceptiontable[j].catchtype.any =
1216 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1221 if (!suck_check_classbuffer_size(cb, 2))
1224 codeattrnum = suck_u2(cb);
1226 for (; codeattrnum > 0; codeattrnum--) {
1229 if (!suck_check_classbuffer_size(cb, 2))
1232 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1235 if (caname == utf_LineNumberTable) {
1238 if (!suck_check_classbuffer_size(cb, 4 + 2))
1242 m->linenumbercount = suck_u2(cb);
1244 if (!suck_check_classbuffer_size(cb,
1245 (2 + 2) * m->linenumbercount))
1248 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1250 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1251 m->linenumbers[lncid].start_pc = suck_u2(cb);
1252 m->linenumbers[lncid].line_number = suck_u2(cb);
1256 if (!skipattributes(cb, codeattrnum))
1262 if (!skipattributebody(cb))
1267 } else if (aname == utf_Exceptions) {
1270 if (m->thrownexceptions) {
1271 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1275 if (!suck_check_classbuffer_size(cb, 4 + 2))
1278 suck_u4(cb); /* length */
1279 m->thrownexceptionscount = suck_u2(cb);
1281 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1284 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1286 for (j = 0; j < m->thrownexceptionscount; j++) {
1287 /* the classref is created later */
1288 if (!((m->thrownexceptions)[j].any =
1289 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1294 if (!skipattributebody(cb))
1299 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1300 exceptions_throw_classformaterror(c, "Missing Code attribute");
1304 /* everything was ok */
1310 /* load_attribute **************************************************************
1312 Read attributes from classfile.
1314 *******************************************************************************/
1316 static bool load_attributes(classbuffer *cb, u4 num)
1324 for (i = 0; i < num; i++) {
1325 /* retrieve attribute name */
1326 if (!suck_check_classbuffer_size(cb, 2))
1329 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1332 if (aname == utf_InnerClasses) {
1333 /* innerclasses attribute */
1334 if (c->innerclass) {
1335 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1339 if (!suck_check_classbuffer_size(cb, 4 + 2))
1342 /* skip attribute length */
1345 /* number of records */
1346 c->innerclasscount = suck_u2(cb);
1348 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1351 /* allocate memory for innerclass structure */
1352 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1354 for (j = 0; j < c->innerclasscount; j++) {
1355 /* The innerclass structure contains a class with an encoded
1356 name, its defining scope, its simple name and a bitmask of
1357 the access flags. If an inner class is not a member, its
1358 outer_class is NULL, if a class is anonymous, its name is
1361 innerclassinfo *info = c->innerclass + j;
1363 info->inner_class.ref =
1364 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1365 info->outer_class.ref =
1366 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1368 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1369 info->flags = suck_u2(cb);
1372 } else if (aname == utf_SourceFile) {
1373 if (!suck_check_classbuffer_size(cb, 4 + 2))
1376 if (suck_u4(cb) != 2) {
1377 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1381 if (c->sourcefile) {
1382 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1386 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1390 /* unknown attribute */
1391 if (!skipattributebody(cb))
1400 /* load_class_from_sysloader ***************************************************
1402 Load the class with the given name using the system class loader
1405 name.............the classname
1408 the loaded class, or
1409 NULL if an exception has been thrown
1411 *******************************************************************************/
1413 classinfo *load_class_from_sysloader(utf *name)
1416 java_objectheader *cl;
1419 LOADER_ASSERT(class_java_lang_Object);
1420 LOADER_ASSERT(class_java_lang_ClassLoader);
1421 LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1423 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1424 utf_getSystemClassLoader,
1425 utf_void__java_lang_ClassLoader,
1426 class_java_lang_Object,
1432 cl = vm_call_method(m, NULL);
1437 c = load_class_from_classloader(name, cl);
1443 /* load_class_from_classloader *************************************************
1445 Load the class with the given name using the given user-defined class loader.
1448 name.............the classname
1449 cl...............user-defined class loader
1452 the loaded class, or
1453 NULL if an exception has been thrown
1455 *******************************************************************************/
1457 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1459 java_objectheader *o;
1462 java_lang_String *s;
1463 #if defined(ENABLE_RT_TIMING)
1464 struct timespec time_start, time_lookup, time_prepare, time_java,
1468 RT_TIMING_GET_TIME(time_start);
1470 LOADER_ASSERT(name);
1472 /* lookup if this class has already been loaded */
1474 c = classcache_lookup(cl, name);
1476 RT_TIMING_GET_TIME(time_lookup);
1477 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
1482 /* if other class loader than bootstrap, call it */
1490 namelen = name->blength;
1492 /* handle array classes */
1493 if (text[0] == '[') {
1499 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1500 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1501 *exceptionptr = new_noclassdeffounderror(name);
1505 u = utf_new(text + 2, namelen - 3);
1507 if (!(comp = load_class_from_classloader(u, cl)))
1510 /* create the array class */
1512 c = class_array_of(comp, false);
1514 tmpc = classcache_store(cl, c, true);
1517 /* exception, free the loaded class */
1518 c->state &= ~CLASS_LOADING;
1525 /* load the component class */
1527 u = utf_new(text + 1, namelen - 1);
1529 if (!(comp = load_class_from_classloader(u, cl)))
1532 /* create the array class */
1534 c = class_array_of(comp, false);
1536 tmpc = classcache_store(cl, c, true);
1539 /* exception, free the loaded class */
1540 c->state &= ~CLASS_LOADING;
1547 /* primitive array classes are loaded by the bootstrap loader */
1549 c = load_class_bootstrap(name);
1555 LOADER_ASSERT(class_java_lang_Object);
1557 lc = class_resolveclassmethod(cl->vftbl->class,
1559 utf_java_lang_String__java_lang_Class,
1560 class_java_lang_Object,
1564 return false; /* exception */
1566 /* move return value into `o' and cast it afterwards to a classinfo* */
1568 s = javastring_new_slash_to_dot(name);
1570 RT_TIMING_GET_TIME(time_prepare);
1572 o = vm_call_method(lc, cl, s);
1574 RT_TIMING_GET_TIME(time_java);
1576 c = (classinfo *) o;
1579 /* Store this class in the loaded class cache. If another
1580 class with the same (initloader,name) pair has been
1581 stored earlier it will be returned by classcache_store
1582 In this case classcache_store may not free the class
1583 because it has already been exposed to Java code which
1584 may have kept references to that class. */
1586 tmpc = classcache_store(cl, c, false);
1589 /* exception, free the loaded class */
1590 c->state &= ~CLASS_LOADING;
1597 /* loadClass has thrown an exception. We must convert
1598 ClassNotFoundException into
1599 NoClassDefFoundException. */
1601 /* XXX Maybe we should have a flag that avoids this
1602 conversion for calling load_class_from_classloader from
1603 Class.forName. Currently we do a double conversion in
1606 classnotfoundexception_to_noclassdeffounderror();
1609 RT_TIMING_GET_TIME(time_cache);
1611 RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
1612 RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
1613 RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
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)
1654 #if defined(ENABLE_RT_TIMING)
1655 struct timespec time_start, time_lookup, time_array, time_suck,
1656 time_load, time_cache;
1659 RT_TIMING_GET_TIME(time_start);
1663 LOADER_ASSERT(name);
1665 /* lookup if this class has already been loaded */
1667 if ((r = classcache_lookup(NULL, name))) {
1669 RT_TIMING_GET_TIME(time_lookup);
1670 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1675 RT_TIMING_GET_TIME(time_lookup);
1676 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1678 /* create the classinfo */
1680 c = class_create_classinfo(name);
1682 /* handle array classes */
1684 if (name->text[0] == '[') {
1685 c = load_newly_created_array(c, NULL);
1688 LOADER_ASSERT(c->state & CLASS_LOADED);
1690 RT_TIMING_GET_TIME(time_array);
1691 RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
1696 #if defined(ENABLE_STATISTICS)
1699 if (getcompilingtime)
1700 compilingtime_stop();
1703 loadingtime_start();
1706 /* load classdata, throw exception on error */
1708 if ((cb = suck_start(c)) == NULL) {
1709 /* this normally means, the classpath was not set properly */
1711 if (name == utf_java_lang_Object)
1712 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1713 "java/lang/Object");
1715 *exceptionptr = new_noclassdeffounderror(name);
1720 RT_TIMING_GET_TIME(time_suck);
1722 /* load the class from the buffer */
1724 r = load_class_from_classbuffer(cb);
1726 RT_TIMING_GET_TIME(time_load);
1729 /* the class could not be loaded, free the classinfo struct */
1734 /* Store this class in the loaded class cache this step also
1735 checks the loading constraints. If the class has been loaded
1736 before, the earlier loaded class is returned. */
1738 classinfo *res = classcache_store(NULL, c, true);
1748 RT_TIMING_GET_TIME(time_cache);
1750 /* SUN compatible -verbose:class output */
1752 if (opt_verboseclass && r) {
1754 utf_display_classname(name);
1755 printf(" from %s]\n", cb->path);
1762 #if defined(ENABLE_STATISTICS)
1768 if (getcompilingtime)
1769 compilingtime_start();
1772 RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
1773 RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
1774 RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
1775 RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
1781 /* load_class_from_classbuffer *************************************************
1783 Loads everything interesting about a class from the class file. The
1784 'classinfo' structure must have been allocated previously.
1786 The super class and the interfaces implemented by this class need
1787 not be loaded. The link is set later by the function 'class_link'.
1789 The loaded class is removed from the list 'unloadedclasses' and
1790 added to the list 'unlinkedclasses'.
1793 This function is NOT synchronized!
1795 *******************************************************************************/
1797 classinfo *load_class_from_classbuffer(classbuffer *cb)
1805 descriptor_pool *descpool;
1806 #if defined(ENABLE_STATISTICS)
1810 #if defined(ENABLE_RT_TIMING)
1811 struct timespec time_start, time_checks, time_ndpool, time_cpool,
1812 time_setup, time_fields, time_methods, time_classrefs,
1813 time_descs, time_setrefs, time_parsefds, time_parsemds,
1814 time_parsecpool, time_verify, time_attrs;
1817 RT_TIMING_GET_TIME(time_start);
1819 /* get the classbuffer's class */
1823 /* the class is already loaded */
1825 if (c->state & CLASS_LOADED)
1828 #if defined(ENABLE_STATISTICS)
1830 count_class_loads++;
1833 #if !defined(NDEBUG)
1834 /* output for debugging purposes */
1837 log_message_class("Loading class: ", c);
1840 /* mark start of dump memory area */
1842 dumpsize = dump_size();
1844 /* class is currently loading */
1846 c->state |= CLASS_LOADING;
1848 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1849 goto return_exception;
1851 /* check signature */
1853 if (suck_u4(cb) != MAGIC) {
1854 exceptions_throw_classformaterror(c, "Bad magic number");
1856 goto return_exception;
1864 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1866 new_unsupportedclassversionerror(c,
1867 "Unsupported major.minor version %d.%d",
1870 goto return_exception;
1872 RT_TIMING_GET_TIME(time_checks);
1874 /* create a new descriptor pool */
1876 descpool = descriptor_pool_new(c);
1878 RT_TIMING_GET_TIME(time_ndpool);
1880 /* load the constant pool */
1882 if (!load_constantpool(cb, descpool))
1883 goto return_exception;
1885 RT_TIMING_GET_TIME(time_cpool);
1889 if (!suck_check_classbuffer_size(cb, 2))
1890 goto return_exception;
1892 c->flags = suck_u2(cb);
1894 /* check ACC flags consistency */
1896 if (c->flags & ACC_INTERFACE) {
1897 if (!(c->flags & ACC_ABSTRACT)) {
1898 /* We work around this because interfaces in JDK 1.1 are
1899 * not declared abstract. */
1901 c->flags |= ACC_ABSTRACT;
1904 if (c->flags & ACC_FINAL) {
1905 exceptions_throw_classformaterror(c,
1906 "Illegal class modifiers: 0x%X",
1908 goto return_exception;
1911 if (c->flags & ACC_SUPER) {
1912 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1916 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1917 exceptions_throw_classformaterror(c,
1918 "Illegal class modifiers: 0x%X",
1920 goto return_exception;
1923 if (!suck_check_classbuffer_size(cb, 2 + 2))
1924 goto return_exception;
1929 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1930 goto return_exception;
1932 if (c->name == utf_not_named_yet) {
1933 /* we finally have a name for this class */
1935 class_set_packagename(c);
1937 } else if (name != c->name) {
1941 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1942 utf_strlen(name) + strlen(")") + strlen("0");
1944 msg = MNEW(char, msglen);
1946 utf_sprint(msg, c->name);
1947 strcat(msg, " (wrong name: ");
1948 utf_strcat(msg, name);
1952 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1954 MFREE(msg, char, msglen);
1956 goto return_exception;
1959 /* retrieve superclass */
1961 c->super.any = NULL;
1962 if ((i = suck_u2(cb))) {
1963 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1964 goto return_exception;
1966 /* java.lang.Object may not have a super class. */
1968 if (c->name == utf_java_lang_Object) {
1970 new_exception_message(string_java_lang_ClassFormatError,
1971 "java.lang.Object with superclass");
1973 goto return_exception;
1976 /* Interfaces must have java.lang.Object as super class. */
1978 if ((c->flags & ACC_INTERFACE) &&
1979 supername != utf_java_lang_Object) {
1981 new_exception_message(string_java_lang_ClassFormatError,
1982 "Interfaces must have java.lang.Object as superclass");
1984 goto return_exception;
1990 /* This is only allowed for java.lang.Object. */
1992 if (c->name != utf_java_lang_Object) {
1993 exceptions_throw_classformaterror(c, "Bad superclass index");
1994 goto return_exception;
1998 /* retrieve interfaces */
2000 if (!suck_check_classbuffer_size(cb, 2))
2001 goto return_exception;
2003 c->interfacescount = suck_u2(cb);
2005 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
2006 goto return_exception;
2008 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2009 for (i = 0; i < c->interfacescount; i++) {
2010 /* the classrefs are created later */
2011 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2012 goto return_exception;
2015 RT_TIMING_GET_TIME(time_setup);
2018 if (!suck_check_classbuffer_size(cb, 2))
2019 goto return_exception;
2021 c->fieldscount = suck_u2(cb);
2022 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2023 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2024 for (i = 0; i < c->fieldscount; i++) {
2025 if (!load_field(cb, &(c->fields[i]),descpool))
2026 goto return_exception;
2029 RT_TIMING_GET_TIME(time_fields);
2032 if (!suck_check_classbuffer_size(cb, 2))
2033 goto return_exception;
2035 c->methodscount = suck_u2(cb);
2036 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2037 c->methods = MNEW(methodinfo, c->methodscount);
2038 for (i = 0; i < c->methodscount; i++) {
2039 if (!load_method(cb, &(c->methods[i]),descpool))
2040 goto return_exception;
2043 RT_TIMING_GET_TIME(time_methods);
2045 /* create the class reference table */
2048 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2050 RT_TIMING_GET_TIME(time_classrefs);
2052 /* allocate space for the parsed descriptors */
2054 descriptor_pool_alloc_parsed_descriptors(descpool);
2056 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2058 #if defined(ENABLE_STATISTICS)
2060 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2061 count_classref_len += classrefsize;
2062 count_parsed_desc_len += descsize;
2066 RT_TIMING_GET_TIME(time_descs);
2068 /* put the classrefs in the constant pool */
2069 for (i = 0; i < c->cpcount; i++) {
2070 if (c->cptags[i] == CONSTANT_Class) {
2071 utf *name = (utf *) c->cpinfos[i];
2072 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2076 /* set the super class reference */
2079 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2081 goto return_exception;
2084 /* set the super interfaces references */
2086 for (i = 0; i < c->interfacescount; i++) {
2087 c->interfaces[i].ref =
2088 descriptor_pool_lookup_classref(descpool,
2089 (utf *) c->interfaces[i].any);
2090 if (!c->interfaces[i].ref)
2091 goto return_exception;
2094 RT_TIMING_GET_TIME(time_setrefs);
2096 /* parse field descriptors */
2098 for (i = 0; i < c->fieldscount; i++) {
2099 c->fields[i].parseddesc =
2100 descriptor_pool_parse_field_descriptor(descpool,
2101 c->fields[i].descriptor);
2102 if (!c->fields[i].parseddesc)
2103 goto return_exception;
2106 RT_TIMING_GET_TIME(time_parsefds);
2108 /* parse method descriptors */
2110 for (i = 0; i < c->methodscount; i++) {
2111 methodinfo *m = &c->methods[i];
2113 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2114 m->flags, class_get_self_classref(m->class));
2116 goto return_exception;
2118 for (j = 0; j < m->exceptiontablelength; j++) {
2119 if (!m->exceptiontable[j].catchtype.any)
2121 if ((m->exceptiontable[j].catchtype.ref =
2122 descriptor_pool_lookup_classref(descpool,
2123 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2124 goto return_exception;
2127 for (j = 0; j < m->thrownexceptionscount; j++) {
2128 if (!m->thrownexceptions[j].any)
2130 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2131 (utf *) m->thrownexceptions[j].any)) == NULL)
2132 goto return_exception;
2136 RT_TIMING_GET_TIME(time_parsemds);
2138 /* parse the loaded descriptors */
2140 for (i = 0; i < c->cpcount; i++) {
2141 constant_FMIref *fmi;
2144 switch (c->cptags[i]) {
2145 case CONSTANT_Fieldref:
2146 fmi = (constant_FMIref *) c->cpinfos[i];
2147 fmi->parseddesc.fd =
2148 descriptor_pool_parse_field_descriptor(descpool,
2150 if (!fmi->parseddesc.fd)
2151 goto return_exception;
2152 index = fmi->p.index;
2154 (constant_classref *) class_getconstant(c, index,
2156 if (!fmi->p.classref)
2157 goto return_exception;
2159 case CONSTANT_Methodref:
2160 case CONSTANT_InterfaceMethodref:
2161 fmi = (constant_FMIref *) c->cpinfos[i];
2162 index = fmi->p.index;
2164 (constant_classref *) class_getconstant(c, index,
2166 if (!fmi->p.classref)
2167 goto return_exception;
2168 fmi->parseddesc.md =
2169 descriptor_pool_parse_method_descriptor(descpool,
2173 if (!fmi->parseddesc.md)
2174 goto return_exception;
2179 RT_TIMING_GET_TIME(time_parsecpool);
2181 #ifdef ENABLE_VERIFIER
2182 /* Check if all fields and methods can be uniquely
2183 * identified by (name,descriptor). */
2186 /* We use a hash table here to avoid making the
2187 * average case quadratic in # of methods, fields.
2189 static int shift = 0;
2191 u2 *next; /* for chaining colliding hash entries */
2197 /* Allocate hashtable */
2198 len = c->methodscount;
2199 if (len < c->fieldscount) len = c->fieldscount;
2201 hashtab = MNEW(u2,(hashlen + len));
2202 next = hashtab + hashlen;
2204 /* Determine bitshift (to get good hash values) */
2214 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2216 for (i = 0; i < c->fieldscount; ++i) {
2217 fieldinfo *fi = c->fields + i;
2219 /* It's ok if we lose bits here */
2220 index = ((((size_t) fi->name) +
2221 ((size_t) fi->descriptor)) >> shift) % hashlen;
2223 if ((old = hashtab[index])) {
2227 if (c->fields[old].name == fi->name &&
2228 c->fields[old].descriptor == fi->descriptor) {
2229 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2230 goto return_exception;
2232 } while ((old = next[old]));
2234 hashtab[index] = i + 1;
2238 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2240 for (i = 0; i < c->methodscount; ++i) {
2241 methodinfo *mi = c->methods + i;
2243 /* It's ok if we lose bits here */
2244 index = ((((size_t) mi->name) +
2245 ((size_t) mi->descriptor)) >> shift) % hashlen;
2249 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2250 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2254 if ((old = hashtab[index])) {
2258 if (c->methods[old].name == mi->name &&
2259 c->methods[old].descriptor == mi->descriptor) {
2260 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2261 goto return_exception;
2263 } while ((old = next[old]));
2265 hashtab[index] = i + 1;
2268 MFREE(hashtab, u2, (hashlen + len));
2270 #endif /* ENABLE_VERIFIER */
2272 RT_TIMING_GET_TIME(time_verify);
2274 #if defined(ENABLE_STATISTICS)
2276 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2277 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2278 count_class_infos += sizeof(methodinfo) * c->methodscount;
2282 /* load attribute structures */
2284 if (!suck_check_classbuffer_size(cb, 2))
2285 goto return_exception;
2287 if (!load_attributes(cb, suck_u2(cb)))
2288 goto return_exception;
2291 /* Pre java 1.5 version don't check this. This implementation is like
2292 java 1.5 do it: for class file version 45.3 we don't check it, older
2293 versions are checked.
2295 if ((ma == 45 && mi > 3) || ma > 45) {
2296 /* check if all data has been read */
2297 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2299 if (classdata_left > 0) {
2300 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2301 goto return_exception;
2306 RT_TIMING_GET_TIME(time_attrs);
2308 /* release dump area */
2310 dump_release(dumpsize);
2312 /* revert loading state and class is loaded */
2314 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2316 #if !defined(NDEBUG)
2318 log_message_class("Loading done class: ", c);
2321 RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
2322 RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
2323 RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
2324 RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
2325 RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
2326 RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
2327 RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
2328 RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
2329 RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
2330 RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
2331 RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
2332 RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
2333 RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
2334 RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
2335 RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
2340 /* release dump area */
2342 dump_release(dumpsize);
2344 /* an exception has been thrown */
2350 /* load_newly_created_array ****************************************************
2352 Load a newly created array class.
2355 c....................the array class C has been loaded
2356 other classinfo......the array class was found in the class cache,
2358 NULL.................an exception has been thrown
2361 This is an internal function. Do not use it unless you know exactly
2364 Use one of the load_class_... functions for general array class loading.
2366 *******************************************************************************/
2368 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2370 classinfo *comp = NULL;
2372 methoddesc *clonedesc;
2373 constant_classref *classrefs;
2378 text = c->name->text;
2379 namelen = c->name->blength;
2381 /* Check array class name */
2383 if (namelen < 2 || text[0] != '[') {
2384 *exceptionptr = new_noclassdeffounderror(c->name);
2388 /* Check the element type */
2392 /* c is an array of arrays. We have to create the component class. */
2394 u = utf_new(text + 1, namelen - 1);
2395 if (!(comp = load_class_from_classloader(u, loader)))
2398 LOADER_ASSERT(comp->state & CLASS_LOADED);
2404 /* the array's flags are that of the component class */
2405 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2406 c->classloader = comp->classloader;
2410 /* c is an array of objects. */
2412 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2413 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2414 *exceptionptr = new_noclassdeffounderror(c->name);
2418 u = utf_new(text + 2, namelen - 3);
2420 if (!(comp = load_class_from_classloader(u, loader)))
2423 LOADER_ASSERT(comp->state & CLASS_LOADED);
2429 /* the array's flags are that of the component class */
2430 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2431 c->classloader = comp->classloader;
2435 /* c is an array of a primitive type */
2437 /* check for cases like `[II' */
2439 *exceptionptr = new_noclassdeffounderror(c->name);
2443 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2444 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2445 c->classloader = NULL;
2448 LOADER_ASSERT(class_java_lang_Object);
2449 LOADER_ASSERT(class_java_lang_Cloneable);
2450 LOADER_ASSERT(class_java_io_Serializable);
2452 /* setup the array class */
2454 c->super.cls = class_java_lang_Object;
2456 c->interfacescount = 2;
2457 c->interfaces = MNEW(classref_or_classinfo, 2);
2462 tc = class_java_lang_Cloneable;
2463 LOADER_ASSERT(tc->state & CLASS_LOADED);
2464 list_addfirst(&unlinkedclasses, tc);
2465 c->interfaces[0].cls = tc;
2467 tc = class_java_io_Serializable;
2468 LOADER_ASSERT(tc->state & CLASS_LOADED);
2469 list_addfirst(&unlinkedclasses, tc);
2470 c->interfaces[1].cls = tc;
2473 c->interfaces[0].cls = class_java_lang_Cloneable;
2474 c->interfaces[1].cls = class_java_io_Serializable;
2477 c->methodscount = 1;
2478 c->methods = MNEW(methodinfo, c->methodscount);
2480 classrefs = MNEW(constant_classref, 2);
2481 CLASSREF_INIT(classrefs[0], c, c->name);
2482 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2484 /* create descriptor for clone method */
2485 /* we need one paramslot which is reserved for the 'this' parameter */
2486 clonedesc = NEW(methoddesc);
2487 clonedesc->returntype.type = TYPE_ADDRESS;
2488 clonedesc->returntype.classref = classrefs + 1;
2489 clonedesc->returntype.arraydim = 0;
2490 /* initialize params to "empty", add real params below in
2491 descriptor_params_from_paramtypes */
2492 clonedesc->paramcount = 0;
2493 clonedesc->paramslots = 0;
2494 clonedesc->paramtypes[0].classref = classrefs + 0;
2496 /* create methodinfo */
2499 MSET(clone, 0, methodinfo, 1);
2501 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2502 initObjectLock(&clone->header);
2505 /* ATTENTION: if you delete the ACC_NATIVE below, set
2506 clone->maxlocals=1 (interpreter related) */
2508 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2509 clone->name = utf_clone;
2510 clone->descriptor = utf_void__java_lang_Object;
2511 clone->parseddesc = clonedesc;
2514 /* parse the descriptor to get the register allocation */
2516 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2520 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2522 /* XXX: field: length? */
2524 /* array classes are not loaded from class files */
2526 c->state |= CLASS_LOADED;
2527 c->parseddescs = (u1 *) clonedesc;
2528 c->parseddescsize = sizeof(methodinfo);
2529 c->classrefs = classrefs;
2530 c->classrefcount = 1;
2532 /* insert class into the loaded class cache */
2533 /* XXX free classinfo if NULL returned? */
2535 return classcache_store(loader, c, true);
2539 /* loader_close ****************************************************************
2541 Frees all resources.
2543 *******************************************************************************/
2545 void loader_close(void)
2552 * These are local overrides for various environment variables in Emacs.
2553 * Please do not remove this and leave it at the end of the file, where
2554 * Emacs will automagically detect them.
2555 * ---------------------------------------------------------------------
2558 * indent-tabs-mode: t
2562 * vim:noexpandtab:sw=4:ts=4: