1 /* src/vm/loader.c - class loader functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: loader.c 2186 2005-04-02 00:43:25Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Throwable.h"
50 #if defined(USE_THREADS)
51 # if defined(NATIVE_THREADS)
52 # include "threads/native/threads.h"
54 # include "threads/green/threads.h"
55 # include "threads/green/locks.h"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
61 #include "vm/exceptions.h"
62 #include "vm/builtin.h"
63 #include "vm/global.h"
64 #include "vm/linker.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69 #include "vm/tables.h"
72 # include "vm/unzip.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
84 /********************************************************************
85 list of classpath entries (either filesystem directories or
87 ********************************************************************/
89 classpath_info *classpath_entries = NULL;
91 /* loader_init *****************************************************************
93 Initializes all lists and loads all classes required for the system
96 *******************************************************************************/
98 bool loader_init(u1 *stackbottom)
102 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
103 /* Initialize the monitor pointer for zip/jar file locking. */
105 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
106 if (cpi->type == CLASSPATH_ARCHIVE)
107 initObjectLock(&cpi->header);
111 /* load some important classes */
113 if (!load_class_bootstrap(class_java_lang_Object))
116 if (!load_class_bootstrap(class_java_lang_String))
119 if (!load_class_bootstrap(class_java_lang_Cloneable))
122 if (!load_class_bootstrap(class_java_io_Serializable))
126 /* load classes for wrapping primitive types */
128 if (!load_class_bootstrap(class_java_lang_Void))
131 if (!load_class_bootstrap(class_java_lang_Boolean))
134 if (!load_class_bootstrap(class_java_lang_Byte))
137 if (!load_class_bootstrap(class_java_lang_Character))
140 if (!load_class_bootstrap(class_java_lang_Short))
143 if (!load_class_bootstrap(class_java_lang_Integer))
146 if (!load_class_bootstrap(class_java_lang_Long))
149 if (!load_class_bootstrap(class_java_lang_Float))
152 if (!load_class_bootstrap(class_java_lang_Double))
156 #if defined(USE_THREADS)
157 if (stackbottom != 0)
165 /************* functions for reading classdata *********************************
167 getting classdata in blocks of variable size
168 (8,16,32,64-bit integer or float)
170 *******************************************************************************/
172 /* check_classbuffer_size ******************************************************
174 assert that at least <len> bytes are left to read
175 <len> is limited to the range of non-negative s4 values
177 *******************************************************************************/
179 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
181 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
183 new_classformaterror((cb)->class, "Truncated class file");
192 /* suck_nbytes *****************************************************************
194 transfer block of classfile data into a buffer
196 *******************************************************************************/
198 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
200 memcpy(buffer, cb->pos + 1, len);
205 /* skip_nbytes ****************************************************************
207 skip block of classfile data
209 *******************************************************************************/
211 inline void skip_nbytes(classbuffer *cb, s4 len)
217 inline u1 suck_u1(classbuffer *cb)
223 inline u2 suck_u2(classbuffer *cb)
227 return ((u2) a << 8) + (u2) b;
231 inline u4 suck_u4(classbuffer *cb)
237 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
241 /* get u8 from classfile data */
242 static u8 suck_u8(classbuffer *cb)
248 return (hi << 32) + lo;
251 v.high = suck_u4(cb);
258 /* get float from classfile data */
259 static float suck_float(classbuffer *cb)
267 for (i = 0; i < 4; i++)
268 buffer[3 - i] = suck_u1(cb);
270 memcpy((u1*) (&f), buffer, 4);
272 suck_nbytes((u1*) (&f), cb, 4);
275 if (sizeof(float) != 4) {
276 *exceptionptr = new_exception_message(string_java_lang_InternalError,
277 "Incompatible float-format");
279 /* XXX should we exit in such a case? */
280 throw_exception_exit();
287 /* get double from classfile data */
288 static double suck_double(classbuffer *cb)
296 for (i = 0; i < 8; i++)
297 buffer[7 - i] = suck_u1(cb);
299 memcpy((u1*) (&d), buffer, 8);
301 suck_nbytes((u1*) (&d), cb, 8);
304 if (sizeof(double) != 8) {
305 *exceptionptr = new_exception_message(string_java_lang_InternalError,
306 "Incompatible double-format");
308 /* XXX should we exit in such a case? */
309 throw_exception_exit();
316 /************************** function suck_init *********************************
318 called once at startup, sets the searchpath for the classfiles
320 *******************************************************************************/
322 void suck_init(char *classpath)
330 classpath_info *lastcpi;
334 /* search for last classpath entry (only if there already some) */
336 if ((lastcpi = classpath_entries)) {
337 while (lastcpi->next)
338 lastcpi = lastcpi->next;
341 for (start = classpath; (*start) != '\0';) {
343 /* search for ':' delimiter to get the end of the current entry */
344 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
348 filenamelen = end - start;
350 if (filenamelen > 3) {
351 if (strncasecmp(end - 3, "zip", 3) == 0 ||
352 strncasecmp(end - 3, "jar", 3) == 0) {
357 /* save classpath entries as absolute pathnames */
362 if (*start != '/') { /* XXX fix me for win32 */
364 cwdlen = strlen(cwd) + strlen("/");
367 /* allocate memory for filename and fill it */
369 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
373 strcpy(filename, cwd);
374 strcat(filename, "/");
375 strncat(filename, start, filenamelen);
377 /* add cwd length to file length */
378 filenamelen += cwdlen;
381 strncpy(filename, start, filenamelen);
382 filename[filenamelen] = '\0';
388 #if defined(USE_ZLIB)
389 unzFile uf = unzOpen(filename);
392 cpi = NEW(classpath_info);
393 cpi->type = CLASSPATH_ARCHIVE;
396 cpi->path = filename;
397 cpi->pathlen = filenamelen;
401 throw_cacao_exception_exit(string_java_lang_InternalError,
402 "zip/jar files not supported");
406 cpi = NEW(classpath_info);
407 cpi->type = CLASSPATH_PATH;
410 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
411 filename[filenamelen] = '/';
412 filename[filenamelen + 1] = '\0';
416 cpi->path = filename;
417 cpi->pathlen = filenamelen;
420 /* attach current classpath entry */
423 if (!classpath_entries)
424 classpath_entries = cpi;
432 /* goto next classpath entry, skip ':' delimiter */
444 void create_all_classes()
448 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
449 #if defined(USE_ZLIB)
450 if (cpi->type == CLASSPATH_ARCHIVE) {
454 s = (unz_s *) cpi->uf;
455 ce = s->cacao_dir_list;
458 (void) class_new(ce->name);
464 #if defined(USE_ZLIB)
471 /* suck_start ******************************************************************
473 Returns true if classbuffer is already loaded or a file for the
474 specified class has succussfully been read in. All directories of
475 the searchpath are used to find the classfile (<classname>.class).
476 Returns false if no classfile is found and writes an error message.
478 *******************************************************************************/
480 classbuffer *suck_start(classinfo *c)
492 /* initialize return value */
497 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
498 filename = MNEW(char, filenamelen);
500 utf_sprint(filename, c->name);
501 strcat(filename, ".class");
503 /* walk through all classpath entries */
505 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
506 #if defined(USE_ZLIB)
507 if (cpi->type == CLASSPATH_ARCHIVE) {
509 #if defined(USE_THREADS)
510 /* enter a monitor on zip/jar archives */
512 builtin_monitorenter((java_objectheader *) cpi);
515 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
516 unz_file_info file_info;
518 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
519 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
520 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
521 cb = NEW(classbuffer);
523 cb->size = file_info.uncompressed_size;
524 cb->data = MNEW(u1, cb->size);
525 cb->pos = cb->data - 1;
527 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
529 if (len != cb->size) {
531 log_text("Error while unzipping");
538 log_text("Error while opening file in archive");
542 log_text("Error while retrieving fileinfo");
545 unzCloseCurrentFile(cpi->uf);
547 #if defined(USE_THREADS)
548 /* leave the monitor */
550 builtin_monitorexit((java_objectheader *) cpi);
554 #endif /* defined(USE_ZLIB) */
556 path = MNEW(char, cpi->pathlen + filenamelen);
557 strcpy(path, cpi->path);
558 strcat(path, filename);
560 classfile = fopen(path, "r");
562 if (classfile) { /* file exists */
563 if (!stat(path, &buffer)) { /* read classfile data */
564 cb = NEW(classbuffer);
566 cb->size = buffer.st_size;
567 cb->data = MNEW(u1, cb->size);
568 cb->pos = cb->data - 1;
570 /* read class data */
571 len = fread(cb->data, 1, cb->size, classfile);
573 if (len != buffer.st_size) {
575 /* if (ferror(classfile)) { */
584 MFREE(path, char, cpi->pathlen + filenamelen);
585 #if defined(USE_ZLIB)
592 dolog("Warning: Can not open class file '%s'", filename);
594 MFREE(filename, char, filenamelen);
600 /************************** function suck_stop *********************************
602 frees memory for buffer with classfile data.
603 Caution: this function may only be called if buffer has been allocated
604 by suck_start with reading a file
606 *******************************************************************************/
608 void suck_stop(classbuffer *cb)
612 MFREE(cb->data, u1, cb->size);
613 FREE(cb, classbuffer);
617 /******************************************************************************/
618 /******************* Some support functions ***********************************/
619 /******************************************************************************/
621 void fprintflags (FILE *fp, u2 f)
623 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
624 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
625 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
626 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
627 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
628 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
629 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
630 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
631 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
632 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
633 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
637 /********** internal function: printflags (only for debugging) ***************/
639 void printflags(u2 f)
641 fprintflags(stdout,f);
645 /********************** Function: skipattributebody ****************************
647 skips an attribute after the 16 bit reference to attribute_name has already
650 *******************************************************************************/
652 static bool skipattributebody(classbuffer *cb)
656 if (!check_classbuffer_size(cb, 4))
661 if (!check_classbuffer_size(cb, len))
664 skip_nbytes(cb, len);
670 /************************* Function: skipattributes ****************************
672 skips num attribute structures
674 *******************************************************************************/
676 static bool skipattributes(classbuffer *cb, u4 num)
681 for (i = 0; i < num; i++) {
682 if (!check_classbuffer_size(cb, 2 + 4))
688 if (!check_classbuffer_size(cb, len))
691 skip_nbytes(cb, len);
698 /******************** function:: class_getconstant *****************************
700 retrieves the value at position 'pos' of the constantpool of a class
701 if the type of the value is other than 'ctype' the system is stopped
703 *******************************************************************************/
705 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
707 /* check index and type of constantpool entry */
708 /* (pos == 0 is caught by type comparison) */
709 if (pos >= c->cpcount || c->cptags[pos] != ctype) {
710 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
714 return c->cpinfos[pos];
718 /******************** function: innerclass_getconstant ************************
720 like class_getconstant, but if cptags is ZERO null is returned
722 *******************************************************************************/
724 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
726 /* invalid position in constantpool */
727 if (pos >= c->cpcount) {
728 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
732 /* constantpool entry of type 0 */
736 /* check type of constantpool entry */
737 if (c->cptags[pos] != ctype) {
738 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
742 return c->cpinfos[pos];
746 /********************* Function: class_constanttype ****************************
748 Determines the type of a class entry in the ConstantPool
750 *******************************************************************************/
752 u4 class_constanttype(classinfo *c, u4 pos)
754 if (pos <= 0 || pos >= c->cpcount) {
755 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
759 return c->cptags[pos];
763 /* load_constantpool ***********************************************************
765 Loads the constantpool of a class, the entries are transformed into
766 a simpler format by resolving references (a detailed overview of
767 the compact structures can be found in global.h).
769 *******************************************************************************/
771 static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
774 /* The following structures are used to save information which cannot be
775 processed during the first pass. After the complete constantpool has
776 been traversed the references can be resolved.
777 (only in specific order) */
779 /* CONSTANT_Class entries */
780 typedef struct forward_class {
781 struct forward_class *next;
786 /* CONSTANT_String */
787 typedef struct forward_string {
788 struct forward_string *next;
793 /* CONSTANT_NameAndType */
794 typedef struct forward_nameandtype {
795 struct forward_nameandtype *next;
799 } forward_nameandtype;
801 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
802 typedef struct forward_fieldmethint {
803 struct forward_fieldmethint *next;
807 u2 nameandtype_index;
808 } forward_fieldmethint;
814 forward_class *forward_classes = NULL;
815 forward_string *forward_strings = NULL;
816 forward_nameandtype *forward_nameandtypes = NULL;
817 forward_fieldmethint *forward_fieldmethints = NULL;
821 forward_nameandtype *nfn;
822 forward_fieldmethint *nff;
830 /* number of entries in the constant_pool table plus one */
831 if (!check_classbuffer_size(cb, 2))
834 cpcount = c->cpcount = suck_u2(cb);
836 /* allocate memory */
837 cptags = c->cptags = MNEW(u1, cpcount);
838 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
841 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
845 #if defined(STATISTICS)
847 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
850 /* initialize constantpool */
851 for (idx = 0; idx < cpcount; idx++) {
852 cptags[idx] = CONSTANT_UNUSED;
857 /******* first pass *******/
858 /* entries which cannot be resolved now are written into
859 temporary structures and traversed again later */
862 while (idx < cpcount) {
865 /* get constant type */
866 if (!check_classbuffer_size(cb, 1))
873 nfc = NEW(forward_class);
875 nfc->next = forward_classes;
876 forward_classes = nfc;
878 nfc->thisindex = idx;
879 /* reference to CONSTANT_NameAndType */
880 if (!check_classbuffer_size(cb, 2))
883 nfc->name_index = suck_u2(cb);
888 case CONSTANT_String:
889 nfs = NEW(forward_string);
891 nfs->next = forward_strings;
892 forward_strings = nfs;
894 nfs->thisindex = idx;
896 /* reference to CONSTANT_Utf8_info with string characters */
897 if (!check_classbuffer_size(cb, 2))
900 nfs->string_index = suck_u2(cb);
905 case CONSTANT_NameAndType:
906 nfn = NEW(forward_nameandtype);
908 nfn->next = forward_nameandtypes;
909 forward_nameandtypes = nfn;
911 nfn->thisindex = idx;
913 if (!check_classbuffer_size(cb, 2 + 2))
916 /* reference to CONSTANT_Utf8_info containing simple name */
917 nfn->name_index = suck_u2(cb);
919 /* reference to CONSTANT_Utf8_info containing field or method
921 nfn->sig_index = suck_u2(cb);
926 case CONSTANT_Fieldref:
927 case CONSTANT_Methodref:
928 case CONSTANT_InterfaceMethodref:
929 nff = NEW(forward_fieldmethint);
931 nff->next = forward_fieldmethints;
932 forward_fieldmethints = nff;
934 nff->thisindex = idx;
938 if (!check_classbuffer_size(cb, 2 + 2))
941 /* class or interface type that contains the declaration of the
943 nff->class_index = suck_u2(cb);
945 /* name and descriptor of the field or method */
946 nff->nameandtype_index = suck_u2(cb);
951 case CONSTANT_Integer: {
952 constant_integer *ci = NEW(constant_integer);
954 #if defined(STATISTICS)
956 count_const_pool_len += sizeof(constant_integer);
959 if (!check_classbuffer_size(cb, 4))
962 ci->value = suck_s4(cb);
963 cptags[idx] = CONSTANT_Integer;
970 case CONSTANT_Float: {
971 constant_float *cf = NEW(constant_float);
973 #if defined(STATISTICS)
975 count_const_pool_len += sizeof(constant_float);
978 if (!check_classbuffer_size(cb, 4))
981 cf->value = suck_float(cb);
982 cptags[idx] = CONSTANT_Float;
989 case CONSTANT_Long: {
990 constant_long *cl = NEW(constant_long);
992 #if defined(STATISTICS)
994 count_const_pool_len += sizeof(constant_long);
997 if (!check_classbuffer_size(cb, 8))
1000 cl->value = suck_s8(cb);
1001 cptags[idx] = CONSTANT_Long;
1004 if (idx > cpcount) {
1006 new_classformaterror(c, "Invalid constant pool entry");
1012 case CONSTANT_Double: {
1013 constant_double *cd = NEW(constant_double);
1015 #if defined(STATISTICS)
1017 count_const_pool_len += sizeof(constant_double);
1020 if (!check_classbuffer_size(cb, 8))
1023 cd->value = suck_double(cb);
1024 cptags[idx] = CONSTANT_Double;
1027 if (idx > cpcount) {
1029 new_classformaterror(c, "Invalid constant pool entry");
1035 case CONSTANT_Utf8: {
1038 /* number of bytes in the bytes array (not string-length) */
1039 if (!check_classbuffer_size(cb, 2))
1042 length = suck_u2(cb);
1043 cptags[idx] = CONSTANT_Utf8;
1045 /* validate the string */
1046 if (!check_classbuffer_size(cb, length))
1050 !is_valid_utf((char *) (cb->pos + 1),
1051 (char *) (cb->pos + 1 + length))) {
1052 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1053 panic("Invalid UTF-8 string");
1055 /* insert utf-string into the utf-symboltable */
1056 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1058 /* skip bytes of the string (buffer size check above) */
1059 skip_nbytes(cb, length);
1066 new_classformaterror(c, "Illegal constant pool type");
1071 /* add all class references to the descriptor_pool */
1072 for (nfc=forward_classes; nfc; nfc=nfc->next) {
1073 utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
1074 if (!descriptor_pool_add_class(descpool,name))
1077 /* add all descriptors in NameAndTypes to the descriptor_pool */
1078 for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
1079 utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
1080 if (!descriptor_pool_add(descpool,desc,NULL))
1084 /* resolve entries in temporary structures */
1086 while (forward_classes) {
1088 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1090 if (opt_verify && !is_valid_name_utf(name))
1091 panic("Class reference with invalid name");
1093 cptags[forward_classes->thisindex] = CONSTANT_Class;
1094 /* retrieve class from class-table */
1097 tc = class_new_intern(name);
1099 if (!load_class_from_classloader(tc, c->classloader))
1102 /* link the class later, because we cannot link the class currently
1104 list_addfirst(&unlinkedclasses, tc);
1106 cpinfos[forward_classes->thisindex] = tc;
1109 cpinfos[forward_classes->thisindex] = class_new(name);
1112 nfc = forward_classes;
1113 forward_classes = forward_classes->next;
1114 FREE(nfc, forward_class);
1117 while (forward_strings) {
1119 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1121 /* resolve utf-string */
1122 cptags[forward_strings->thisindex] = CONSTANT_String;
1123 cpinfos[forward_strings->thisindex] = text;
1125 nfs = forward_strings;
1126 forward_strings = forward_strings->next;
1127 FREE(nfs, forward_string);
1130 while (forward_nameandtypes) {
1131 constant_nameandtype *cn = NEW(constant_nameandtype);
1133 #if defined(STATISTICS)
1135 count_const_pool_len += sizeof(constant_nameandtype);
1138 /* resolve simple name and descriptor */
1139 cn->name = class_getconstant(c,
1140 forward_nameandtypes->name_index,
1143 cn->descriptor = class_getconstant(c,
1144 forward_nameandtypes->sig_index,
1149 if (!is_valid_name_utf(cn->name)) {
1151 new_classformaterror(c,
1152 "Illegal Field name \"%s\"",
1158 /* disallow referencing <clinit> among others */
1159 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1161 new_exception_utfmessage(string_java_lang_InternalError,
1167 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1168 cpinfos[forward_nameandtypes->thisindex] = cn;
1170 nfn = forward_nameandtypes;
1171 forward_nameandtypes = forward_nameandtypes->next;
1172 FREE(nfn, forward_nameandtype);
1175 while (forward_fieldmethints) {
1176 constant_nameandtype *nat;
1177 constant_FMIref *fmi = NEW(constant_FMIref);
1179 #if defined(STATISTICS)
1181 count_const_pool_len += sizeof(constant_FMIref);
1183 /* resolve simple name and descriptor */
1184 nat = class_getconstant(c,
1185 forward_fieldmethints->nameandtype_index,
1186 CONSTANT_NameAndType);
1188 fmi->class = class_getconstant(c,
1189 forward_fieldmethints->class_index,
1191 fmi->name = nat->name;
1192 fmi->descriptor = nat->descriptor;
1194 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1195 cpinfos[forward_fieldmethints->thisindex] = fmi;
1197 nff = forward_fieldmethints;
1198 forward_fieldmethints = forward_fieldmethints->next;
1199 FREE(nff, forward_fieldmethint);
1202 /* everything was ok */
1208 /* load_field ******************************************************************
1210 Load everything about a class field from the class file and fill a
1211 'fieldinfo' structure. For static fields, space in the data segment
1214 *******************************************************************************/
1216 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1218 static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
1223 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1228 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1231 f->flags = suck_u2(cb);
1233 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1237 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1240 f->parseddesc = NULL;
1241 if (!descriptor_pool_add(descpool,u,NULL))
1246 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1247 *exceptionptr = new_classformaterror(c,
1248 "Illegal Field name \"%s\"",
1253 /* check flag consistency */
1254 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1256 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1257 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1259 new_classformaterror(c,
1260 "Illegal field modifiers: 0x%X",
1265 if (c->flags & ACC_INTERFACE) {
1266 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1267 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1268 f->flags & ACC_TRANSIENT) {
1270 new_classformaterror(c,
1271 "Illegal field modifiers: 0x%X",
1278 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1279 f->offset = 0; /* offset from start of object */
1284 case TYPE_INT: f->value.i = 0; break;
1285 case TYPE_FLOAT: f->value.f = 0.0; break;
1286 case TYPE_DOUBLE: f->value.d = 0.0; break;
1287 case TYPE_ADDRESS: f->value.a = NULL; break;
1290 f->value.l = 0; break;
1292 f->value.l.low = 0; f->value.l.high = 0; break;
1296 /* read attributes */
1297 if (!check_classbuffer_size(cb, 2))
1300 attrnum = suck_u2(cb);
1301 for (i = 0; i < attrnum; i++) {
1302 if (!check_classbuffer_size(cb, 2))
1305 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1308 if (u == utf_ConstantValue) {
1309 if (!check_classbuffer_size(cb, 4 + 2))
1312 /* check attribute length */
1313 if (suck_u4(cb) != 2) {
1315 new_classformaterror(c, "Wrong size for VALUE attribute");
1319 /* constant value attribute */
1320 if (pindex != field_load_NOVALUE) {
1322 new_classformaterror(c,
1323 "Multiple ConstantValue attributes");
1327 /* index of value in constantpool */
1328 pindex = suck_u2(cb);
1330 /* initialize field with value from constantpool */
1333 constant_integer *ci;
1335 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1338 f->value.i = ci->value;
1345 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1348 f->value.l = cl->value;
1355 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1358 f->value.f = cf->value;
1363 constant_double *cd;
1365 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1368 f->value.d = cd->value;
1373 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1376 /* create javastring from compressed utf8-string */
1377 f->value.a = literalstring_new(u);
1381 log_text("Invalid Constant - Type");
1385 /* unknown attribute */
1386 if (!skipattributebody(cb))
1391 /* everything was ok */
1397 /* load_method *****************************************************************
1399 Loads a method from the class file and fills an existing
1400 'methodinfo' structure. For native methods, the function pointer
1401 field is set to the real function pointer, for JavaVM methods a
1402 pointer to the compiler is used preliminarily.
1404 *******************************************************************************/
1406 static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
1417 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1418 initObjectLock(&m->header);
1423 count_all_methods++;
1426 m->thrownexceptionscount = 0;
1427 m->linenumbercount = 0;
1430 m->nativelyoverloaded = false;
1432 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1435 m->flags = suck_u2(cb);
1437 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1441 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1444 m->parseddesc = NULL;
1445 if (!descriptor_pool_add(descpool,u,&argcount))
1449 if (!is_valid_name_utf(m->name))
1450 panic("Method with invalid name");
1452 if (m->name->text[0] == '<'
1453 && m->name != utf_init && m->name != utf_clinit)
1454 panic("Method with invalid special name");
1457 if (!(m->flags & ACC_STATIC))
1458 argcount++; /* count the 'this' argument */
1461 if (argcount > 255) {
1463 new_classformaterror(c, "Too many arguments in signature");
1467 /* check flag consistency */
1468 if (m->name != utf_clinit) {
1469 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1471 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1473 new_classformaterror(c,
1474 "Illegal method modifiers: 0x%X",
1479 if (m->flags & ACC_ABSTRACT) {
1480 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1481 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1483 new_classformaterror(c,
1484 "Illegal method modifiers: 0x%X",
1490 if (c->flags & ACC_INTERFACE) {
1491 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1493 new_classformaterror(c,
1494 "Illegal method modifiers: 0x%X",
1500 if (m->name == utf_init) {
1501 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1502 ACC_NATIVE | ACC_ABSTRACT))
1503 panic("Instance initialization method has invalid flags set");
1509 m->basicblockcount = 0;
1510 m->basicblocks = NULL;
1511 m->basicblockindex = NULL;
1512 m->instructioncount = 0;
1513 m->instructions = NULL;
1516 m->exceptiontable = NULL;
1517 m->stubroutine = NULL;
1519 m->entrypoint = NULL;
1520 m->methodUsed = NOTUSED;
1523 m->subRedefsUsed = 0;
1527 if (!check_classbuffer_size(cb, 2))
1530 attrnum = suck_u2(cb);
1531 for (i = 0; i < attrnum; i++) {
1534 if (!check_classbuffer_size(cb, 2))
1537 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1540 if (aname == utf_Code) {
1541 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1543 new_classformaterror(c,
1544 "Code attribute in native or abstract methods");
1551 new_classformaterror(c, "Multiple Code attributes");
1556 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1560 m->maxstack = suck_u2(cb);
1561 m->maxlocals = suck_u2(cb);
1563 if (m->maxlocals < argcount) {
1565 new_classformaterror(c, "Arguments can't fit into locals");
1570 if (!check_classbuffer_size(cb, 4))
1573 m->jcodelength = suck_u4(cb);
1575 if (m->jcodelength == 0) {
1577 new_classformaterror(c, "Code of a method has length 0");
1582 if (m->jcodelength > 65535) {
1584 new_classformaterror(c,
1585 "Code of a method longer than 65535 bytes");
1590 if (!check_classbuffer_size(cb, m->jcodelength))
1593 m->jcode = MNEW(u1, m->jcodelength);
1594 suck_nbytes(m->jcode, cb, m->jcodelength);
1596 if (!check_classbuffer_size(cb, 2))
1599 m->exceptiontablelength = suck_u2(cb);
1600 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1603 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1605 #if defined(STATISTICS)
1607 count_vmcode_len += m->jcodelength + 18;
1608 count_extable_len += 8 * m->exceptiontablelength;
1612 for (j = 0; j < m->exceptiontablelength; j++) {
1614 m->exceptiontable[j].startpc = suck_u2(cb);
1615 m->exceptiontable[j].endpc = suck_u2(cb);
1616 m->exceptiontable[j].handlerpc = suck_u2(cb);
1620 m->exceptiontable[j].catchtype = NULL;
1623 if (!(m->exceptiontable[j].catchtype =
1624 class_getconstant(c, idx, CONSTANT_Class)))
1629 if (!check_classbuffer_size(cb, 2))
1632 codeattrnum = suck_u2(cb);
1634 for (; codeattrnum > 0; codeattrnum--) {
1637 if (!check_classbuffer_size(cb, 2))
1640 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1643 if (caname == utf_LineNumberTable) {
1646 if (!check_classbuffer_size(cb, 4 + 2))
1650 m->linenumbercount = suck_u2(cb);
1652 if (!check_classbuffer_size(cb,
1653 (2 + 2) * m->linenumbercount))
1656 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1658 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1659 m->linenumbers[lncid].start_pc = suck_u2(cb);
1660 m->linenumbers[lncid].line_number = suck_u2(cb);
1664 if (!skipattributes(cb, codeattrnum))
1670 if (!skipattributebody(cb))
1675 } else if (aname == utf_Exceptions) {
1678 if (m->thrownexceptions) {
1680 new_classformaterror(c, "Multiple Exceptions attributes");
1684 if (!check_classbuffer_size(cb, 4 + 2))
1687 suck_u4(cb); /* length */
1688 m->thrownexceptionscount = suck_u2(cb);
1690 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1693 m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1695 for (j = 0; j < m->thrownexceptionscount; j++) {
1696 if (!((m->thrownexceptions)[j] =
1697 class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1702 if (!skipattributebody(cb))
1707 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1708 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1713 /* everything was ok */
1719 /* load_attribute **************************************************************
1721 Read attributes from classfile.
1723 *******************************************************************************/
1725 static bool load_attributes(classbuffer *cb, u4 num)
1733 for (i = 0; i < num; i++) {
1734 /* retrieve attribute name */
1735 if (!check_classbuffer_size(cb, 2))
1738 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1741 if (aname == utf_InnerClasses) {
1742 /* innerclasses attribute */
1743 if (c->innerclass) {
1745 new_classformaterror(c, "Multiple InnerClasses attributes");
1749 if (!check_classbuffer_size(cb, 4 + 2))
1752 /* skip attribute length */
1755 /* number of records */
1756 c->innerclasscount = suck_u2(cb);
1758 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1761 /* allocate memory for innerclass structure */
1762 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1764 for (j = 0; j < c->innerclasscount; j++) {
1765 /* The innerclass structure contains a class with an encoded
1766 name, its defining scope, its simple name and a bitmask of
1767 the access flags. If an inner class is not a member, its
1768 outer_class is NULL, if a class is anonymous, its name is
1771 innerclassinfo *info = c->innerclass + j;
1774 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1776 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1778 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1779 info->flags = suck_u2(cb);
1782 } else if (aname == utf_SourceFile) {
1783 if (!check_classbuffer_size(cb, 4 + 2))
1786 if (suck_u4(cb) != 2) {
1788 new_classformaterror(c, "Wrong size for VALUE attribute");
1792 if (c->sourcefile) {
1794 new_classformaterror(c, "Multiple SourceFile attributes");
1798 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1802 /* unknown attribute */
1803 if (!skipattributebody(cb))
1812 /* load_class_from_classloader *************************************************
1816 *******************************************************************************/
1818 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
1822 /* if other class loader than bootstrap, call it */
1827 lc = class_resolveclassmethod(cl->vftbl->class,
1829 utf_java_lang_String__java_lang_Class,
1830 class_java_lang_Object,
1836 r = (classinfo *) asm_calljavafunction(lc,
1838 javastring_new(c->name),
1844 return load_class_bootstrap(c);
1849 /* load_class_bootstrap ********************************************************
1853 *******************************************************************************/
1855 classinfo *load_class_bootstrap(classinfo *c)
1860 #if defined(USE_THREADS)
1861 /* enter a monitor on the class */
1863 builtin_monitorenter((java_objectheader *) c);
1866 /* maybe the class is already loaded */
1869 #if defined(USE_THREADS)
1870 builtin_monitorexit((java_objectheader *) c);
1876 #if defined(STATISTICS)
1879 if (getcompilingtime)
1880 compilingtime_stop();
1883 loadingtime_start();
1886 /* load classdata, throw exception on error */
1888 if ((cb = suck_start(c)) == NULL) {
1889 /* this means, the classpath was not set properly */
1890 if (c->name == utf_java_lang_Object)
1891 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1892 "java/lang/Object");
1895 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1898 #if defined(USE_THREADS)
1899 builtin_monitorexit((java_objectheader *) c);
1905 /* load the class from the buffer */
1907 r = load_class_from_classbuffer(cb);
1909 /* if return value is NULL, we had a problem and the class is not loaded */
1913 /* now free the allocated memory, otherwise we could ran into a DOS */
1920 #if defined(STATISTICS)
1926 if (getcompilingtime)
1927 compilingtime_start();
1930 #if defined(USE_THREADS)
1931 /* leave the monitor */
1933 builtin_monitorexit((java_objectheader *) c);
1940 /* load_class_from_classbuffer *************************************************
1942 Loads everything interesting about a class from the class file. The
1943 'classinfo' structure must have been allocated previously.
1945 The super class and the interfaces implemented by this class need
1946 not be loaded. The link is set later by the function 'class_link'.
1948 The loaded class is removed from the list 'unloadedclasses' and
1949 added to the list 'unlinkedclasses'.
1951 *******************************************************************************/
1953 classinfo *load_class_from_classbuffer(classbuffer *cb)
1960 descriptor_pool *descpool;
1961 char msg[MAXLOGTEXT]; /* maybe we get an exception */
1962 #if defined(STATISTICS)
1967 /* get the classbuffer's class */
1970 /* maybe the class is already loaded */
1974 #if defined(STATISTICS)
1976 count_class_loads++;
1979 /* output for debugging purposes */
1981 log_message_class("Loading class: ", c);
1983 /* mark start of dump memory area */
1984 dumpsize = dump_size();
1986 /* class is somewhat loaded */
1989 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1990 goto return_exception;
1992 /* check signature */
1993 if (suck_u4(cb) != MAGIC) {
1994 *exceptionptr = new_classformaterror(c, "Bad magic number");
1996 goto return_exception;
2003 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2005 new_unsupportedclassversionerror(c,
2006 "Unsupported major.minor version %d.%d",
2009 goto return_exception;
2012 /* create a new descriptor pool */
2013 descpool = descriptor_pool_new(c);
2015 /* load the constant pool */
2016 if (!load_constantpool(cb,descpool))
2017 goto return_exception;
2020 c->erroneous_state = 0;
2021 c->initializing_thread = 0;
2023 c->classUsed = NOTUSED; /* not used initially CO-RT */
2027 if (!check_classbuffer_size(cb, 2))
2028 goto return_exception;
2030 c->flags = suck_u2(cb);
2031 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2033 /* check ACC flags consistency */
2034 if (c->flags & ACC_INTERFACE) {
2035 if (!(c->flags & ACC_ABSTRACT)) {
2036 /* We work around this because interfaces in JDK 1.1 are
2037 * not declared abstract. */
2039 c->flags |= ACC_ABSTRACT;
2040 /* panic("Interface class not declared abstract"); */
2043 if (c->flags & ACC_FINAL) {
2045 new_classformaterror(c,
2046 "Illegal class modifiers: 0x%X", c->flags);
2048 goto return_exception;
2051 if (c->flags & ACC_SUPER) {
2052 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2056 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2058 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2060 goto return_exception;
2063 if (!check_classbuffer_size(cb, 2 + 2))
2064 goto return_exception;
2068 if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2069 goto return_exception;
2072 utf_sprint(msg, c->name);
2073 sprintf(msg + strlen(msg), " (wrong name: ");
2074 utf_sprint(msg + strlen(msg), tc->name);
2075 sprintf(msg + strlen(msg), ")");
2078 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2080 goto return_exception;
2083 /* retrieve superclass */
2084 if ((i = suck_u2(cb))) {
2085 if (!(c->super.cls = class_getconstant(c, i, CONSTANT_Class)))
2086 goto return_exception;
2088 /* java.lang.Object may not have a super class. */
2089 if (c->name == utf_java_lang_Object) {
2091 new_exception_message(string_java_lang_ClassFormatError,
2092 "java.lang.Object with superclass");
2094 goto return_exception;
2097 /* Interfaces must have java.lang.Object as super class. */
2098 if ((c->flags & ACC_INTERFACE) &&
2099 c->super.cls->name != utf_java_lang_Object) {
2101 new_exception_message(string_java_lang_ClassFormatError,
2102 "Interfaces must have java.lang.Object as superclass");
2104 goto return_exception;
2108 c->super.any = NULL;
2110 /* This is only allowed for java.lang.Object. */
2111 if (c->name != utf_java_lang_Object) {
2112 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2114 goto return_exception;
2118 /* retrieve interfaces */
2119 if (!check_classbuffer_size(cb, 2))
2120 goto return_exception;
2122 c->interfacescount = suck_u2(cb);
2124 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2125 goto return_exception;
2127 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2128 for (i = 0; i < c->interfacescount; i++) {
2129 if (!(c->interfaces[i].cls = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2130 goto return_exception;
2134 if (!check_classbuffer_size(cb, 2))
2135 goto return_exception;
2137 c->fieldscount = suck_u2(cb);
2138 c->fields = GCNEW(fieldinfo, c->fieldscount);
2139 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2140 for (i = 0; i < c->fieldscount; i++) {
2141 if (!load_field(cb, &(c->fields[i]),descpool))
2142 goto return_exception;
2146 if (!check_classbuffer_size(cb, 2))
2147 goto return_exception;
2149 c->methodscount = suck_u2(cb);
2150 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2151 c->methods = MNEW(methodinfo, c->methodscount);
2152 for (i = 0; i < c->methodscount; i++) {
2153 if (!load_method(cb, &(c->methods[i]),descpool))
2154 goto return_exception;
2157 /* create the class reference table */
2158 c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
2160 /* allocate space for the parsed descriptors */
2161 descriptor_pool_alloc_parsed_descriptors(descpool);
2162 c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
2164 #if defined(STATISTICS)
2166 descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
2167 count_classref_len += classrefsize;
2168 count_parsed_desc_len += descsize;
2172 /* parse the loaded descriptors */
2173 for (i=0; i<c->cpcount; ++i) {
2174 constant_FMIref *fmi;
2176 switch (c->cptags[i]) {
2177 case CONSTANT_Class:
2178 /* XXX set classref */
2180 case CONSTANT_Fieldref:
2181 fmi = (constant_FMIref *)c->cpinfos[i];
2182 fmi->parseddesc.fd =
2183 descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
2184 if (!fmi->parseddesc.fd)
2185 goto return_exception;
2186 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2188 case CONSTANT_Methodref:
2189 case CONSTANT_InterfaceMethodref:
2190 fmi = (constant_FMIref *)c->cpinfos[i];
2191 fmi->parseddesc.md =
2192 descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
2193 if (!fmi->parseddesc.md)
2194 goto return_exception;
2195 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2199 for (i = 0; i < c->fieldscount; i++) {
2200 c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
2201 if (!c->fields[i].parseddesc)
2202 goto return_exception;
2204 for (i = 0; i < c->methodscount; i++) {
2205 c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor);
2206 if (!c->methods[i].parseddesc)
2207 goto return_exception;
2210 /* Check if all fields and methods can be uniquely
2211 * identified by (name,descriptor). */
2213 /* We use a hash table here to avoid making the
2214 * average case quadratic in # of methods, fields.
2216 static int shift = 0;
2218 u2 *next; /* for chaining colliding hash entries */
2224 /* Allocate hashtable */
2225 len = c->methodscount;
2226 if (len < c->fieldscount) len = c->fieldscount;
2228 hashtab = MNEW(u2,(hashlen + len));
2229 next = hashtab + hashlen;
2231 /* Determine bitshift (to get good hash values) */
2241 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2243 for (i = 0; i < c->fieldscount; ++i) {
2244 fieldinfo *fi = c->fields + i;
2246 /* It's ok if we lose bits here */
2247 index = ((((size_t) fi->name) +
2248 ((size_t) fi->descriptor)) >> shift) % hashlen;
2250 if ((old = hashtab[index])) {
2254 if (c->fields[old].name == fi->name &&
2255 c->fields[old].descriptor == fi->descriptor) {
2257 new_classformaterror(c,
2258 "Repetitive field name/signature");
2260 goto return_exception;
2262 } while ((old = next[old]));
2264 hashtab[index] = i + 1;
2268 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2270 for (i = 0; i < c->methodscount; ++i) {
2271 methodinfo *mi = c->methods + i;
2273 /* It's ok if we lose bits here */
2274 index = ((((size_t) mi->name) +
2275 ((size_t) mi->descriptor)) >> shift) % hashlen;
2279 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2280 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2284 if ((old = hashtab[index])) {
2288 if (c->methods[old].name == mi->name &&
2289 c->methods[old].descriptor == mi->descriptor) {
2291 new_classformaterror(c,
2292 "Repetitive method name/signature");
2294 goto return_exception;
2296 } while ((old = next[old]));
2298 hashtab[index] = i + 1;
2301 MFREE(hashtab, u2, (hashlen + len));
2304 #if defined(STATISTICS)
2306 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2307 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2308 count_class_infos += sizeof(methodinfo) * c->methodscount;
2312 /* load attribute structures */
2313 if (!check_classbuffer_size(cb, 2))
2314 goto return_exception;
2316 if (!load_attributes(cb, suck_u2(cb)))
2317 goto return_exception;
2320 /* Pre java 1.5 version don't check this. This implementation is like
2321 java 1.5 do it: for class file version 45.3 we don't check it, older
2322 versions are checked.
2324 if ((ma == 45 && mi > 3) || ma > 45) {
2325 /* check if all data has been read */
2326 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2328 if (classdata_left > 0) {
2330 new_classformaterror(c, "Extra bytes at the end of class file");
2331 goto return_exception;
2336 /* release dump area */
2337 dump_release(dumpsize);
2340 log_message_class("Loading done class: ", c);
2345 /* release dump area */
2346 dump_release(dumpsize);
2348 /* an exception has been thrown */
2354 /******************* Function: class_new_array *********************************
2356 This function is called by class_new to setup an array class.
2358 *******************************************************************************/
2360 void class_new_array(classinfo *c)
2362 classinfo *comp = NULL;
2364 methoddesc *clonedesc;
2365 constant_classref *classrefs;
2368 /* Check array class name */
2369 namelen = c->name->blength;
2370 if (namelen < 2 || c->name->text[0] != '[')
2371 panic("Invalid array class name");
2373 /* Check the component type */
2374 switch (c->name->text[1]) {
2376 /* c is an array of arrays. We have to create the component class. */
2378 comp = class_new_intern(utf_new_intern(c->name->text + 1,
2380 load_class_from_classloader(comp, c->classloader);
2381 list_addfirst(&unlinkedclasses, comp);
2384 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2389 /* c is an array of objects. */
2390 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2391 panic("Invalid array class name");
2394 comp = class_new_intern(utf_new_intern(c->name->text + 2,
2396 load_class_from_classloader(comp, c->classloader);
2397 list_addfirst(&unlinkedclasses, comp);
2400 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2405 /* Setup the array class */
2406 c->super.cls = class_java_lang_Object;
2407 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2409 c->interfacescount = 2;
2410 c->interfaces = MNEW(classref_or_classinfo, 2);
2415 tc = class_java_lang_Cloneable;
2416 load_class_bootstrap(tc);
2417 list_addfirst(&unlinkedclasses, tc);
2418 c->interfaces[0].cls = tc;
2420 tc = class_java_io_Serializable;
2421 load_class_bootstrap(tc);
2422 list_addfirst(&unlinkedclasses, tc);
2423 c->interfaces[1].cls = tc;
2426 c->interfaces[0].cls = class_java_lang_Cloneable;
2427 c->interfaces[1].cls = class_java_io_Serializable;
2430 c->methodscount = 1;
2431 c->methods = MNEW(methodinfo, c->methodscount);
2433 classrefs = MNEW(constant_classref,1);
2434 CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
2436 clonedesc = NEW(methoddesc);
2437 clonedesc->returntype.type = TYPE_ADDRESS;
2438 clonedesc->returntype.classref = classrefs;
2439 clonedesc->returntype.arraydim = 0;
2440 clonedesc->paramcount = 0;
2441 clonedesc->paramslots = 0;
2444 MSET(clone, 0, methodinfo, 1);
2445 clone->flags = ACC_PUBLIC;
2446 clone->name = utf_new_char("clone");
2447 clone->descriptor = utf_void__java_lang_Object;
2448 clone->parseddesc = clonedesc;
2450 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2451 clone->monoPoly = MONO;
2453 /* XXX: field: length? */
2455 /* array classes are not loaded from class files */
2457 c->parseddescs = (u1*) clonedesc;
2458 c->parseddescsize = sizeof(methodinfo);
2459 c->classrefs = classrefs;
2460 c->classrefcount = 1;
2462 /* XXX insert class into the loaded class cache */
2466 /************************* Function: class_findfield ***************************
2468 Searches a 'classinfo' structure for a field having the given name and
2471 *******************************************************************************/
2473 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2477 for (i = 0; i < c->fieldscount; i++) {
2478 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2479 return &(c->fields[i]);
2482 panic("Can not find field given in CONSTANT_Fieldref");
2484 /* keep compiler happy */
2489 /****************** Function: class_resolvefield_int ***************************
2491 This is an internally used helper function. Do not use this directly.
2493 Tries to resolve a field having the given name and type.
2494 If the field cannot be resolved, NULL is returned.
2496 *******************************************************************************/
2498 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2503 /* search for field in class c */
2505 for (i = 0; i < c->fieldscount; i++) {
2506 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2507 return &(c->fields[i]);
2511 /* try superinterfaces recursively */
2513 for (i = 0; i < c->interfacescount; i++) {
2514 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2519 /* try superclass */
2522 return class_resolvefield_int(c->super.cls, name, desc);
2530 /********************* Function: class_resolvefield ***************************
2532 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2534 If the field cannot be resolved the return value is NULL. If EXCEPT is
2535 true *exceptionptr is set, too.
2537 *******************************************************************************/
2539 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2540 classinfo *referer, bool except)
2544 /* XXX resolve class c */
2545 /* XXX check access from REFERER to C */
2547 fi = class_resolvefield_int(c, name, desc);
2552 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2558 /* XXX check access rights */
2564 /* class_findmethod ************************************************************
2566 Searches a 'classinfo' structure for a method having the given name
2567 and descriptor. If descriptor is NULL, it is ignored.
2569 *******************************************************************************/
2571 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2576 for (i = 0; i < c->methodscount; i++) {
2577 m = &(c->methods[i]);
2579 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2587 /*********************** Function: class_fetchmethod **************************
2589 like class_findmethod, but aborts with an error if the method is not found
2591 *******************************************************************************/
2593 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2597 mi = class_findmethod(c, name, desc);
2600 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2601 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2602 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2603 panic("Method not found");
2610 /************************* Function: class_findmethod_approx ******************
2612 like class_findmethod but ignores the return value when comparing the
2615 *******************************************************************************/
2617 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2621 for (i = 0; i < c->methodscount; i++) {
2622 if (c->methods[i].name == name) {
2623 utf *meth_descr = c->methods[i].descriptor;
2627 return &(c->methods[i]);
2629 if (desc->blength <= meth_descr->blength) {
2630 /* current position in utf text */
2631 char *desc_utf_ptr = desc->text;
2632 char *meth_utf_ptr = meth_descr->text;
2633 /* points behind utf strings */
2634 char *desc_end = utf_end(desc);
2635 char *meth_end = utf_end(meth_descr);
2638 /* compare argument types */
2639 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2641 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2642 break; /* no match */
2645 return &(c->methods[i]); /* all parameter types equal */
2655 /***************** Function: class_resolvemethod_approx ***********************
2657 Searches a class and every super class for a method (without paying
2658 attention to the return value)
2660 *******************************************************************************/
2662 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2665 /* search for method (ignore returntype) */
2666 methodinfo *m = class_findmethod_approx(c, name, desc);
2669 /* search superclass */
2677 /* class_resolvemethod *********************************************************
2679 Searches a class and it's super classes for a method.
2681 *******************************************************************************/
2683 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2688 m = class_findmethod(c, name, desc);
2700 /* class_resolveinterfacemethod_intern *****************************************
2702 Internally used helper function. Do not use this directly.
2704 *******************************************************************************/
2706 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2707 utf *name, utf *desc)
2712 m = class_findmethod(c, name, desc);
2717 /* try the superinterfaces */
2719 for (i = 0; i < c->interfacescount; i++) {
2720 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2729 /* class_resolveinterfacemethod ************************************************
2731 Resolves a reference from REFERER to a method with NAME and DESC in
2734 If the method cannot be resolved the return value is NULL. If
2735 EXCEPT is true *exceptionptr is set, too.
2737 *******************************************************************************/
2739 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2740 classinfo *referer, bool except)
2744 /* XXX resolve class c */
2745 /* XXX check access from REFERER to C */
2747 if (!(c->flags & ACC_INTERFACE)) {
2750 new_exception(string_java_lang_IncompatibleClassChangeError);
2755 mi = class_resolveinterfacemethod_intern(c, name, desc);
2760 /* try class java.lang.Object */
2761 mi = class_findmethod(class_java_lang_Object, name, desc);
2768 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2774 /* class_resolveclassmethod ****************************************************
2776 Resolves a reference from REFERER to a method with NAME and DESC in
2779 If the method cannot be resolved the return value is NULL. If EXCEPT is
2780 true *exceptionptr is set, too.
2782 *******************************************************************************/
2784 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2785 classinfo *referer, bool except)
2793 /* XXX resolve class c */
2794 /* XXX check access from REFERER to C */
2796 /* if (c->flags & ACC_INTERFACE) { */
2798 /* *exceptionptr = */
2799 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
2803 /* try class c and its superclasses */
2808 mi = class_findmethod(cls, name, desc);
2813 cls = cls->super.cls;
2816 /* try the superinterfaces */
2818 for (i = 0; i < c->interfacescount; i++) {
2819 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2826 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2827 utf_strlen(desc) + strlen("0");
2829 msg = MNEW(char, msglen);
2831 utf_sprint(msg, c->name);
2833 utf_sprint(msg + strlen(msg), name);
2834 utf_sprint(msg + strlen(msg), desc);
2837 new_exception_message(string_java_lang_NoSuchMethodError, msg);
2839 MFREE(msg, char, msglen);
2845 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
2847 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
2852 /* XXX check access rights */
2858 /************************* Function: class_issubclass **************************
2860 Checks if sub is a descendant of super.
2862 *******************************************************************************/
2864 bool class_issubclass(classinfo *sub, classinfo *super)
2867 if (!sub) return false;
2868 if (sub == super) return true;
2869 sub = sub->super.cls;
2874 /****************** Initialization function for classes ******************
2876 In Java, every class can have a static initialization function. This
2877 function has to be called BEFORE calling other methods or accessing static
2880 *******************************************************************************/
2882 static classinfo *class_init_intern(classinfo *c);
2884 classinfo *class_init(classinfo *c)
2888 if (!makeinitializations)
2891 #if defined(USE_THREADS)
2892 /* enter a monitor on the class */
2894 builtin_monitorenter((java_objectheader *) c);
2897 /* maybe the class is already initalized or the current thread, which can
2898 pass the monitor, is currently initalizing this class */
2900 /* JOWENN: In future we need an additinal flag: initializationfailed,
2901 since further access to the class should cause a NoClassDefFound,
2902 if the static initializer failed once
2905 if (c->initialized || c->initializing) {
2906 #if defined(USE_THREADS)
2907 builtin_monitorexit((java_objectheader *) c);
2913 /* this initalizing run begins NOW */
2914 c->initializing = true;
2916 /* call the internal function */
2917 r = class_init_intern(c);
2919 /* if return value is not NULL everything was ok and the class is
2922 c->initialized = true;
2924 /* this initalizing run is done */
2925 c->initializing = false;
2927 #if defined(USE_THREADS)
2928 /* leave the monitor */
2930 builtin_monitorexit((java_objectheader *) c);
2937 /* this function MUST NOT be called directly, because of thread <clinit>
2940 static classinfo *class_init_intern(classinfo *c)
2944 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2948 /* maybe the class is not already loaded */
2950 if (!load_class_bootstrap(c))
2953 /* maybe the class is not already linked */
2958 #if defined(STATISTICS)
2960 count_class_inits++;
2963 /* initialize super class */
2966 if (!c->super.cls->initialized) {
2968 char logtext[MAXLOGTEXT];
2969 sprintf(logtext, "Initialize super class ");
2970 utf_sprint_classname(logtext + strlen(logtext), c->super.cls->name);
2971 sprintf(logtext + strlen(logtext), " from ");
2972 utf_sprint_classname(logtext + strlen(logtext), c->name);
2976 if (!class_init(c->super.cls))
2981 /* initialize interface classes */
2983 for (i = 0; i < c->interfacescount; i++) {
2984 if (!c->interfaces[i].cls->initialized) {
2986 char logtext[MAXLOGTEXT];
2987 sprintf(logtext, "Initialize interface class ");
2988 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i].cls->name);
2989 sprintf(logtext + strlen(logtext), " from ");
2990 utf_sprint_classname(logtext + strlen(logtext), c->name);
2994 if (!class_init(c->interfaces[i].cls))
2999 m = class_findmethod(c, utf_clinit, utf_void__void);
3003 char logtext[MAXLOGTEXT];
3004 sprintf(logtext, "Class ");
3005 utf_sprint_classname(logtext + strlen(logtext), c->name);
3006 sprintf(logtext + strlen(logtext), " has no static class initializer");
3013 /* Sun's and IBM's JVM don't care about the static flag */
3014 /* if (!(m->flags & ACC_STATIC)) { */
3015 /* panic("Class initializer is not static!"); */
3018 log_message_class("Starting static class initializer for class: ", c);
3020 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3025 /* now call the initializer */
3026 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3028 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3029 assert(blockInts == 0);
3033 /* we have an exception or error */
3034 if (*exceptionptr) {
3035 /* class is NOT initialized */
3036 c->initialized = false;
3038 /* is this an exception, than wrap it */
3039 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3040 java_objectheader *xptr;
3041 java_objectheader *cause;
3044 cause = *exceptionptr;
3046 /* clear exception, because we are calling jit code again */
3047 *exceptionptr = NULL;
3049 /* wrap the exception */
3051 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3052 (java_lang_Throwable *) cause);
3054 /* XXX should we exit here? */
3058 /* set new exception */
3059 *exceptionptr = xptr;
3066 log_message_class("Finished static class initializer for class: ", c);
3072 void class_showconstanti(classinfo *c, int ii)
3078 printf ("#%d: ", (int) i);
3080 switch (c->cptags [i]) {
3081 case CONSTANT_Class:
3082 printf("Classreference -> ");
3083 utf_display(((classinfo*)e)->name);
3086 case CONSTANT_Fieldref:
3087 printf("Fieldref -> "); goto displayFMIi;
3088 case CONSTANT_Methodref:
3089 printf("Methodref -> "); goto displayFMIi;
3090 case CONSTANT_InterfaceMethodref:
3091 printf("InterfaceMethod -> "); goto displayFMIi;
3094 constant_FMIref *fmi = e;
3095 utf_display(fmi->class->name);
3097 utf_display(fmi->name);
3099 utf_display(fmi->descriptor);
3103 case CONSTANT_String:
3104 printf("String -> ");
3107 case CONSTANT_Integer:
3108 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3110 case CONSTANT_Float:
3111 printf("Float -> %f", ((constant_float*)e)->value);
3113 case CONSTANT_Double:
3114 printf("Double -> %f", ((constant_double*)e)->value);
3118 u8 v = ((constant_long*)e)->value;
3120 printf("Long -> %ld", (long int) v);
3122 printf("Long -> HI: %ld, LO: %ld\n",
3123 (long int) v.high, (long int) v.low);
3127 case CONSTANT_NameAndType:
3129 constant_nameandtype *cnt = e;
3130 printf("NameAndType: ");
3131 utf_display(cnt->name);
3133 utf_display(cnt->descriptor);
3141 panic("Invalid type of ConstantPool-Entry");
3148 void class_showconstantpool (classinfo *c)
3153 printf ("---- dump of constant pool ----\n");
3155 for (i=0; i<c->cpcount; i++) {
3156 printf ("#%d: ", (int) i);
3158 e = c -> cpinfos [i];
3161 switch (c -> cptags [i]) {
3162 case CONSTANT_Class:
3163 printf ("Classreference -> ");
3164 utf_display ( ((classinfo*)e) -> name );
3167 case CONSTANT_Fieldref:
3168 printf ("Fieldref -> "); goto displayFMI;
3169 case CONSTANT_Methodref:
3170 printf ("Methodref -> "); goto displayFMI;
3171 case CONSTANT_InterfaceMethodref:
3172 printf ("InterfaceMethod -> "); goto displayFMI;
3175 constant_FMIref *fmi = e;
3176 utf_display ( fmi->class->name );
3178 utf_display ( fmi->name);
3180 utf_display ( fmi->descriptor );
3184 case CONSTANT_String:
3185 printf ("String -> ");
3188 case CONSTANT_Integer:
3189 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3191 case CONSTANT_Float:
3192 printf ("Float -> %f", ((constant_float*)e) -> value);
3194 case CONSTANT_Double:
3195 printf ("Double -> %f", ((constant_double*)e) -> value);
3199 u8 v = ((constant_long*)e) -> value;
3201 printf ("Long -> %ld", (long int) v);
3203 printf ("Long -> HI: %ld, LO: %ld\n",
3204 (long int) v.high, (long int) v.low);
3208 case CONSTANT_NameAndType:
3210 constant_nameandtype *cnt = e;
3211 printf ("NameAndType: ");
3212 utf_display (cnt->name);
3214 utf_display (cnt->descriptor);
3218 printf ("Utf8 -> ");
3222 panic ("Invalid type of ConstantPool-Entry");
3232 /********** Function: class_showmethods (debugging only) *************/
3234 void class_showmethods (classinfo *c)
3238 printf ("--------- Fields and Methods ----------------\n");
3239 printf ("Flags: "); printflags (c->flags); printf ("\n");
3241 printf ("This: "); utf_display (c->name); printf ("\n");
3243 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3245 printf ("Index: %d\n", c->index);
3247 printf ("interfaces:\n");
3248 for (i=0; i < c-> interfacescount; i++) {
3250 utf_display (c -> interfaces[i].cls -> name);
3251 printf (" (%d)\n", c->interfaces[i].cls -> index);
3254 printf ("fields:\n");
3255 for (i=0; i < c -> fieldscount; i++) {
3256 field_display (&(c -> fields[i]));
3259 printf ("methods:\n");
3260 for (i=0; i < c -> methodscount; i++) {
3261 methodinfo *m = &(c->methods[i]);
3262 if ( !(m->flags & ACC_STATIC))
3263 printf ("vftblindex: %d ", m->vftblindex);
3265 method_display ( m );
3269 printf ("Virtual function table:\n");
3270 for (i=0; i<c->vftbl->vftbllength; i++) {
3271 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3277 /******************************************************************************/
3278 /******************* General functions for the class loader *******************/
3279 /******************************************************************************/
3281 /******************** Function: loader_close ***********************************
3285 *******************************************************************************/
3292 for (slot = 0; slot < class_hash.size; slot++) {
3293 c = class_hash.ptr[slot];
3304 * These are local overrides for various environment variables in Emacs.
3305 * Please do not remove this and leave it at the end of the file, where
3306 * Emacs will automagically detect them.
3307 * ---------------------------------------------------------------------
3310 * indent-tabs-mode: t