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 3082 2005-07-20 15:28:51Z twisti $
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_Throwable.h"
49 #if defined(USE_THREADS)
50 # if defined(NATIVE_THREADS)
51 # include "threads/native/threads.h"
53 # include "threads/green/threads.h"
54 # include "threads/green/locks.h"
58 #include "toolbox/logging.h"
59 #include "toolbox/util.h"
60 #include "vm/exceptions.h"
61 #include "vm/builtin.h"
62 #include "vm/global.h"
63 #include "vm/linker.h"
64 #include "vm/loader.h"
65 #include "vm/options.h"
66 #include "vm/statistics.h"
67 #include "vm/stringlocal.h"
68 #include "vm/tables.h"
69 #include "vm/classcache.h"
72 # include "vm/unzip.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
78 /******************************************************************************/
80 /******************************************************************************/
82 /*#define LOADER_VERBOSE*/
89 #define LOADER_ASSERT(cond) assert(cond)
91 #define LOADER_ASSERT(cond)
99 static int loader_recursion = 0;
100 #define LOADER_INDENT(str) do { int i; for(i=0;i<loader_recursion*4;++i) {str[i]=' ';} str[i]=0;} while (0)
101 #define LOADER_INC() loader_recursion++
102 #define LOADER_DEC() loader_recursion--
109 /********************************************************************
110 list of classpath entries (either filesystem directories or
112 ********************************************************************/
114 classpath_info *classpath_entries = NULL;
117 /* loader_init *****************************************************************
119 Initializes all lists and loads all classes required for the system
122 *******************************************************************************/
124 bool loader_init(u1 *stackbottom)
126 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
129 /* Initialize the monitor pointer for zip/jar file locking. */
131 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
132 if (cpi->type == CLASSPATH_ARCHIVE)
133 initObjectLock(&cpi->header);
137 /* load some important classes */
139 if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
142 if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
145 if (!(class_java_lang_Cloneable =
146 load_class_bootstrap(utf_java_lang_Cloneable)))
149 if (!(class_java_io_Serializable =
150 load_class_bootstrap(utf_java_io_Serializable)))
154 /* load classes for wrapping primitive types */
156 if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
159 if (!(class_java_lang_Boolean =
160 load_class_bootstrap(utf_java_lang_Boolean)))
163 if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
166 if (!(class_java_lang_Character =
167 load_class_bootstrap(utf_java_lang_Character)))
170 if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
173 if (!(class_java_lang_Integer =
174 load_class_bootstrap(utf_java_lang_Integer)))
177 if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
180 if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
183 if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
187 /* load some other important classes */
189 if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
192 if (!(class_java_lang_ClassLoader =
193 load_class_bootstrap(utf_java_lang_ClassLoader)))
196 if (!(class_java_lang_SecurityManager =
197 load_class_bootstrap(utf_java_lang_SecurityManager)))
200 if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
203 if (!(class_java_lang_ThreadGroup =
204 load_class_bootstrap(utf_java_lang_ThreadGroup)))
208 /* some classes which may be used more often */
210 if (!(class_java_lang_StackTraceElement =
211 load_class_bootstrap(utf_java_lang_StackTraceElement)))
214 if (!(class_java_lang_reflect_Constructor =
215 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
218 if (!(class_java_lang_reflect_Field =
219 load_class_bootstrap(utf_java_lang_reflect_Field)))
222 if (!(class_java_lang_reflect_Method =
223 load_class_bootstrap(utf_java_lang_reflect_Method)))
226 if (!(class_java_security_PrivilegedAction =
227 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
230 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
233 if (!(arrayclass_java_lang_Object =
234 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
237 #if defined(USE_THREADS)
238 if (stackbottom != 0)
246 /************* functions for reading classdata *********************************
248 getting classdata in blocks of variable size
249 (8,16,32,64-bit integer or float)
251 *******************************************************************************/
253 /* check_classbuffer_size ******************************************************
255 assert that at least <len> bytes are left to read
256 <len> is limited to the range of non-negative s4 values
258 *******************************************************************************/
260 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
262 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
264 new_classformaterror((cb)->class, "Truncated class file");
273 /* suck_nbytes *****************************************************************
275 transfer block of classfile data into a buffer
277 *******************************************************************************/
279 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
281 memcpy(buffer, cb->pos + 1, len);
286 /* skip_nbytes ****************************************************************
288 skip block of classfile data
290 *******************************************************************************/
292 inline void skip_nbytes(classbuffer *cb, s4 len)
298 inline u1 suck_u1(classbuffer *cb)
304 inline u2 suck_u2(classbuffer *cb)
308 return ((u2) a << 8) + (u2) b;
312 inline u4 suck_u4(classbuffer *cb)
318 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
322 /* get u8 from classfile data */
323 static u8 suck_u8(classbuffer *cb)
329 return (hi << 32) + lo;
332 v.high = suck_u4(cb);
339 /* get float from classfile data */
340 static float suck_float(classbuffer *cb)
348 for (i = 0; i < 4; i++)
349 buffer[3 - i] = suck_u1(cb);
351 memcpy((u1*) (&f), buffer, 4);
353 suck_nbytes((u1*) (&f), cb, 4);
356 if (sizeof(float) != 4) {
357 *exceptionptr = new_exception_message(string_java_lang_InternalError,
358 "Incompatible float-format");
360 /* XXX should we exit in such a case? */
361 throw_exception_exit();
368 /* get double from classfile data */
369 static double suck_double(classbuffer *cb)
377 for (i = 0; i < 8; i++)
378 buffer[7 - i] = suck_u1(cb);
380 memcpy((u1*) (&d), buffer, 8);
382 suck_nbytes((u1*) (&d), cb, 8);
385 if (sizeof(double) != 8) {
386 *exceptionptr = new_exception_message(string_java_lang_InternalError,
387 "Incompatible double-format");
389 /* XXX should we exit in such a case? */
390 throw_exception_exit();
397 /************************** function suck_init *********************************
399 called once at startup, sets the searchpath for the classfiles
401 *******************************************************************************/
403 void suck_init(char *classpath)
411 classpath_info *lastcpi;
415 /* search for last classpath entry (only if there already some) */
417 if ((lastcpi = classpath_entries)) {
418 while (lastcpi->next)
419 lastcpi = lastcpi->next;
422 for (start = classpath; (*start) != '\0';) {
424 /* search for ':' delimiter to get the end of the current entry */
425 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
429 filenamelen = end - start;
431 if (filenamelen > 3) {
432 if (strncasecmp(end - 3, "zip", 3) == 0 ||
433 strncasecmp(end - 3, "jar", 3) == 0) {
438 /* save classpath entries as absolute pathnames */
443 if (*start != '/') { /* XXX fix me for win32 */
445 cwdlen = strlen(cwd) + strlen("/");
448 /* allocate memory for filename and fill it */
450 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
454 strcpy(filename, cwd);
455 strcat(filename, "/");
456 strncat(filename, start, filenamelen);
458 /* add cwd length to file length */
459 filenamelen += cwdlen;
462 strncpy(filename, start, filenamelen);
463 filename[filenamelen] = '\0';
469 #if defined(USE_ZLIB)
470 unzFile uf = unzOpen(filename);
473 cpi = NEW(classpath_info);
474 cpi->type = CLASSPATH_ARCHIVE;
477 cpi->path = filename;
478 cpi->pathlen = filenamelen;
482 throw_cacao_exception_exit(string_java_lang_InternalError,
483 "zip/jar files not supported");
487 cpi = NEW(classpath_info);
488 cpi->type = CLASSPATH_PATH;
491 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
492 filename[filenamelen] = '/';
493 filename[filenamelen + 1] = '\0';
497 cpi->path = filename;
498 cpi->pathlen = filenamelen;
501 /* attach current classpath entry */
504 if (!classpath_entries)
505 classpath_entries = cpi;
513 /* goto next classpath entry, skip ':' delimiter */
525 /* loader_load_all_classes *****************************************************
527 Loads all classes specified in the BOOTCLASSPATH.
529 *******************************************************************************/
531 void loader_load_all_classes(void)
536 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
537 #if defined(USE_ZLIB)
538 if (cpi->type == CLASSPATH_ARCHIVE) {
542 s = (unz_s *) cpi->uf;
543 ce = s->cacao_dir_list;
546 /* skip all entries in META-INF and .properties files */
548 if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
549 !strstr(ce->name->text, ".properties"))
550 c = load_class_bootstrap(ce->name);
557 #if defined(USE_ZLIB)
564 /* suck_start ******************************************************************
566 Returns true if classbuffer is already loaded or a file for the
567 specified class has succussfully been read in. All directories of
568 the searchpath are used to find the classfile (<classname>.class).
569 Returns false if no classfile is found and writes an error message.
571 *******************************************************************************/
573 classbuffer *suck_start(classinfo *c)
585 /* initialize return value */
590 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
591 filename = MNEW(char, filenamelen);
593 utf_sprint(filename, c->name);
594 strcat(filename, ".class");
596 /* walk through all classpath entries */
598 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
599 #if defined(USE_ZLIB)
600 if (cpi->type == CLASSPATH_ARCHIVE) {
602 #if defined(USE_THREADS)
603 /* enter a monitor on zip/jar archives */
605 builtin_monitorenter((java_objectheader *) cpi);
608 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
609 unz_file_info file_info;
611 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
612 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
613 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
614 cb = NEW(classbuffer);
616 cb->size = file_info.uncompressed_size;
617 cb->data = MNEW(u1, cb->size);
618 cb->pos = cb->data - 1;
620 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
622 if (len != cb->size) {
624 log_text("Error while unzipping");
631 log_text("Error while opening file in archive");
635 log_text("Error while retrieving fileinfo");
638 unzCloseCurrentFile(cpi->uf);
640 #if defined(USE_THREADS)
641 /* leave the monitor */
643 builtin_monitorexit((java_objectheader *) cpi);
647 #endif /* defined(USE_ZLIB) */
649 path = MNEW(char, cpi->pathlen + filenamelen);
650 strcpy(path, cpi->path);
651 strcat(path, filename);
653 classfile = fopen(path, "r");
655 if (classfile) { /* file exists */
656 if (!stat(path, &buffer)) { /* read classfile data */
657 cb = NEW(classbuffer);
659 cb->size = buffer.st_size;
660 cb->data = MNEW(u1, cb->size);
661 cb->pos = cb->data - 1;
663 /* read class data */
664 len = fread(cb->data, 1, cb->size, classfile);
666 if (len != buffer.st_size) {
668 /* if (ferror(classfile)) { */
677 MFREE(path, char, cpi->pathlen + filenamelen);
678 #if defined(USE_ZLIB)
685 dolog("Warning: Can not open class file '%s'", filename);
687 if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
695 MFREE(filename, char, filenamelen);
701 /************************** function suck_stop *********************************
703 frees memory for buffer with classfile data.
704 Caution: this function may only be called if buffer has been allocated
705 by suck_start with reading a file
707 *******************************************************************************/
709 void suck_stop(classbuffer *cb)
713 MFREE(cb->data, u1, cb->size);
714 FREE(cb, classbuffer);
718 /******************************************************************************/
719 /******************* Some support functions ***********************************/
720 /******************************************************************************/
722 void fprintflags (FILE *fp, u2 f)
724 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
725 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
726 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
727 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
728 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
729 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
730 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
731 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
732 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
733 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
734 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
738 /********** internal function: printflags (only for debugging) ***************/
740 void printflags(u2 f)
742 fprintflags(stdout,f);
746 /********************** Function: skipattributebody ****************************
748 skips an attribute after the 16 bit reference to attribute_name has already
751 *******************************************************************************/
753 static bool skipattributebody(classbuffer *cb)
757 if (!check_classbuffer_size(cb, 4))
762 if (!check_classbuffer_size(cb, len))
765 skip_nbytes(cb, len);
771 /************************* Function: skipattributes ****************************
773 skips num attribute structures
775 *******************************************************************************/
777 static bool skipattributes(classbuffer *cb, u4 num)
782 for (i = 0; i < num; i++) {
783 if (!check_classbuffer_size(cb, 2 + 4))
789 if (!check_classbuffer_size(cb, len))
792 skip_nbytes(cb, len);
799 /* load_constantpool ***********************************************************
801 Loads the constantpool of a class, the entries are transformed into
802 a simpler format by resolving references (a detailed overview of
803 the compact structures can be found in global.h).
805 *******************************************************************************/
807 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
810 /* The following structures are used to save information which cannot be
811 processed during the first pass. After the complete constantpool has
812 been traversed the references can be resolved.
813 (only in specific order) */
815 /* CONSTANT_Class entries */
816 typedef struct forward_class {
817 struct forward_class *next;
822 /* CONSTANT_String */
823 typedef struct forward_string {
824 struct forward_string *next;
829 /* CONSTANT_NameAndType */
830 typedef struct forward_nameandtype {
831 struct forward_nameandtype *next;
835 } forward_nameandtype;
837 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
838 typedef struct forward_fieldmethint {
839 struct forward_fieldmethint *next;
843 u2 nameandtype_index;
844 } forward_fieldmethint;
850 forward_class *forward_classes = NULL;
851 forward_string *forward_strings = NULL;
852 forward_nameandtype *forward_nameandtypes = NULL;
853 forward_fieldmethint *forward_fieldmethints = NULL;
857 forward_nameandtype *nfn;
858 forward_fieldmethint *nff;
866 /* number of entries in the constant_pool table plus one */
867 if (!check_classbuffer_size(cb, 2))
870 cpcount = c->cpcount = suck_u2(cb);
872 /* allocate memory */
873 cptags = c->cptags = MNEW(u1, cpcount);
874 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
877 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
881 #if defined(STATISTICS)
883 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
886 /* initialize constantpool */
887 for (idx = 0; idx < cpcount; idx++) {
888 cptags[idx] = CONSTANT_UNUSED;
893 /******* first pass *******/
894 /* entries which cannot be resolved now are written into
895 temporary structures and traversed again later */
898 while (idx < cpcount) {
901 /* get constant type */
902 if (!check_classbuffer_size(cb, 1))
909 nfc = DNEW(forward_class);
911 nfc->next = forward_classes;
912 forward_classes = nfc;
914 nfc->thisindex = idx;
915 /* reference to CONSTANT_NameAndType */
916 if (!check_classbuffer_size(cb, 2))
919 nfc->name_index = suck_u2(cb);
924 case CONSTANT_String:
925 nfs = DNEW(forward_string);
927 nfs->next = forward_strings;
928 forward_strings = nfs;
930 nfs->thisindex = idx;
932 /* reference to CONSTANT_Utf8_info with string characters */
933 if (!check_classbuffer_size(cb, 2))
936 nfs->string_index = suck_u2(cb);
941 case CONSTANT_NameAndType:
942 nfn = DNEW(forward_nameandtype);
944 nfn->next = forward_nameandtypes;
945 forward_nameandtypes = nfn;
947 nfn->thisindex = idx;
949 if (!check_classbuffer_size(cb, 2 + 2))
952 /* reference to CONSTANT_Utf8_info containing simple name */
953 nfn->name_index = suck_u2(cb);
955 /* reference to CONSTANT_Utf8_info containing field or method
957 nfn->sig_index = suck_u2(cb);
962 case CONSTANT_Fieldref:
963 case CONSTANT_Methodref:
964 case CONSTANT_InterfaceMethodref:
965 nff = DNEW(forward_fieldmethint);
967 nff->next = forward_fieldmethints;
968 forward_fieldmethints = nff;
970 nff->thisindex = idx;
974 if (!check_classbuffer_size(cb, 2 + 2))
977 /* class or interface type that contains the declaration of the
979 nff->class_index = suck_u2(cb);
981 /* name and descriptor of the field or method */
982 nff->nameandtype_index = suck_u2(cb);
987 case CONSTANT_Integer: {
988 constant_integer *ci = NEW(constant_integer);
990 #if defined(STATISTICS)
992 count_const_pool_len += sizeof(constant_integer);
995 if (!check_classbuffer_size(cb, 4))
998 ci->value = suck_s4(cb);
999 cptags[idx] = CONSTANT_Integer;
1006 case CONSTANT_Float: {
1007 constant_float *cf = NEW(constant_float);
1009 #if defined(STATISTICS)
1011 count_const_pool_len += sizeof(constant_float);
1014 if (!check_classbuffer_size(cb, 4))
1017 cf->value = suck_float(cb);
1018 cptags[idx] = CONSTANT_Float;
1025 case CONSTANT_Long: {
1026 constant_long *cl = NEW(constant_long);
1028 #if defined(STATISTICS)
1030 count_const_pool_len += sizeof(constant_long);
1033 if (!check_classbuffer_size(cb, 8))
1036 cl->value = suck_s8(cb);
1037 cptags[idx] = CONSTANT_Long;
1040 if (idx > cpcount) {
1042 new_classformaterror(c, "Invalid constant pool entry");
1048 case CONSTANT_Double: {
1049 constant_double *cd = NEW(constant_double);
1051 #if defined(STATISTICS)
1053 count_const_pool_len += sizeof(constant_double);
1056 if (!check_classbuffer_size(cb, 8))
1059 cd->value = suck_double(cb);
1060 cptags[idx] = CONSTANT_Double;
1063 if (idx > cpcount) {
1065 new_classformaterror(c, "Invalid constant pool entry");
1071 case CONSTANT_Utf8: {
1074 /* number of bytes in the bytes array (not string-length) */
1075 if (!check_classbuffer_size(cb, 2))
1078 length = suck_u2(cb);
1079 cptags[idx] = CONSTANT_Utf8;
1081 /* validate the string */
1082 if (!check_classbuffer_size(cb, length))
1086 !is_valid_utf((char *) (cb->pos + 1),
1087 (char *) (cb->pos + 1 + length))) {
1088 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1091 /* insert utf-string into the utf-symboltable */
1092 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1094 /* skip bytes of the string (buffer size check above) */
1095 skip_nbytes(cb, length);
1102 new_classformaterror(c, "Illegal constant pool type");
1108 /* resolve entries in temporary structures */
1110 while (forward_classes) {
1112 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1114 if (opt_verify && !is_valid_name_utf(name)) {
1116 new_classformaterror(c, "Class reference with invalid name");
1120 /* add all class references to the descriptor_pool */
1122 if (!descriptor_pool_add_class(descpool, name))
1125 cptags[forward_classes->thisindex] = CONSTANT_Class;
1130 if (!(tc = load_class_bootstrap(name)))
1133 /* link the class later, because we cannot link the class currently
1135 list_addfirst(&unlinkedclasses, tc);
1138 /* the classref is created later */
1139 cpinfos[forward_classes->thisindex] = name;
1141 nfc = forward_classes;
1142 forward_classes = forward_classes->next;
1145 while (forward_strings) {
1147 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1149 /* resolve utf-string */
1150 cptags[forward_strings->thisindex] = CONSTANT_String;
1151 cpinfos[forward_strings->thisindex] = text;
1153 nfs = forward_strings;
1154 forward_strings = forward_strings->next;
1157 while (forward_nameandtypes) {
1158 constant_nameandtype *cn = NEW(constant_nameandtype);
1160 #if defined(STATISTICS)
1162 count_const_pool_len += sizeof(constant_nameandtype);
1165 /* resolve simple name and descriptor */
1166 cn->name = class_getconstant(c,
1167 forward_nameandtypes->name_index,
1170 cn->descriptor = class_getconstant(c,
1171 forward_nameandtypes->sig_index,
1176 if (!is_valid_name_utf(cn->name)) {
1178 new_classformaterror(c,
1179 "Illegal Field name \"%s\"",
1185 /* disallow referencing <clinit> among others */
1186 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1188 new_exception_utfmessage(string_java_lang_InternalError,
1194 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1195 cpinfos[forward_nameandtypes->thisindex] = cn;
1197 nfn = forward_nameandtypes;
1198 forward_nameandtypes = forward_nameandtypes->next;
1201 while (forward_fieldmethints) {
1202 constant_nameandtype *nat;
1203 constant_FMIref *fmi = NEW(constant_FMIref);
1205 #if defined(STATISTICS)
1207 count_const_pool_len += sizeof(constant_FMIref);
1209 /* resolve simple name and descriptor */
1211 nat = class_getconstant(c,
1212 forward_fieldmethints->nameandtype_index,
1213 CONSTANT_NameAndType);
1215 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
1217 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
1220 /* the classref is created later */
1222 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
1223 fmi->name = nat->name;
1224 fmi->descriptor = nat->descriptor;
1226 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1227 cpinfos[forward_fieldmethints->thisindex] = fmi;
1229 nff = forward_fieldmethints;
1230 forward_fieldmethints = forward_fieldmethints->next;
1233 /* everything was ok */
1239 /* load_field ******************************************************************
1241 Load everything about a class field from the class file and fill a
1242 'fieldinfo' structure. For static fields, space in the data segment
1245 *******************************************************************************/
1247 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1249 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
1254 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1259 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1262 f->flags = suck_u2(cb);
1264 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1269 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1273 f->parseddesc = NULL;
1275 if (!descriptor_pool_add(descpool, u, NULL))
1280 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1281 *exceptionptr = new_classformaterror(c,
1282 "Illegal Field name \"%s\"",
1287 /* check flag consistency */
1288 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1290 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1291 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1293 new_classformaterror(c,
1294 "Illegal field modifiers: 0x%X",
1299 if (c->flags & ACC_INTERFACE) {
1300 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1301 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1302 f->flags & ACC_TRANSIENT) {
1304 new_classformaterror(c,
1305 "Illegal field modifiers: 0x%X",
1312 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1313 f->offset = 0; /* offset from start of object */
1318 case TYPE_INT: f->value.i = 0; break;
1319 case TYPE_FLOAT: f->value.f = 0.0; break;
1320 case TYPE_DOUBLE: f->value.d = 0.0; break;
1321 case TYPE_ADDRESS: f->value.a = NULL; break;
1324 f->value.l = 0; break;
1326 f->value.l.low = 0; f->value.l.high = 0; break;
1330 /* read attributes */
1331 if (!check_classbuffer_size(cb, 2))
1334 attrnum = suck_u2(cb);
1335 for (i = 0; i < attrnum; i++) {
1336 if (!check_classbuffer_size(cb, 2))
1339 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1342 if (u == utf_ConstantValue) {
1343 if (!check_classbuffer_size(cb, 4 + 2))
1346 /* check attribute length */
1347 if (suck_u4(cb) != 2) {
1349 new_classformaterror(c, "Wrong size for VALUE attribute");
1353 /* constant value attribute */
1354 if (pindex != field_load_NOVALUE) {
1356 new_classformaterror(c,
1357 "Multiple ConstantValue attributes");
1361 /* index of value in constantpool */
1362 pindex = suck_u2(cb);
1364 /* initialize field with value from constantpool */
1367 constant_integer *ci;
1369 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1372 f->value.i = ci->value;
1379 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1382 f->value.l = cl->value;
1389 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1392 f->value.f = cf->value;
1397 constant_double *cd;
1399 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1402 f->value.d = cd->value;
1407 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1410 /* create javastring from compressed utf8-string */
1411 f->value.a = literalstring_new(u);
1415 log_text("Invalid Constant - Type");
1419 /* unknown attribute */
1420 if (!skipattributebody(cb))
1425 /* everything was ok */
1431 /* load_method *****************************************************************
1433 Loads a method from the class file and fills an existing
1434 'methodinfo' structure. For native methods, the function pointer
1435 field is set to the real function pointer, for JavaVM methods a
1436 pointer to the compiler is used preliminarily.
1438 *******************************************************************************/
1440 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1451 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1452 initObjectLock(&m->header);
1457 count_all_methods++;
1460 m->thrownexceptionscount = 0;
1461 m->linenumbercount = 0;
1464 m->nativelyoverloaded = false;
1466 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1469 m->flags = suck_u2(cb);
1471 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1476 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1480 m->parseddesc = NULL;
1482 if (!descriptor_pool_add(descpool, u, &argcount))
1486 if (!is_valid_name_utf(m->name)) {
1487 log_text("Method with invalid name");
1491 if (m->name->text[0] == '<' &&
1492 m->name != utf_init && m->name != utf_clinit) {
1493 log_text("Method with invalid special name");
1498 if (!(m->flags & ACC_STATIC))
1499 argcount++; /* count the 'this' argument */
1502 if (argcount > 255) {
1504 new_classformaterror(c, "Too many arguments in signature");
1508 /* check flag consistency */
1509 if (m->name != utf_clinit) {
1510 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1512 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1514 new_classformaterror(c,
1515 "Illegal method modifiers: 0x%X",
1520 if (m->flags & ACC_ABSTRACT) {
1521 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1522 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1524 new_classformaterror(c,
1525 "Illegal method modifiers: 0x%X",
1531 if (c->flags & ACC_INTERFACE) {
1532 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1534 new_classformaterror(c,
1535 "Illegal method modifiers: 0x%X",
1541 if (m->name == utf_init) {
1542 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1543 ACC_NATIVE | ACC_ABSTRACT)) {
1544 log_text("Instance initialization method has invalid flags set");
1552 m->basicblockcount = 0;
1553 m->basicblocks = NULL;
1554 m->basicblockindex = NULL;
1555 m->instructioncount = 0;
1556 m->instructions = NULL;
1559 m->exceptiontable = NULL;
1560 m->stubroutine = NULL;
1562 m->entrypoint = NULL;
1563 m->methodUsed = NOTUSED;
1566 m->subRedefsUsed = 0;
1570 if (!check_classbuffer_size(cb, 2))
1573 attrnum = suck_u2(cb);
1574 for (i = 0; i < attrnum; i++) {
1577 if (!check_classbuffer_size(cb, 2))
1580 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1583 if (aname == utf_Code) {
1584 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1586 new_classformaterror(c,
1587 "Code attribute in native or abstract methods");
1594 new_classformaterror(c, "Multiple Code attributes");
1599 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1603 m->maxstack = suck_u2(cb);
1604 m->maxlocals = suck_u2(cb);
1606 if (m->maxlocals < argcount) {
1608 new_classformaterror(c, "Arguments can't fit into locals");
1613 if (!check_classbuffer_size(cb, 4))
1616 m->jcodelength = suck_u4(cb);
1618 if (m->jcodelength == 0) {
1620 new_classformaterror(c, "Code of a method has length 0");
1625 if (m->jcodelength > 65535) {
1627 new_classformaterror(c,
1628 "Code of a method longer than 65535 bytes");
1633 if (!check_classbuffer_size(cb, m->jcodelength))
1636 m->jcode = MNEW(u1, m->jcodelength);
1637 suck_nbytes(m->jcode, cb, m->jcodelength);
1639 if (!check_classbuffer_size(cb, 2))
1642 m->exceptiontablelength = suck_u2(cb);
1643 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1646 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1648 #if defined(STATISTICS)
1650 count_vmcode_len += m->jcodelength + 18;
1651 count_extable_len += 8 * m->exceptiontablelength;
1655 for (j = 0; j < m->exceptiontablelength; j++) {
1657 m->exceptiontable[j].startpc = suck_u2(cb);
1658 m->exceptiontable[j].endpc = suck_u2(cb);
1659 m->exceptiontable[j].handlerpc = suck_u2(cb);
1663 m->exceptiontable[j].catchtype.any = NULL;
1666 /* the classref is created later */
1667 if (!(m->exceptiontable[j].catchtype.any =
1668 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1673 if (!check_classbuffer_size(cb, 2))
1676 codeattrnum = suck_u2(cb);
1678 for (; codeattrnum > 0; codeattrnum--) {
1681 if (!check_classbuffer_size(cb, 2))
1684 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1687 if (caname == utf_LineNumberTable) {
1690 if (!check_classbuffer_size(cb, 4 + 2))
1694 m->linenumbercount = suck_u2(cb);
1696 if (!check_classbuffer_size(cb,
1697 (2 + 2) * m->linenumbercount))
1700 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1702 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1703 m->linenumbers[lncid].start_pc = suck_u2(cb);
1704 m->linenumbers[lncid].line_number = suck_u2(cb);
1708 if (!skipattributes(cb, codeattrnum))
1714 if (!skipattributebody(cb))
1719 } else if (aname == utf_Exceptions) {
1722 if (m->thrownexceptions) {
1724 new_classformaterror(c, "Multiple Exceptions attributes");
1728 if (!check_classbuffer_size(cb, 4 + 2))
1731 suck_u4(cb); /* length */
1732 m->thrownexceptionscount = suck_u2(cb);
1734 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1737 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1739 for (j = 0; j < m->thrownexceptionscount; j++) {
1740 /* the classref is created later */
1741 if (!((m->thrownexceptions)[j].any =
1742 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1747 if (!skipattributebody(cb))
1752 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1753 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1758 /* everything was ok */
1764 /* load_attribute **************************************************************
1766 Read attributes from classfile.
1768 *******************************************************************************/
1770 static bool load_attributes(classbuffer *cb, u4 num)
1778 for (i = 0; i < num; i++) {
1779 /* retrieve attribute name */
1780 if (!check_classbuffer_size(cb, 2))
1783 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1786 if (aname == utf_InnerClasses) {
1787 /* innerclasses attribute */
1788 if (c->innerclass) {
1790 new_classformaterror(c, "Multiple InnerClasses attributes");
1794 if (!check_classbuffer_size(cb, 4 + 2))
1797 /* skip attribute length */
1800 /* number of records */
1801 c->innerclasscount = suck_u2(cb);
1803 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1806 /* allocate memory for innerclass structure */
1807 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1809 for (j = 0; j < c->innerclasscount; j++) {
1810 /* The innerclass structure contains a class with an encoded
1811 name, its defining scope, its simple name and a bitmask of
1812 the access flags. If an inner class is not a member, its
1813 outer_class is NULL, if a class is anonymous, its name is
1816 innerclassinfo *info = c->innerclass + j;
1818 info->inner_class.ref =
1819 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1820 info->outer_class.ref =
1821 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1823 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1824 info->flags = suck_u2(cb);
1827 } else if (aname == utf_SourceFile) {
1828 if (!check_classbuffer_size(cb, 4 + 2))
1831 if (suck_u4(cb) != 2) {
1833 new_classformaterror(c, "Wrong size for VALUE attribute");
1837 if (c->sourcefile) {
1839 new_classformaterror(c, "Multiple SourceFile attributes");
1843 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1847 /* unknown attribute */
1848 if (!skipattributebody(cb))
1857 /* load_class_from_sysloader ***************************************************
1859 Load the class with the given name using the system class loader
1862 name.............the classname
1865 the loaded class, or
1866 NULL if an exception has been thrown
1868 *******************************************************************************/
1870 classinfo *load_class_from_sysloader(utf *name)
1873 java_objectheader *cl;
1876 #ifdef LOADER_VERBOSE
1877 char logtext[MAXLOGTEXT];
1878 LOADER_INDENT(logtext);
1879 sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1880 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1884 LOADER_ASSERT(class_java_lang_Object);
1885 LOADER_ASSERT(class_java_lang_ClassLoader);
1886 LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1888 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1889 utf_getSystemClassLoader,
1890 utf_void__java_lang_ClassLoader,
1891 class_java_lang_Object,
1897 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1902 r = load_class_from_classloader(name, cl);
1908 /* load_class_from_classloader *************************************************
1910 Load the class with the given name using the given user-defined class loader.
1913 name.............the classname
1914 cl...............user-defined class loader
1917 the loaded class, or
1918 NULL if an exception has been thrown
1920 *******************************************************************************/
1922 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1926 #ifdef LOADER_VERBOSE
1927 char logtext[MAXLOGTEXT];
1928 LOADER_INDENT(logtext);
1929 strcat(logtext,"load_class_from_classloader(");
1930 utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1931 if (!cl) strcat(logtext,"<bootstrap>");
1932 else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1933 else strcat(logtext,"<unknown class>");
1934 strcat(logtext,")");
1938 LOADER_ASSERT(name);
1940 /* lookup if this class has already been loaded */
1942 r = classcache_lookup(cl, name);
1944 #ifdef LOADER_VERBOSE
1946 dolog(" cached -> %p",(void*)r);
1952 /* if other class loader than bootstrap, call it */
1957 /* handle array classes */
1958 if (name->text[0] == '[') {
1964 utf_ptr = name->text + 1;
1965 len = name->blength - 1;
1973 /* load the component class */
1974 u = utf_new(utf_ptr, len);
1976 if (!(comp = load_class_from_classloader(u, cl))) {
1981 /* create the array class */
1982 r = class_array_of(comp, false);
1986 /* primitive array classes are loaded by the bootstrap loader */
1988 r = load_class_bootstrap(name);
1994 LOADER_ASSERT(class_java_lang_Object);
1996 lc = class_resolveclassmethod(cl->vftbl->class,
1998 utf_java_lang_String__java_lang_Class,
1999 class_java_lang_Object,
2003 return false; /* exception */
2006 r = (classinfo *) asm_calljavafunction(lc,
2008 javastring_new_slash_to_dot(name),
2013 /* store this class in the loaded class cache */
2014 /* If another class with the same (initloader,name) pair has been */
2015 /* stored earlier it will be returned by classcache_store */
2016 /* In this case classcache_store may not free the class because it*/
2017 /* has already been exposed to Java code which may have kept */
2018 /* references to that class. */
2019 classinfo *c = classcache_store(cl,r,false);
2021 /* exception, free the loaded class */
2032 r = load_class_bootstrap(name);
2039 /* load_class_bootstrap ********************************************************
2041 Load the class with the given name using the bootstrap class loader.
2044 name.............the classname
2047 loaded classinfo, or
2048 NULL if an exception has been thrown
2051 load_class_bootstrap is synchronized. It can be treated as an
2054 *******************************************************************************/
2056 classinfo *load_class_bootstrap(utf *name)
2061 #ifdef LOADER_VERBOSE
2062 char logtext[MAXLOGTEXT];
2067 LOADER_ASSERT(name);
2070 /* lookup if this class has already been loaded */
2072 if ((r = classcache_lookup(NULL, name)))
2075 #ifdef LOADER_VERBOSE
2076 LOADER_INDENT(logtext);
2077 strcat(logtext,"load_class_bootstrap(");
2078 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2082 /* create the classinfo */
2084 c = class_create_classinfo(name);
2086 /* handle array classes */
2088 if (name->text[0] == '[') {
2089 c = load_newly_created_array(c, NULL);
2091 goto return_exception;
2092 LOADER_ASSERT(c->loaded);
2097 #if defined(STATISTICS)
2100 if (getcompilingtime)
2101 compilingtime_stop();
2104 loadingtime_start();
2107 /* load classdata, throw exception on error */
2109 if ((cb = suck_start(c)) == NULL) {
2110 /* this normally means, the classpath was not set properly */
2112 if (name == utf_java_lang_Object)
2113 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2114 "java/lang/Object");
2117 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2119 goto return_exception;
2122 /* load the class from the buffer */
2124 r = load_class_from_classbuffer(cb);
2130 #if defined(STATISTICS)
2136 if (getcompilingtime)
2137 compilingtime_start();
2141 /* the class could not be loaded, free the classinfo struct */
2146 /* store this class in the loaded class cache */
2147 /* this step also checks the loading constraints */
2148 /* If the class has been loaded before, the */
2149 /* earlier loaded class is returned. */
2150 classinfo *res = classcache_store(NULL,c,true);
2159 goto return_exception;
2173 /* load_class_from_classbuffer *************************************************
2175 Loads everything interesting about a class from the class file. The
2176 'classinfo' structure must have been allocated previously.
2178 The super class and the interfaces implemented by this class need
2179 not be loaded. The link is set later by the function 'class_link'.
2181 The loaded class is removed from the list 'unloadedclasses' and
2182 added to the list 'unlinkedclasses'.
2185 This function is NOT synchronized!
2187 *******************************************************************************/
2189 classinfo *load_class_from_classbuffer(classbuffer *cb)
2197 descriptor_pool *descpool;
2198 #if defined(STATISTICS)
2202 #ifdef LOADER_VERBOSE
2203 char logtext[MAXLOGTEXT];
2206 /* get the classbuffer's class */
2210 /* maybe the class is already loaded */
2215 #ifdef LOADER_VERBOSE
2216 LOADER_INDENT(logtext);
2217 strcat(logtext,"load_class_from_classbuffer(");
2218 utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2223 #if defined(STATISTICS)
2225 count_class_loads++;
2228 /* output for debugging purposes */
2231 log_message_class("Loading class: ", c);
2233 /* mark start of dump memory area */
2235 dumpsize = dump_size();
2237 /* class is somewhat loaded */
2241 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2242 goto return_exception;
2244 /* check signature */
2246 if (suck_u4(cb) != MAGIC) {
2247 *exceptionptr = new_classformaterror(c, "Bad magic number");
2249 goto return_exception;
2257 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2259 new_unsupportedclassversionerror(c,
2260 "Unsupported major.minor version %d.%d",
2263 goto return_exception;
2266 /* create a new descriptor pool */
2268 descpool = descriptor_pool_new(c);
2270 /* load the constant pool */
2272 if (!load_constantpool(cb, descpool))
2273 goto return_exception;
2276 c->erroneous_state = 0;
2277 c->initializing_thread = 0;
2279 c->classUsed = NOTUSED; /* not used initially CO-RT */
2284 if (!check_classbuffer_size(cb, 2))
2285 goto return_exception;
2287 c->flags = suck_u2(cb);
2289 /* check ACC flags consistency */
2291 if (c->flags & ACC_INTERFACE) {
2292 if (!(c->flags & ACC_ABSTRACT)) {
2293 /* We work around this because interfaces in JDK 1.1 are
2294 * not declared abstract. */
2296 c->flags |= ACC_ABSTRACT;
2299 if (c->flags & ACC_FINAL) {
2301 new_classformaterror(c,
2302 "Illegal class modifiers: 0x%X", c->flags);
2304 goto return_exception;
2307 if (c->flags & ACC_SUPER) {
2308 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2312 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2314 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2316 goto return_exception;
2319 if (!check_classbuffer_size(cb, 2 + 2))
2320 goto return_exception;
2325 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2326 goto return_exception;
2328 if (c->name == utf_not_named_yet) {
2329 /* we finally have a name for this class */
2331 class_set_packagename(c);
2333 } else if (name != c->name) {
2337 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2338 utf_strlen(name) + strlen(")") + strlen("0");
2340 msg = MNEW(char, msglen);
2342 utf_sprint(msg, c->name);
2343 strcat(msg, " (wrong name: ");
2344 utf_strcat(msg, name);
2348 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2350 MFREE(msg, char, msglen);
2352 goto return_exception;
2355 /* retrieve superclass */
2357 c->super.any = NULL;
2358 if ((i = suck_u2(cb))) {
2359 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2360 goto return_exception;
2362 /* java.lang.Object may not have a super class. */
2364 if (c->name == utf_java_lang_Object) {
2366 new_exception_message(string_java_lang_ClassFormatError,
2367 "java.lang.Object with superclass");
2369 goto return_exception;
2372 /* Interfaces must have java.lang.Object as super class. */
2374 if ((c->flags & ACC_INTERFACE) &&
2375 supername != utf_java_lang_Object) {
2377 new_exception_message(string_java_lang_ClassFormatError,
2378 "Interfaces must have java.lang.Object as superclass");
2380 goto return_exception;
2386 /* This is only allowed for java.lang.Object. */
2388 if (c->name != utf_java_lang_Object) {
2389 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2391 goto return_exception;
2395 /* retrieve interfaces */
2397 if (!check_classbuffer_size(cb, 2))
2398 goto return_exception;
2400 c->interfacescount = suck_u2(cb);
2402 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2403 goto return_exception;
2405 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2406 for (i = 0; i < c->interfacescount; i++) {
2407 /* the classrefs are created later */
2408 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2409 goto return_exception;
2413 if (!check_classbuffer_size(cb, 2))
2414 goto return_exception;
2416 c->fieldscount = suck_u2(cb);
2417 c->fields = GCNEW(fieldinfo, c->fieldscount);
2418 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2419 for (i = 0; i < c->fieldscount; i++) {
2420 if (!load_field(cb, &(c->fields[i]),descpool))
2421 goto return_exception;
2425 if (!check_classbuffer_size(cb, 2))
2426 goto return_exception;
2428 c->methodscount = suck_u2(cb);
2429 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2430 c->methods = MNEW(methodinfo, c->methodscount);
2431 for (i = 0; i < c->methodscount; i++) {
2432 if (!load_method(cb, &(c->methods[i]),descpool))
2433 goto return_exception;
2436 /* create the class reference table */
2439 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2441 /* allocate space for the parsed descriptors */
2443 descriptor_pool_alloc_parsed_descriptors(descpool);
2445 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2447 #if defined(STATISTICS)
2449 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2450 count_classref_len += classrefsize;
2451 count_parsed_desc_len += descsize;
2455 /* put the classrefs in the constant pool */
2456 for (i = 0; i < c->cpcount; i++) {
2457 if (c->cptags[i] == CONSTANT_Class) {
2458 utf *name = (utf *) c->cpinfos[i];
2459 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2463 /* set the super class reference */
2466 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2468 goto return_exception;
2471 /* set the super interfaces references */
2473 for (i = 0; i < c->interfacescount; i++) {
2474 c->interfaces[i].ref =
2475 descriptor_pool_lookup_classref(descpool,
2476 (utf *) c->interfaces[i].any);
2477 if (!c->interfaces[i].ref)
2478 goto return_exception;
2481 /* parse field descriptors */
2483 for (i = 0; i < c->fieldscount; i++) {
2484 c->fields[i].parseddesc =
2485 descriptor_pool_parse_field_descriptor(descpool,
2486 c->fields[i].descriptor);
2487 if (!c->fields[i].parseddesc)
2488 goto return_exception;
2491 /* parse method descriptors */
2493 for (i = 0; i < c->methodscount; i++) {
2494 methodinfo *m = &c->methods[i];
2496 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2497 m->flags, class_get_self_classref(m->class));
2499 goto return_exception;
2501 for (j = 0; j < m->exceptiontablelength; j++) {
2502 if (!m->exceptiontable[j].catchtype.any)
2504 if ((m->exceptiontable[j].catchtype.ref =
2505 descriptor_pool_lookup_classref(descpool,
2506 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2507 goto return_exception;
2510 for (j = 0; j < m->thrownexceptionscount; j++) {
2511 if (!m->thrownexceptions[j].any)
2513 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2514 (utf *) m->thrownexceptions[j].any)) == NULL)
2515 goto return_exception;
2519 /* parse the loaded descriptors */
2521 for (i = 0; i < c->cpcount; i++) {
2522 constant_FMIref *fmi;
2525 switch (c->cptags[i]) {
2526 case CONSTANT_Fieldref:
2527 fmi = (constant_FMIref *) c->cpinfos[i];
2528 fmi->parseddesc.fd =
2529 descriptor_pool_parse_field_descriptor(descpool,
2531 if (!fmi->parseddesc.fd)
2532 goto return_exception;
2533 index = (int) (size_t) fmi->classref;
2535 (constant_classref *) class_getconstant(c, index,
2538 goto return_exception;
2540 case CONSTANT_Methodref:
2541 case CONSTANT_InterfaceMethodref:
2542 fmi = (constant_FMIref *) c->cpinfos[i];
2543 index = (int) (size_t) fmi->classref;
2545 (constant_classref *) class_getconstant(c, index,
2548 goto return_exception;
2549 fmi->parseddesc.md =
2550 descriptor_pool_parse_method_descriptor(descpool,
2554 if (!fmi->parseddesc.md)
2555 goto return_exception;
2560 /* Check if all fields and methods can be uniquely
2561 * identified by (name,descriptor). */
2564 /* We use a hash table here to avoid making the
2565 * average case quadratic in # of methods, fields.
2567 static int shift = 0;
2569 u2 *next; /* for chaining colliding hash entries */
2575 /* Allocate hashtable */
2576 len = c->methodscount;
2577 if (len < c->fieldscount) len = c->fieldscount;
2579 hashtab = MNEW(u2,(hashlen + len));
2580 next = hashtab + hashlen;
2582 /* Determine bitshift (to get good hash values) */
2592 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2594 for (i = 0; i < c->fieldscount; ++i) {
2595 fieldinfo *fi = c->fields + i;
2597 /* It's ok if we lose bits here */
2598 index = ((((size_t) fi->name) +
2599 ((size_t) fi->descriptor)) >> shift) % hashlen;
2601 if ((old = hashtab[index])) {
2605 if (c->fields[old].name == fi->name &&
2606 c->fields[old].descriptor == fi->descriptor) {
2608 new_classformaterror(c,
2609 "Repetitive field name/signature");
2611 goto return_exception;
2613 } while ((old = next[old]));
2615 hashtab[index] = i + 1;
2619 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2621 for (i = 0; i < c->methodscount; ++i) {
2622 methodinfo *mi = c->methods + i;
2624 /* It's ok if we lose bits here */
2625 index = ((((size_t) mi->name) +
2626 ((size_t) mi->descriptor)) >> shift) % hashlen;
2630 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2631 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2635 if ((old = hashtab[index])) {
2639 if (c->methods[old].name == mi->name &&
2640 c->methods[old].descriptor == mi->descriptor) {
2642 new_classformaterror(c,
2643 "Repetitive method name/signature");
2645 goto return_exception;
2647 } while ((old = next[old]));
2649 hashtab[index] = i + 1;
2652 MFREE(hashtab, u2, (hashlen + len));
2655 #if defined(STATISTICS)
2657 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2658 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2659 count_class_infos += sizeof(methodinfo) * c->methodscount;
2663 /* load attribute structures */
2665 if (!check_classbuffer_size(cb, 2))
2666 goto return_exception;
2668 if (!load_attributes(cb, suck_u2(cb)))
2669 goto return_exception;
2672 /* Pre java 1.5 version don't check this. This implementation is like
2673 java 1.5 do it: for class file version 45.3 we don't check it, older
2674 versions are checked.
2676 if ((ma == 45 && mi > 3) || ma > 45) {
2677 /* check if all data has been read */
2678 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2680 if (classdata_left > 0) {
2682 new_classformaterror(c, "Extra bytes at the end of class file");
2683 goto return_exception;
2688 /* release dump area */
2690 dump_release(dumpsize);
2693 log_message_class("Loading done class: ", c);
2699 /* release dump area */
2701 dump_release(dumpsize);
2703 /* an exception has been thrown */
2710 /* load_newly_created_array ****************************************************
2712 Load a newly created array class.
2715 c....................the array class C has been loaded
2716 other classinfo......the array class was found in the class cache,
2718 NULL.................an exception has been thrown
2721 This is an internal function. Do not use it unless you know exactly
2724 Use one of the load_class_... functions for general array class loading.
2726 *******************************************************************************/
2728 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2730 classinfo *comp = NULL;
2732 methoddesc *clonedesc;
2733 constant_classref *classrefs;
2735 java_objectheader *definingloader = NULL;
2738 #ifdef LOADER_VERBOSE
2739 char logtext[MAXLOGTEXT];
2740 LOADER_INDENT(logtext);
2741 strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2742 sprintf(logtext+strlen(logtext),") loader=%p",loader);
2746 /* Check array class name */
2748 namelen = c->name->blength;
2749 if (namelen < 2 || c->name->text[0] != '[') {
2750 *exceptionptr = new_internalerror("Invalid array class name");
2754 /* Check the component type */
2756 switch (c->name->text[1]) {
2758 /* c is an array of arrays. We have to create the component class. */
2760 u = utf_new_intern(c->name->text + 1, namelen - 1);
2762 if (!(comp = load_class_from_classloader(u, loader))) {
2767 LOADER_ASSERT(comp->loaded);
2771 definingloader = comp->classloader;
2775 /* c is an array of objects. */
2776 if (namelen < 4 || c->name->text[namelen - 1] != ';') {
2777 *exceptionptr = new_internalerror("Invalid array class name");
2781 u = utf_new_intern(c->name->text + 2, namelen - 3);
2784 if (!(comp = load_class_from_classloader(u, loader))) {
2789 LOADER_ASSERT(comp->loaded);
2793 definingloader = comp->classloader;
2797 LOADER_ASSERT(class_java_lang_Object);
2798 LOADER_ASSERT(class_java_lang_Cloneable);
2799 LOADER_ASSERT(class_java_io_Serializable);
2801 /* Setup the array class */
2803 c->super.cls = class_java_lang_Object;
2804 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2806 c->interfacescount = 2;
2807 c->interfaces = MNEW(classref_or_classinfo, 2);
2812 tc = class_java_lang_Cloneable;
2813 LOADER_ASSERT(tc->loaded);
2814 list_addfirst(&unlinkedclasses, tc);
2815 c->interfaces[0].cls = tc;
2817 tc = class_java_io_Serializable;
2818 LOADER_ASSERT(tc->loaded);
2819 list_addfirst(&unlinkedclasses, tc);
2820 c->interfaces[1].cls = tc;
2823 c->interfaces[0].cls = class_java_lang_Cloneable;
2824 c->interfaces[1].cls = class_java_io_Serializable;
2827 c->methodscount = 1;
2828 c->methods = MNEW(methodinfo, c->methodscount);
2830 classrefs = MNEW(constant_classref, 2);
2831 CLASSREF_INIT(classrefs[0], c, c->name);
2832 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2834 /* create descriptor for clone method */
2835 /* we need one paramslot which is reserved for the 'this' parameter */
2836 clonedesc = NEW(methoddesc);
2837 clonedesc->returntype.type = TYPE_ADDRESS;
2838 clonedesc->returntype.classref = classrefs + 1;
2839 clonedesc->returntype.arraydim = 0;
2840 clonedesc->paramcount = 0;
2841 clonedesc->paramslots = 0;
2842 clonedesc->paramtypes[0].classref = classrefs + 0;
2844 /* parse the descriptor to get the register allocation */
2846 if (!descriptor_params_from_paramtypes(clonedesc, ACC_NONE))
2850 MSET(clone, 0, methodinfo, 1);
2852 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2853 initObjectLock(&clone->header);
2856 clone->flags = ACC_PUBLIC;
2857 clone->name = utf_clone;
2858 clone->descriptor = utf_void__java_lang_Object;
2859 clone->parseddesc = clonedesc;
2861 clone->monoPoly = MONO;
2864 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2867 /* XXX: field: length? */
2869 /* array classes are not loaded from class files */
2872 c->parseddescs = (u1 *) clonedesc;
2873 c->parseddescsize = sizeof(methodinfo);
2874 c->classrefs = classrefs;
2875 c->classrefcount = 1;
2876 c->classloader = definingloader;
2878 /* insert class into the loaded class cache */
2879 /* XXX free classinfo if NULL returned? */
2881 return classcache_store(loader,c,true);
2885 /************************* Function: class_findfield ***************************
2887 Searches a 'classinfo' structure for a field having the given name and
2890 *******************************************************************************/
2892 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2896 for (i = 0; i < c->fieldscount; i++) {
2897 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2898 return &(c->fields[i]);
2901 log_text("Can not find field given in CONSTANT_Fieldref");
2904 /* keep compiler happy */
2910 /****************** Function: class_resolvefield_int ***************************
2912 This is an internally used helper function. Do not use this directly.
2914 Tries to resolve a field having the given name and type.
2915 If the field cannot be resolved, NULL is returned.
2917 *******************************************************************************/
2919 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2924 /* search for field in class c */
2926 for (i = 0; i < c->fieldscount; i++) {
2927 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2928 return &(c->fields[i]);
2932 /* try superinterfaces recursively */
2934 for (i = 0; i < c->interfacescount; i++) {
2935 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2940 /* try superclass */
2943 return class_resolvefield_int(c->super.cls, name, desc);
2951 /********************* Function: class_resolvefield ***************************
2953 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2955 If the field cannot be resolved the return value is NULL. If EXCEPT is
2956 true *exceptionptr is set, too.
2958 *******************************************************************************/
2960 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2961 classinfo *referer, bool except)
2965 /* XXX resolve class c */
2966 /* XXX check access from REFERER to C */
2968 fi = class_resolvefield_int(c, name, desc);
2973 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2979 /* XXX check access rights */
2985 /* class_findmethod ************************************************************
2987 Searches a 'classinfo' structure for a method having the given name
2988 and descriptor. If descriptor is NULL, it is ignored.
2990 *******************************************************************************/
2992 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2997 for (i = 0; i < c->methodscount; i++) {
2998 m = &(c->methods[i]);
3000 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
3008 /*********************** Function: class_fetchmethod **************************
3010 like class_findmethod, but aborts with an error if the method is not found
3012 *******************************************************************************/
3014 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3018 mi = class_findmethod(c, name, desc);
3021 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3022 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3023 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3025 log_text("Method not found");
3033 /************************* Function: class_findmethod_approx ******************
3035 like class_findmethod but ignores the return value when comparing the
3038 *******************************************************************************/
3040 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3044 for (i = 0; i < c->methodscount; i++) {
3045 if (c->methods[i].name == name) {
3046 utf *meth_descr = c->methods[i].descriptor;
3050 return &(c->methods[i]);
3052 if (desc->blength <= meth_descr->blength) {
3053 /* current position in utf text */
3054 char *desc_utf_ptr = desc->text;
3055 char *meth_utf_ptr = meth_descr->text;
3056 /* points behind utf strings */
3057 char *desc_end = UTF_END(desc);
3058 char *meth_end = UTF_END(meth_descr);
3061 /* compare argument types */
3062 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3064 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3065 break; /* no match */
3068 return &(c->methods[i]); /* all parameter types equal */
3078 /***************** Function: class_resolvemethod_approx ***********************
3080 Searches a class and every super class for a method (without paying
3081 attention to the return value)
3083 *******************************************************************************/
3085 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3088 /* search for method (ignore returntype) */
3089 methodinfo *m = class_findmethod_approx(c, name, desc);
3092 /* search superclass */
3100 /* class_resolvemethod *********************************************************
3102 Searches a class and it's super classes for a method.
3104 *******************************************************************************/
3106 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3111 m = class_findmethod(c, name, desc);
3123 /* class_resolveinterfacemethod_intern *****************************************
3125 Internally used helper function. Do not use this directly.
3127 *******************************************************************************/
3129 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
3130 utf *name, utf *desc)
3135 m = class_findmethod(c, name, desc);
3140 /* try the superinterfaces */
3142 for (i = 0; i < c->interfacescount; i++) {
3143 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3153 /* class_resolveinterfacemethod ************************************************
3155 Resolves a reference from REFERER to a method with NAME and DESC in
3158 If the method cannot be resolved the return value is NULL. If
3159 EXCEPT is true *exceptionptr is set, too.
3161 *******************************************************************************/
3163 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3164 classinfo *referer, bool except)
3168 /* XXX resolve class c */
3169 /* XXX check access from REFERER to C */
3171 if (!(c->flags & ACC_INTERFACE)) {
3174 new_exception(string_java_lang_IncompatibleClassChangeError);
3179 mi = class_resolveinterfacemethod_intern(c, name, desc);
3184 /* try class java.lang.Object */
3186 mi = class_findmethod(class_java_lang_Object, name, desc);
3193 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3199 /* class_resolveclassmethod ****************************************************
3201 Resolves a reference from REFERER to a method with NAME and DESC in
3204 If the method cannot be resolved the return value is NULL. If
3205 EXCEPT is true *exceptionptr is set, too.
3207 *******************************************************************************/
3209 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3210 classinfo *referer, bool except)
3218 /* XXX resolve class c */
3219 /* XXX check access from REFERER to C */
3221 /* if (c->flags & ACC_INTERFACE) { */
3223 /* *exceptionptr = */
3224 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3228 /* try class c and its superclasses */
3233 mi = class_findmethod(cls, name, desc);
3238 cls = cls->super.cls;
3241 /* try the superinterfaces */
3243 for (i = 0; i < c->interfacescount; i++) {
3244 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3252 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3253 utf_strlen(desc) + strlen("0");
3255 msg = MNEW(char, msglen);
3257 utf_sprint(msg, c->name);
3259 utf_sprint(msg + strlen(msg), name);
3260 utf_sprint(msg + strlen(msg), desc);
3263 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3265 MFREE(msg, char, msglen);
3271 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3273 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3278 /* XXX check access rights */
3284 /************************* Function: class_issubclass **************************
3286 Checks if sub is a descendant of super.
3288 *******************************************************************************/
3290 bool class_issubclass(classinfo *sub, classinfo *super)
3293 if (!sub) return false;
3294 if (sub == super) return true;
3295 sub = sub->super.cls;
3300 void class_showconstanti(classinfo *c, int ii)
3306 printf ("#%d: ", (int) i);
3308 switch (c->cptags [i]) {
3309 case CONSTANT_Class:
3310 printf("Classreference -> ");
3311 utf_display(((constant_classref*)e)->name);
3314 case CONSTANT_Fieldref:
3315 printf("Fieldref -> "); goto displayFMIi;
3316 case CONSTANT_Methodref:
3317 printf("Methodref -> "); goto displayFMIi;
3318 case CONSTANT_InterfaceMethodref:
3319 printf("InterfaceMethod -> "); goto displayFMIi;
3322 constant_FMIref *fmi = e;
3323 utf_display(fmi->classref->name);
3325 utf_display(fmi->name);
3327 utf_display(fmi->descriptor);
3331 case CONSTANT_String:
3332 printf("String -> ");
3335 case CONSTANT_Integer:
3336 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3338 case CONSTANT_Float:
3339 printf("Float -> %f", ((constant_float*)e)->value);
3341 case CONSTANT_Double:
3342 printf("Double -> %f", ((constant_double*)e)->value);
3346 u8 v = ((constant_long*)e)->value;
3348 printf("Long -> %ld", (long int) v);
3350 printf("Long -> HI: %ld, LO: %ld\n",
3351 (long int) v.high, (long int) v.low);
3355 case CONSTANT_NameAndType:
3357 constant_nameandtype *cnt = e;
3358 printf("NameAndType: ");
3359 utf_display(cnt->name);
3361 utf_display(cnt->descriptor);
3369 log_text("Invalid type of ConstantPool-Entry");
3377 void class_showconstantpool (classinfo *c)
3382 printf ("---- dump of constant pool ----\n");
3384 for (i=0; i<c->cpcount; i++) {
3385 printf ("#%d: ", (int) i);
3387 e = c -> cpinfos [i];
3390 switch (c -> cptags [i]) {
3391 case CONSTANT_Class:
3392 printf ("Classreference -> ");
3393 utf_display ( ((constant_classref*)e) -> name );
3396 case CONSTANT_Fieldref:
3397 printf ("Fieldref -> "); goto displayFMI;
3398 case CONSTANT_Methodref:
3399 printf ("Methodref -> "); goto displayFMI;
3400 case CONSTANT_InterfaceMethodref:
3401 printf ("InterfaceMethod -> "); goto displayFMI;
3404 constant_FMIref *fmi = e;
3405 utf_display ( fmi->classref->name );
3407 utf_display ( fmi->name);
3409 utf_display ( fmi->descriptor );
3413 case CONSTANT_String:
3414 printf ("String -> ");
3417 case CONSTANT_Integer:
3418 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3420 case CONSTANT_Float:
3421 printf ("Float -> %f", ((constant_float*)e) -> value);
3423 case CONSTANT_Double:
3424 printf ("Double -> %f", ((constant_double*)e) -> value);
3428 u8 v = ((constant_long*)e) -> value;
3430 printf ("Long -> %ld", (long int) v);
3432 printf ("Long -> HI: %ld, LO: %ld\n",
3433 (long int) v.high, (long int) v.low);
3437 case CONSTANT_NameAndType:
3439 constant_nameandtype *cnt = e;
3440 printf ("NameAndType: ");
3441 utf_display (cnt->name);
3443 utf_display (cnt->descriptor);
3447 printf ("Utf8 -> ");
3451 log_text("Invalid type of ConstantPool-Entry");
3462 /********** Function: class_showmethods (debugging only) *************/
3464 void class_showmethods (classinfo *c)
3468 printf ("--------- Fields and Methods ----------------\n");
3469 printf ("Flags: "); printflags (c->flags); printf ("\n");
3471 printf ("This: "); utf_display (c->name); printf ("\n");
3473 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3475 printf ("Index: %d\n", c->index);
3477 printf ("interfaces:\n");
3478 for (i=0; i < c-> interfacescount; i++) {
3480 utf_display (c -> interfaces[i].cls -> name);
3481 printf (" (%d)\n", c->interfaces[i].cls -> index);
3484 printf ("fields:\n");
3485 for (i=0; i < c -> fieldscount; i++) {
3486 field_display (&(c -> fields[i]));
3489 printf ("methods:\n");
3490 for (i=0; i < c -> methodscount; i++) {
3491 methodinfo *m = &(c->methods[i]);
3492 if ( !(m->flags & ACC_STATIC))
3493 printf ("vftblindex: %d ", m->vftblindex);
3495 method_display ( m );
3499 printf ("Virtual function table:\n");
3500 for (i=0; i<c->vftbl->vftbllength; i++) {
3501 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3507 /* loader_close ****************************************************************
3509 Frees all resources.
3511 *******************************************************************************/
3513 void loader_close(void)
3520 * These are local overrides for various environment variables in Emacs.
3521 * Please do not remove this and leave it at the end of the file, where
3522 * Emacs will automagically detect them.
3523 * ---------------------------------------------------------------------
3526 * indent-tabs-mode: t