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 4908 2006-05-12 16:49:50Z 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 lock_init_object_lock((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)
228 lock_init(); /* XXX this should probably be done only for green threads */
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_printable_ascii_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 lock_init_object_lock(&m->header);
1022 #if defined(ENABLE_STATISTICS)
1024 count_all_methods++;
1027 /* all fields of m have been zeroed in load_class_from_classbuffer */
1031 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1034 m->flags = suck_u2(cb);
1036 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1041 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1046 if (!descriptor_pool_add(descpool, u, &argcount))
1049 #ifdef ENABLE_VERIFIER
1051 if (!is_valid_name_utf(m->name)) {
1052 exceptions_throw_classformaterror(c, "Method with invalid name");
1056 if (m->name->text[0] == '<' &&
1057 m->name != utf_init && m->name != utf_clinit) {
1058 exceptions_throw_classformaterror(c, "Method with invalid special name");
1062 #endif /* ENABLE_VERIFIER */
1064 if (!(m->flags & ACC_STATIC))
1065 argcount++; /* count the 'this' argument */
1067 #ifdef ENABLE_VERIFIER
1069 if (argcount > 255) {
1070 exceptions_throw_classformaterror(c, "Too many arguments in signature");
1074 /* check flag consistency */
1075 if (m->name != utf_clinit) {
1076 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1078 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1079 exceptions_throw_classformaterror(c,
1080 "Illegal method modifiers: 0x%X",
1085 if (m->flags & ACC_ABSTRACT) {
1086 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1087 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1088 exceptions_throw_classformaterror(c,
1089 "Illegal method modifiers: 0x%X",
1095 if (c->flags & ACC_INTERFACE) {
1096 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1097 exceptions_throw_classformaterror(c,
1098 "Illegal method modifiers: 0x%X",
1104 if (m->name == utf_init) {
1105 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1106 ACC_NATIVE | ACC_ABSTRACT)) {
1107 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1113 #endif /* ENABLE_VERIFIER */
1115 if (!suck_check_classbuffer_size(cb, 2))
1118 attrnum = suck_u2(cb);
1119 for (i = 0; i < attrnum; i++) {
1122 if (!suck_check_classbuffer_size(cb, 2))
1125 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1128 if (aname == utf_Code) {
1129 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1130 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1135 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1139 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1143 m->maxstack = suck_u2(cb);
1144 m->maxlocals = suck_u2(cb);
1146 if (m->maxlocals < argcount) {
1147 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1151 if (!suck_check_classbuffer_size(cb, 4))
1154 m->jcodelength = suck_u4(cb);
1156 if (m->jcodelength == 0) {
1157 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1161 if (m->jcodelength > 65535) {
1162 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1166 if (!suck_check_classbuffer_size(cb, m->jcodelength))
1169 m->jcode = MNEW(u1, m->jcodelength);
1170 suck_nbytes(m->jcode, cb, m->jcodelength);
1172 if (!suck_check_classbuffer_size(cb, 2))
1175 m->exceptiontablelength = suck_u2(cb);
1176 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1179 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1181 #if defined(ENABLE_STATISTICS)
1183 count_vmcode_len += m->jcodelength + 18;
1184 count_extable_len +=
1185 m->exceptiontablelength * sizeof(exceptiontable);
1189 for (j = 0; j < m->exceptiontablelength; j++) {
1191 m->exceptiontable[j].startpc = suck_u2(cb);
1192 m->exceptiontable[j].endpc = suck_u2(cb);
1193 m->exceptiontable[j].handlerpc = suck_u2(cb);
1197 m->exceptiontable[j].catchtype.any = NULL;
1200 /* the classref is created later */
1201 if (!(m->exceptiontable[j].catchtype.any =
1202 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1207 if (!suck_check_classbuffer_size(cb, 2))
1210 codeattrnum = suck_u2(cb);
1212 for (; codeattrnum > 0; codeattrnum--) {
1215 if (!suck_check_classbuffer_size(cb, 2))
1218 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1221 if (caname == utf_LineNumberTable) {
1224 if (!suck_check_classbuffer_size(cb, 4 + 2))
1228 m->linenumbercount = suck_u2(cb);
1230 if (!suck_check_classbuffer_size(cb,
1231 (2 + 2) * m->linenumbercount))
1234 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1236 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1237 m->linenumbers[lncid].start_pc = suck_u2(cb);
1238 m->linenumbers[lncid].line_number = suck_u2(cb);
1242 if (!skipattributes(cb, codeattrnum))
1248 if (!skipattributebody(cb))
1253 } else if (aname == utf_Exceptions) {
1256 if (m->thrownexceptions) {
1257 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1261 if (!suck_check_classbuffer_size(cb, 4 + 2))
1264 suck_u4(cb); /* length */
1265 m->thrownexceptionscount = suck_u2(cb);
1267 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1270 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1272 for (j = 0; j < m->thrownexceptionscount; j++) {
1273 /* the classref is created later */
1274 if (!((m->thrownexceptions)[j].any =
1275 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1280 if (!skipattributebody(cb))
1285 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1286 exceptions_throw_classformaterror(c, "Missing Code attribute");
1290 /* everything was ok */
1296 /* load_attribute **************************************************************
1298 Read attributes from classfile.
1300 *******************************************************************************/
1302 static bool load_attributes(classbuffer *cb, u4 num)
1310 for (i = 0; i < num; i++) {
1311 /* retrieve attribute name */
1312 if (!suck_check_classbuffer_size(cb, 2))
1315 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1318 if (aname == utf_InnerClasses) {
1319 /* innerclasses attribute */
1320 if (c->innerclass) {
1321 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1325 if (!suck_check_classbuffer_size(cb, 4 + 2))
1328 /* skip attribute length */
1331 /* number of records */
1332 c->innerclasscount = suck_u2(cb);
1334 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1337 /* allocate memory for innerclass structure */
1338 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1340 for (j = 0; j < c->innerclasscount; j++) {
1341 /* The innerclass structure contains a class with an encoded
1342 name, its defining scope, its simple name and a bitmask of
1343 the access flags. If an inner class is not a member, its
1344 outer_class is NULL, if a class is anonymous, its name is
1347 innerclassinfo *info = c->innerclass + j;
1349 info->inner_class.ref =
1350 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1351 info->outer_class.ref =
1352 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1354 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1355 info->flags = suck_u2(cb);
1358 } else if (aname == utf_SourceFile) {
1359 if (!suck_check_classbuffer_size(cb, 4 + 2))
1362 if (suck_u4(cb) != 2) {
1363 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1367 if (c->sourcefile) {
1368 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1372 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1376 /* unknown attribute */
1377 if (!skipattributebody(cb))
1386 /* load_class_from_sysloader ***************************************************
1388 Load the class with the given name using the system class loader
1391 name.............the classname
1394 the loaded class, or
1395 NULL if an exception has been thrown
1397 *******************************************************************************/
1399 classinfo *load_class_from_sysloader(utf *name)
1402 java_objectheader *cl;
1405 LOADER_ASSERT(class_java_lang_Object);
1406 LOADER_ASSERT(class_java_lang_ClassLoader);
1407 LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1409 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1410 utf_getSystemClassLoader,
1411 utf_void__java_lang_ClassLoader,
1412 class_java_lang_Object,
1418 cl = vm_call_method(m, NULL);
1423 c = load_class_from_classloader(name, cl);
1429 /* load_class_from_classloader *************************************************
1431 Load the class with the given name using the given user-defined class loader.
1434 name.............the classname
1435 cl...............user-defined class loader
1438 the loaded class, or
1439 NULL if an exception has been thrown
1441 *******************************************************************************/
1443 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1445 java_objectheader *o;
1448 java_lang_String *s;
1449 #if defined(ENABLE_RT_TIMING)
1450 struct timespec time_start, time_lookup, time_prepare, time_java,
1454 RT_TIMING_GET_TIME(time_start);
1456 LOADER_ASSERT(name);
1458 /* lookup if this class has already been loaded */
1460 c = classcache_lookup(cl, name);
1462 RT_TIMING_GET_TIME(time_lookup);
1463 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
1468 /* if other class loader than bootstrap, call it */
1476 namelen = name->blength;
1478 /* handle array classes */
1479 if (text[0] == '[') {
1485 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1486 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1487 *exceptionptr = new_noclassdeffounderror(name);
1491 u = utf_new(text + 2, namelen - 3);
1493 if (!(comp = load_class_from_classloader(u, cl)))
1496 /* create the array class */
1498 c = class_array_of(comp, false);
1500 tmpc = classcache_store(cl, c, true);
1503 /* exception, free the loaded class */
1504 c->state &= ~CLASS_LOADING;
1511 /* load the component class */
1513 u = utf_new(text + 1, namelen - 1);
1515 if (!(comp = load_class_from_classloader(u, cl)))
1518 /* create the array class */
1520 c = class_array_of(comp, false);
1522 tmpc = classcache_store(cl, c, true);
1525 /* exception, free the loaded class */
1526 c->state &= ~CLASS_LOADING;
1533 /* primitive array classes are loaded by the bootstrap loader */
1535 c = load_class_bootstrap(name);
1541 LOADER_ASSERT(class_java_lang_Object);
1543 lc = class_resolveclassmethod(cl->vftbl->class,
1545 utf_java_lang_String__java_lang_Class,
1546 class_java_lang_Object,
1550 return false; /* exception */
1552 /* move return value into `o' and cast it afterwards to a classinfo* */
1554 s = javastring_new_slash_to_dot(name);
1556 RT_TIMING_GET_TIME(time_prepare);
1558 o = vm_call_method(lc, cl, s);
1560 RT_TIMING_GET_TIME(time_java);
1562 c = (classinfo *) o;
1565 /* Store this class in the loaded class cache. If another
1566 class with the same (initloader,name) pair has been
1567 stored earlier it will be returned by classcache_store
1568 In this case classcache_store may not free the class
1569 because it has already been exposed to Java code which
1570 may have kept references to that class. */
1572 tmpc = classcache_store(cl, c, false);
1575 /* exception, free the loaded class */
1576 c->state &= ~CLASS_LOADING;
1583 /* loadClass has thrown an exception. We must convert
1584 ClassNotFoundException into
1585 NoClassDefFoundException. */
1587 /* XXX Maybe we should have a flag that avoids this
1588 conversion for calling load_class_from_classloader from
1589 Class.forName. Currently we do a double conversion in
1592 classnotfoundexception_to_noclassdeffounderror();
1595 RT_TIMING_GET_TIME(time_cache);
1597 RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
1598 RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
1599 RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
1601 /* SUN compatible -verbose:class output */
1603 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1605 utf_display_printable_ascii_classname(name);
1612 c = load_class_bootstrap(name);
1618 /* load_class_bootstrap ********************************************************
1620 Load the class with the given name using the bootstrap class loader.
1623 name.............the classname
1626 loaded classinfo, or
1627 NULL if an exception has been thrown
1630 load_class_bootstrap is synchronized. It can be treated as an
1633 *******************************************************************************/
1635 classinfo *load_class_bootstrap(utf *name)
1640 #if defined(ENABLE_RT_TIMING)
1641 struct timespec time_start, time_lookup, time_array, time_suck,
1642 time_load, time_cache;
1645 RT_TIMING_GET_TIME(time_start);
1649 LOADER_ASSERT(name);
1651 /* lookup if this class has already been loaded */
1653 if ((r = classcache_lookup(NULL, name))) {
1655 RT_TIMING_GET_TIME(time_lookup);
1656 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
1661 RT_TIMING_GET_TIME(time_lookup);
1662 RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
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);
1676 RT_TIMING_GET_TIME(time_array);
1677 RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
1682 #if defined(ENABLE_STATISTICS)
1685 if (opt_getcompilingtime)
1686 compilingtime_stop();
1688 if (opt_getloadingtime)
1689 loadingtime_start();
1692 /* load classdata, throw exception on error */
1694 if ((cb = suck_start(c)) == NULL) {
1695 /* this normally means, the classpath was not set properly */
1697 if (name == utf_java_lang_Object)
1698 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1699 "java/lang/Object");
1701 *exceptionptr = new_noclassdeffounderror(name);
1706 RT_TIMING_GET_TIME(time_suck);
1708 /* load the class from the buffer */
1710 r = load_class_from_classbuffer(cb);
1712 RT_TIMING_GET_TIME(time_load);
1715 /* the class could not be loaded, free the classinfo struct */
1720 /* Store this class in the loaded class cache this step also
1721 checks the loading constraints. If the class has been loaded
1722 before, the earlier loaded class is returned. */
1724 classinfo *res = classcache_store(NULL, c, true);
1734 RT_TIMING_GET_TIME(time_cache);
1736 /* SUN compatible -verbose:class output */
1738 if (opt_verboseclass && r) {
1740 utf_display_printable_ascii_classname(name);
1741 printf(" from %s]\n", cb->path);
1748 #if defined(ENABLE_STATISTICS)
1751 if (opt_getloadingtime)
1754 if (opt_getcompilingtime)
1755 compilingtime_start();
1758 RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
1759 RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
1760 RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
1761 RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
1767 /* load_class_from_classbuffer *************************************************
1769 Loads everything interesting about a class from the class file. The
1770 'classinfo' structure must have been allocated previously.
1772 The super class and the interfaces implemented by this class need
1773 not be loaded. The link is set later by the function 'class_link'.
1775 The loaded class is removed from the list 'unloadedclasses' and
1776 added to the list 'unlinkedclasses'.
1779 This function is NOT synchronized!
1781 *******************************************************************************/
1783 classinfo *load_class_from_classbuffer(classbuffer *cb)
1791 descriptor_pool *descpool;
1792 #if defined(ENABLE_STATISTICS)
1796 #if defined(ENABLE_RT_TIMING)
1797 struct timespec time_start, time_checks, time_ndpool, time_cpool,
1798 time_setup, time_fields, time_methods, time_classrefs,
1799 time_descs, time_setrefs, time_parsefds, time_parsemds,
1800 time_parsecpool, time_verify, time_attrs;
1803 RT_TIMING_GET_TIME(time_start);
1805 /* get the classbuffer's class */
1809 /* the class is already loaded */
1811 if (c->state & CLASS_LOADED)
1814 #if defined(ENABLE_STATISTICS)
1816 count_class_loads++;
1819 #if !defined(NDEBUG)
1820 /* output for debugging purposes */
1823 log_message_class("Loading class: ", c);
1826 /* mark start of dump memory area */
1828 dumpsize = dump_size();
1830 /* class is currently loading */
1832 c->state |= CLASS_LOADING;
1834 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1835 goto return_exception;
1837 /* check signature */
1839 if (suck_u4(cb) != MAGIC) {
1840 exceptions_throw_classformaterror(c, "Bad magic number");
1842 goto return_exception;
1850 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1852 new_unsupportedclassversionerror(c,
1853 "Unsupported major.minor version %d.%d",
1856 goto return_exception;
1858 RT_TIMING_GET_TIME(time_checks);
1860 /* create a new descriptor pool */
1862 descpool = descriptor_pool_new(c);
1864 RT_TIMING_GET_TIME(time_ndpool);
1866 /* load the constant pool */
1868 if (!load_constantpool(cb, descpool))
1869 goto return_exception;
1871 RT_TIMING_GET_TIME(time_cpool);
1875 if (!suck_check_classbuffer_size(cb, 2))
1876 goto return_exception;
1878 c->flags = suck_u2(cb);
1880 /* check ACC flags consistency */
1882 if (c->flags & ACC_INTERFACE) {
1883 if (!(c->flags & ACC_ABSTRACT)) {
1884 /* We work around this because interfaces in JDK 1.1 are
1885 * not declared abstract. */
1887 c->flags |= ACC_ABSTRACT;
1890 if (c->flags & ACC_FINAL) {
1891 exceptions_throw_classformaterror(c,
1892 "Illegal class modifiers: 0x%X",
1894 goto return_exception;
1897 if (c->flags & ACC_SUPER) {
1898 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1902 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1903 exceptions_throw_classformaterror(c,
1904 "Illegal class modifiers: 0x%X",
1906 goto return_exception;
1909 if (!suck_check_classbuffer_size(cb, 2 + 2))
1910 goto return_exception;
1915 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1916 goto return_exception;
1918 if (c->name == utf_not_named_yet) {
1919 /* we finally have a name for this class */
1921 class_set_packagename(c);
1923 } else if (name != c->name) {
1927 msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
1928 utf_bytes(name) + strlen(")") + strlen("0");
1930 msg = MNEW(char, msglen);
1932 utf_copy_classname(msg, c->name);
1933 strcat(msg, " (wrong name: ");
1934 utf_cat_classname(msg, name);
1938 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1940 MFREE(msg, char, msglen);
1942 goto return_exception;
1945 /* retrieve superclass */
1947 c->super.any = NULL;
1948 if ((i = suck_u2(cb))) {
1949 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1950 goto return_exception;
1952 /* java.lang.Object may not have a super class. */
1954 if (c->name == utf_java_lang_Object) {
1956 new_exception_message(string_java_lang_ClassFormatError,
1957 "java.lang.Object with superclass");
1959 goto return_exception;
1962 /* Interfaces must have java.lang.Object as super class. */
1964 if ((c->flags & ACC_INTERFACE) &&
1965 supername != utf_java_lang_Object) {
1967 new_exception_message(string_java_lang_ClassFormatError,
1968 "Interfaces must have java.lang.Object as superclass");
1970 goto return_exception;
1976 /* This is only allowed for java.lang.Object. */
1978 if (c->name != utf_java_lang_Object) {
1979 exceptions_throw_classformaterror(c, "Bad superclass index");
1980 goto return_exception;
1984 /* retrieve interfaces */
1986 if (!suck_check_classbuffer_size(cb, 2))
1987 goto return_exception;
1989 c->interfacescount = suck_u2(cb);
1991 if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1992 goto return_exception;
1994 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1995 for (i = 0; i < c->interfacescount; i++) {
1996 /* the classrefs are created later */
1997 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1998 goto return_exception;
2001 RT_TIMING_GET_TIME(time_setup);
2004 if (!suck_check_classbuffer_size(cb, 2))
2005 goto return_exception;
2007 c->fieldscount = suck_u2(cb);
2008 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2009 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2010 for (i = 0; i < c->fieldscount; i++) {
2011 if (!load_field(cb, &(c->fields[i]),descpool))
2012 goto return_exception;
2015 RT_TIMING_GET_TIME(time_fields);
2018 if (!suck_check_classbuffer_size(cb, 2))
2019 goto return_exception;
2021 c->methodscount = suck_u2(cb);
2022 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2023 c->methods = MNEW(methodinfo, c->methodscount);
2025 MZERO(c->methods, methodinfo, c->methodscount);
2027 for (i = 0; i < c->methodscount; i++) {
2028 if (!load_method(cb, &(c->methods[i]),descpool))
2029 goto return_exception;
2032 RT_TIMING_GET_TIME(time_methods);
2034 /* create the class reference table */
2037 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2039 RT_TIMING_GET_TIME(time_classrefs);
2041 /* allocate space for the parsed descriptors */
2043 descriptor_pool_alloc_parsed_descriptors(descpool);
2045 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2047 #if defined(ENABLE_STATISTICS)
2049 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2050 count_classref_len += classrefsize;
2051 count_parsed_desc_len += descsize;
2055 RT_TIMING_GET_TIME(time_descs);
2057 /* put the classrefs in the constant pool */
2058 for (i = 0; i < c->cpcount; i++) {
2059 if (c->cptags[i] == CONSTANT_Class) {
2060 utf *name = (utf *) c->cpinfos[i];
2061 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2065 /* set the super class reference */
2068 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2070 goto return_exception;
2073 /* set the super interfaces references */
2075 for (i = 0; i < c->interfacescount; i++) {
2076 c->interfaces[i].ref =
2077 descriptor_pool_lookup_classref(descpool,
2078 (utf *) c->interfaces[i].any);
2079 if (!c->interfaces[i].ref)
2080 goto return_exception;
2083 RT_TIMING_GET_TIME(time_setrefs);
2085 /* parse field descriptors */
2087 for (i = 0; i < c->fieldscount; i++) {
2088 c->fields[i].parseddesc =
2089 descriptor_pool_parse_field_descriptor(descpool,
2090 c->fields[i].descriptor);
2091 if (!c->fields[i].parseddesc)
2092 goto return_exception;
2095 RT_TIMING_GET_TIME(time_parsefds);
2097 /* parse method descriptors */
2099 for (i = 0; i < c->methodscount; i++) {
2100 methodinfo *m = &c->methods[i];
2102 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2103 m->flags, class_get_self_classref(m->class));
2105 goto return_exception;
2107 for (j = 0; j < m->exceptiontablelength; j++) {
2108 if (!m->exceptiontable[j].catchtype.any)
2110 if ((m->exceptiontable[j].catchtype.ref =
2111 descriptor_pool_lookup_classref(descpool,
2112 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2113 goto return_exception;
2116 for (j = 0; j < m->thrownexceptionscount; j++) {
2117 if (!m->thrownexceptions[j].any)
2119 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2120 (utf *) m->thrownexceptions[j].any)) == NULL)
2121 goto return_exception;
2125 RT_TIMING_GET_TIME(time_parsemds);
2127 /* parse the loaded descriptors */
2129 for (i = 0; i < c->cpcount; i++) {
2130 constant_FMIref *fmi;
2133 switch (c->cptags[i]) {
2134 case CONSTANT_Fieldref:
2135 fmi = (constant_FMIref *) c->cpinfos[i];
2136 fmi->parseddesc.fd =
2137 descriptor_pool_parse_field_descriptor(descpool,
2139 if (!fmi->parseddesc.fd)
2140 goto return_exception;
2141 index = fmi->p.index;
2143 (constant_classref *) class_getconstant(c, index,
2145 if (!fmi->p.classref)
2146 goto return_exception;
2148 case CONSTANT_Methodref:
2149 case CONSTANT_InterfaceMethodref:
2150 fmi = (constant_FMIref *) c->cpinfos[i];
2151 index = fmi->p.index;
2153 (constant_classref *) class_getconstant(c, index,
2155 if (!fmi->p.classref)
2156 goto return_exception;
2157 fmi->parseddesc.md =
2158 descriptor_pool_parse_method_descriptor(descpool,
2162 if (!fmi->parseddesc.md)
2163 goto return_exception;
2168 RT_TIMING_GET_TIME(time_parsecpool);
2170 #ifdef ENABLE_VERIFIER
2171 /* Check if all fields and methods can be uniquely
2172 * identified by (name,descriptor). */
2175 /* We use a hash table here to avoid making the
2176 * average case quadratic in # of methods, fields.
2178 static int shift = 0;
2180 u2 *next; /* for chaining colliding hash entries */
2186 /* Allocate hashtable */
2187 len = c->methodscount;
2188 if (len < c->fieldscount) len = c->fieldscount;
2190 hashtab = MNEW(u2,(hashlen + len));
2191 next = hashtab + hashlen;
2193 /* Determine bitshift (to get good hash values) */
2203 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2205 for (i = 0; i < c->fieldscount; ++i) {
2206 fieldinfo *fi = c->fields + i;
2208 /* It's ok if we lose bits here */
2209 index = ((((size_t) fi->name) +
2210 ((size_t) fi->descriptor)) >> shift) % hashlen;
2212 if ((old = hashtab[index])) {
2216 if (c->fields[old].name == fi->name &&
2217 c->fields[old].descriptor == fi->descriptor) {
2218 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2219 goto return_exception;
2221 } while ((old = next[old]));
2223 hashtab[index] = i + 1;
2227 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2229 for (i = 0; i < c->methodscount; ++i) {
2230 methodinfo *mi = c->methods + i;
2232 /* It's ok if we lose bits here */
2233 index = ((((size_t) mi->name) +
2234 ((size_t) mi->descriptor)) >> shift) % hashlen;
2238 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2239 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2243 if ((old = hashtab[index])) {
2247 if (c->methods[old].name == mi->name &&
2248 c->methods[old].descriptor == mi->descriptor) {
2249 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2250 goto return_exception;
2252 } while ((old = next[old]));
2254 hashtab[index] = i + 1;
2257 MFREE(hashtab, u2, (hashlen + len));
2259 #endif /* ENABLE_VERIFIER */
2261 RT_TIMING_GET_TIME(time_verify);
2263 #if defined(ENABLE_STATISTICS)
2265 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2266 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2267 count_class_infos += sizeof(methodinfo) * c->methodscount;
2271 /* load attribute structures */
2273 if (!suck_check_classbuffer_size(cb, 2))
2274 goto return_exception;
2276 if (!load_attributes(cb, suck_u2(cb)))
2277 goto return_exception;
2280 /* Pre java 1.5 version don't check this. This implementation is like
2281 java 1.5 do it: for class file version 45.3 we don't check it, older
2282 versions are checked.
2284 if ((ma == 45 && mi > 3) || ma > 45) {
2285 /* check if all data has been read */
2286 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2288 if (classdata_left > 0) {
2289 exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2290 goto return_exception;
2295 RT_TIMING_GET_TIME(time_attrs);
2297 /* release dump area */
2299 dump_release(dumpsize);
2301 /* revert loading state and class is loaded */
2303 c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2305 #if !defined(NDEBUG)
2307 log_message_class("Loading done class: ", c);
2310 RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
2311 RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
2312 RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
2313 RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
2314 RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
2315 RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
2316 RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
2317 RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
2318 RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
2319 RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
2320 RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
2321 RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
2322 RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
2323 RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
2324 RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
2329 /* release dump area */
2331 dump_release(dumpsize);
2333 /* an exception has been thrown */
2339 /* load_newly_created_array ****************************************************
2341 Load a newly created array class.
2344 c....................the array class C has been loaded
2345 other classinfo......the array class was found in the class cache,
2347 NULL.................an exception has been thrown
2350 This is an internal function. Do not use it unless you know exactly
2353 Use one of the load_class_... functions for general array class loading.
2355 *******************************************************************************/
2357 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2359 classinfo *comp = NULL;
2361 methoddesc *clonedesc;
2362 constant_classref *classrefs;
2367 text = c->name->text;
2368 namelen = c->name->blength;
2370 /* Check array class name */
2372 if (namelen < 2 || text[0] != '[') {
2373 *exceptionptr = new_noclassdeffounderror(c->name);
2377 /* Check the element type */
2381 /* c is an array of arrays. We have to create the component class. */
2383 u = utf_new(text + 1, namelen - 1);
2384 if (!(comp = load_class_from_classloader(u, loader)))
2387 LOADER_ASSERT(comp->state & CLASS_LOADED);
2393 /* the array's flags are that of the component class */
2394 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2395 c->classloader = comp->classloader;
2399 /* c is an array of objects. */
2401 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2402 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2403 *exceptionptr = new_noclassdeffounderror(c->name);
2407 u = utf_new(text + 2, namelen - 3);
2409 if (!(comp = load_class_from_classloader(u, loader)))
2412 LOADER_ASSERT(comp->state & CLASS_LOADED);
2418 /* the array's flags are that of the component class */
2419 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2420 c->classloader = comp->classloader;
2424 /* c is an array of a primitive type */
2426 /* check for cases like `[II' */
2428 *exceptionptr = new_noclassdeffounderror(c->name);
2432 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2433 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2434 c->classloader = NULL;
2437 LOADER_ASSERT(class_java_lang_Object);
2438 LOADER_ASSERT(class_java_lang_Cloneable);
2439 LOADER_ASSERT(class_java_io_Serializable);
2441 /* setup the array class */
2443 c->super.cls = class_java_lang_Object;
2445 c->interfacescount = 2;
2446 c->interfaces = MNEW(classref_or_classinfo, 2);
2451 tc = class_java_lang_Cloneable;
2452 LOADER_ASSERT(tc->state & CLASS_LOADED);
2453 list_addfirst(&unlinkedclasses, tc);
2454 c->interfaces[0].cls = tc;
2456 tc = class_java_io_Serializable;
2457 LOADER_ASSERT(tc->state & CLASS_LOADED);
2458 list_addfirst(&unlinkedclasses, tc);
2459 c->interfaces[1].cls = tc;
2462 c->interfaces[0].cls = class_java_lang_Cloneable;
2463 c->interfaces[1].cls = class_java_io_Serializable;
2466 c->methodscount = 1;
2467 c->methods = MNEW(methodinfo, c->methodscount);
2469 classrefs = MNEW(constant_classref, 2);
2470 CLASSREF_INIT(classrefs[0], c, c->name);
2471 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2473 /* create descriptor for clone method */
2474 /* we need one paramslot which is reserved for the 'this' parameter */
2475 clonedesc = NEW(methoddesc);
2476 clonedesc->returntype.type = TYPE_ADDRESS;
2477 clonedesc->returntype.classref = classrefs + 1;
2478 clonedesc->returntype.arraydim = 0;
2479 /* initialize params to "empty", add real params below in
2480 descriptor_params_from_paramtypes */
2481 clonedesc->paramcount = 0;
2482 clonedesc->paramslots = 0;
2483 clonedesc->paramtypes[0].classref = classrefs + 0;
2484 clonedesc->params = NULL;
2486 /* create methodinfo */
2489 MSET(clone, 0, methodinfo, 1);
2491 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2492 lock_init_object_lock(&clone->header);
2495 /* ATTENTION: if you delete the ACC_NATIVE below, set
2496 clone->maxlocals=1 (interpreter related) */
2498 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2499 clone->name = utf_clone;
2500 clone->descriptor = utf_void__java_lang_Object;
2501 clone->parseddesc = clonedesc;
2504 /* parse the descriptor to get the register allocation */
2506 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2510 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2512 /* XXX: field: length? */
2514 /* array classes are not loaded from class files */
2516 c->state |= CLASS_LOADED;
2517 c->parseddescs = (u1 *) clonedesc;
2518 c->parseddescsize = sizeof(methodinfo);
2519 c->classrefs = classrefs;
2520 c->classrefcount = 1;
2522 /* insert class into the loaded class cache */
2523 /* XXX free classinfo if NULL returned? */
2525 return classcache_store(loader, c, true);
2529 /* loader_close ****************************************************************
2531 Frees all resources.
2533 *******************************************************************************/
2535 void loader_close(void)
2542 * These are local overrides for various environment variables in Emacs.
2543 * Please do not remove this and leave it at the end of the file, where
2544 * Emacs will automagically detect them.
2545 * ---------------------------------------------------------------------
2548 * indent-tabs-mode: t
2552 * vim:noexpandtab:sw=4:ts=4: