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 3101 2005-07-24 20:18:34Z michi $
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 #if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
379 * On little endian ARM processors when using FPA, word order
380 * of doubles is still big endian. So take that into account
381 * here. When using VFP, word order of doubles follows byte
382 * order. (michi 2005/07/24)
384 for (i = 0; i < 4; i++)
385 buffer[3 - i] = suck_u1(cb);
386 for (i = 0; i < 4; i++)
387 buffer[7 - i] = suck_u1(cb);
389 for (i = 0; i < 8; i++)
390 buffer[7 - i] = suck_u1(cb);
391 #endif /* defined(__ARM__) && ... */
393 memcpy((u1*) (&d), buffer, 8);
395 suck_nbytes((u1*) (&d), cb, 8);
398 if (sizeof(double) != 8) {
399 *exceptionptr = new_exception_message(string_java_lang_InternalError,
400 "Incompatible double-format");
402 /* XXX should we exit in such a case? */
403 throw_exception_exit();
410 /************************** function suck_init *********************************
412 called once at startup, sets the searchpath for the classfiles
414 *******************************************************************************/
416 void suck_init(char *classpath)
424 classpath_info *lastcpi;
428 /* search for last classpath entry (only if there already some) */
430 if ((lastcpi = classpath_entries)) {
431 while (lastcpi->next)
432 lastcpi = lastcpi->next;
435 for (start = classpath; (*start) != '\0';) {
437 /* search for ':' delimiter to get the end of the current entry */
438 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
442 filenamelen = end - start;
444 if (filenamelen > 3) {
445 if (strncasecmp(end - 3, "zip", 3) == 0 ||
446 strncasecmp(end - 3, "jar", 3) == 0) {
451 /* save classpath entries as absolute pathnames */
456 if (*start != '/') { /* XXX fix me for win32 */
458 cwdlen = strlen(cwd) + strlen("/");
461 /* allocate memory for filename and fill it */
463 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
467 strcpy(filename, cwd);
468 strcat(filename, "/");
469 strncat(filename, start, filenamelen);
471 /* add cwd length to file length */
472 filenamelen += cwdlen;
475 strncpy(filename, start, filenamelen);
476 filename[filenamelen] = '\0';
482 #if defined(USE_ZLIB)
483 unzFile uf = unzOpen(filename);
486 cpi = NEW(classpath_info);
487 cpi->type = CLASSPATH_ARCHIVE;
490 cpi->path = filename;
491 cpi->pathlen = filenamelen;
495 throw_cacao_exception_exit(string_java_lang_InternalError,
496 "zip/jar files not supported");
500 cpi = NEW(classpath_info);
501 cpi->type = CLASSPATH_PATH;
504 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
505 filename[filenamelen] = '/';
506 filename[filenamelen + 1] = '\0';
510 cpi->path = filename;
511 cpi->pathlen = filenamelen;
514 /* attach current classpath entry */
517 if (!classpath_entries)
518 classpath_entries = cpi;
526 /* goto next classpath entry, skip ':' delimiter */
538 /* loader_load_all_classes *****************************************************
540 Loads all classes specified in the BOOTCLASSPATH.
542 *******************************************************************************/
544 void loader_load_all_classes(void)
549 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
550 #if defined(USE_ZLIB)
551 if (cpi->type == CLASSPATH_ARCHIVE) {
555 s = (unz_s *) cpi->uf;
556 ce = s->cacao_dir_list;
559 /* skip all entries in META-INF and .properties files */
561 if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
562 !strstr(ce->name->text, ".properties"))
563 c = load_class_bootstrap(ce->name);
570 #if defined(USE_ZLIB)
577 /* suck_start ******************************************************************
579 Returns true if classbuffer is already loaded or a file for the
580 specified class has succussfully been read in. All directories of
581 the searchpath are used to find the classfile (<classname>.class).
582 Returns false if no classfile is found and writes an error message.
584 *******************************************************************************/
586 classbuffer *suck_start(classinfo *c)
598 /* initialize return value */
603 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
604 filename = MNEW(char, filenamelen);
606 utf_sprint(filename, c->name);
607 strcat(filename, ".class");
609 /* walk through all classpath entries */
611 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
612 #if defined(USE_ZLIB)
613 if (cpi->type == CLASSPATH_ARCHIVE) {
615 #if defined(USE_THREADS)
616 /* enter a monitor on zip/jar archives */
618 builtin_monitorenter((java_objectheader *) cpi);
621 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
622 unz_file_info file_info;
624 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
625 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
626 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
627 cb = NEW(classbuffer);
629 cb->size = file_info.uncompressed_size;
630 cb->data = MNEW(u1, cb->size);
631 cb->pos = cb->data - 1;
633 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
635 if (len != cb->size) {
637 log_text("Error while unzipping");
644 log_text("Error while opening file in archive");
648 log_text("Error while retrieving fileinfo");
651 unzCloseCurrentFile(cpi->uf);
653 #if defined(USE_THREADS)
654 /* leave the monitor */
656 builtin_monitorexit((java_objectheader *) cpi);
660 #endif /* defined(USE_ZLIB) */
662 path = MNEW(char, cpi->pathlen + filenamelen);
663 strcpy(path, cpi->path);
664 strcat(path, filename);
666 classfile = fopen(path, "r");
668 if (classfile) { /* file exists */
669 if (!stat(path, &buffer)) { /* read classfile data */
670 cb = NEW(classbuffer);
672 cb->size = buffer.st_size;
673 cb->data = MNEW(u1, cb->size);
674 cb->pos = cb->data - 1;
676 /* read class data */
677 len = fread(cb->data, 1, cb->size, classfile);
679 if (len != buffer.st_size) {
681 /* if (ferror(classfile)) { */
690 MFREE(path, char, cpi->pathlen + filenamelen);
691 #if defined(USE_ZLIB)
698 dolog("Warning: Can not open class file '%s'", filename);
700 if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
708 MFREE(filename, char, filenamelen);
714 /************************** function suck_stop *********************************
716 frees memory for buffer with classfile data.
717 Caution: this function may only be called if buffer has been allocated
718 by suck_start with reading a file
720 *******************************************************************************/
722 void suck_stop(classbuffer *cb)
726 MFREE(cb->data, u1, cb->size);
727 FREE(cb, classbuffer);
731 /******************************************************************************/
732 /******************* Some support functions ***********************************/
733 /******************************************************************************/
735 void fprintflags (FILE *fp, u2 f)
737 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
738 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
739 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
740 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
741 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
742 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
743 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
744 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
745 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
746 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
747 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
751 /********** internal function: printflags (only for debugging) ***************/
753 void printflags(u2 f)
755 fprintflags(stdout,f);
759 /********************** Function: skipattributebody ****************************
761 skips an attribute after the 16 bit reference to attribute_name has already
764 *******************************************************************************/
766 static bool skipattributebody(classbuffer *cb)
770 if (!check_classbuffer_size(cb, 4))
775 if (!check_classbuffer_size(cb, len))
778 skip_nbytes(cb, len);
784 /************************* Function: skipattributes ****************************
786 skips num attribute structures
788 *******************************************************************************/
790 static bool skipattributes(classbuffer *cb, u4 num)
795 for (i = 0; i < num; i++) {
796 if (!check_classbuffer_size(cb, 2 + 4))
802 if (!check_classbuffer_size(cb, len))
805 skip_nbytes(cb, len);
812 /* load_constantpool ***********************************************************
814 Loads the constantpool of a class, the entries are transformed into
815 a simpler format by resolving references (a detailed overview of
816 the compact structures can be found in global.h).
818 *******************************************************************************/
820 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
823 /* The following structures are used to save information which cannot be
824 processed during the first pass. After the complete constantpool has
825 been traversed the references can be resolved.
826 (only in specific order) */
828 /* CONSTANT_Class entries */
829 typedef struct forward_class {
830 struct forward_class *next;
835 /* CONSTANT_String */
836 typedef struct forward_string {
837 struct forward_string *next;
842 /* CONSTANT_NameAndType */
843 typedef struct forward_nameandtype {
844 struct forward_nameandtype *next;
848 } forward_nameandtype;
850 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
851 typedef struct forward_fieldmethint {
852 struct forward_fieldmethint *next;
856 u2 nameandtype_index;
857 } forward_fieldmethint;
863 forward_class *forward_classes = NULL;
864 forward_string *forward_strings = NULL;
865 forward_nameandtype *forward_nameandtypes = NULL;
866 forward_fieldmethint *forward_fieldmethints = NULL;
870 forward_nameandtype *nfn;
871 forward_fieldmethint *nff;
879 /* number of entries in the constant_pool table plus one */
880 if (!check_classbuffer_size(cb, 2))
883 cpcount = c->cpcount = suck_u2(cb);
885 /* allocate memory */
886 cptags = c->cptags = MNEW(u1, cpcount);
887 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
890 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
894 #if defined(STATISTICS)
896 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
899 /* initialize constantpool */
900 for (idx = 0; idx < cpcount; idx++) {
901 cptags[idx] = CONSTANT_UNUSED;
906 /******* first pass *******/
907 /* entries which cannot be resolved now are written into
908 temporary structures and traversed again later */
911 while (idx < cpcount) {
914 /* get constant type */
915 if (!check_classbuffer_size(cb, 1))
922 nfc = DNEW(forward_class);
924 nfc->next = forward_classes;
925 forward_classes = nfc;
927 nfc->thisindex = idx;
928 /* reference to CONSTANT_NameAndType */
929 if (!check_classbuffer_size(cb, 2))
932 nfc->name_index = suck_u2(cb);
937 case CONSTANT_String:
938 nfs = DNEW(forward_string);
940 nfs->next = forward_strings;
941 forward_strings = nfs;
943 nfs->thisindex = idx;
945 /* reference to CONSTANT_Utf8_info with string characters */
946 if (!check_classbuffer_size(cb, 2))
949 nfs->string_index = suck_u2(cb);
954 case CONSTANT_NameAndType:
955 nfn = DNEW(forward_nameandtype);
957 nfn->next = forward_nameandtypes;
958 forward_nameandtypes = nfn;
960 nfn->thisindex = idx;
962 if (!check_classbuffer_size(cb, 2 + 2))
965 /* reference to CONSTANT_Utf8_info containing simple name */
966 nfn->name_index = suck_u2(cb);
968 /* reference to CONSTANT_Utf8_info containing field or method
970 nfn->sig_index = suck_u2(cb);
975 case CONSTANT_Fieldref:
976 case CONSTANT_Methodref:
977 case CONSTANT_InterfaceMethodref:
978 nff = DNEW(forward_fieldmethint);
980 nff->next = forward_fieldmethints;
981 forward_fieldmethints = nff;
983 nff->thisindex = idx;
987 if (!check_classbuffer_size(cb, 2 + 2))
990 /* class or interface type that contains the declaration of the
992 nff->class_index = suck_u2(cb);
994 /* name and descriptor of the field or method */
995 nff->nameandtype_index = suck_u2(cb);
1000 case CONSTANT_Integer: {
1001 constant_integer *ci = NEW(constant_integer);
1003 #if defined(STATISTICS)
1005 count_const_pool_len += sizeof(constant_integer);
1008 if (!check_classbuffer_size(cb, 4))
1011 ci->value = suck_s4(cb);
1012 cptags[idx] = CONSTANT_Integer;
1019 case CONSTANT_Float: {
1020 constant_float *cf = NEW(constant_float);
1022 #if defined(STATISTICS)
1024 count_const_pool_len += sizeof(constant_float);
1027 if (!check_classbuffer_size(cb, 4))
1030 cf->value = suck_float(cb);
1031 cptags[idx] = CONSTANT_Float;
1038 case CONSTANT_Long: {
1039 constant_long *cl = NEW(constant_long);
1041 #if defined(STATISTICS)
1043 count_const_pool_len += sizeof(constant_long);
1046 if (!check_classbuffer_size(cb, 8))
1049 cl->value = suck_s8(cb);
1050 cptags[idx] = CONSTANT_Long;
1053 if (idx > cpcount) {
1055 new_classformaterror(c, "Invalid constant pool entry");
1061 case CONSTANT_Double: {
1062 constant_double *cd = NEW(constant_double);
1064 #if defined(STATISTICS)
1066 count_const_pool_len += sizeof(constant_double);
1069 if (!check_classbuffer_size(cb, 8))
1072 cd->value = suck_double(cb);
1073 cptags[idx] = CONSTANT_Double;
1076 if (idx > cpcount) {
1078 new_classformaterror(c, "Invalid constant pool entry");
1084 case CONSTANT_Utf8: {
1087 /* number of bytes in the bytes array (not string-length) */
1088 if (!check_classbuffer_size(cb, 2))
1091 length = suck_u2(cb);
1092 cptags[idx] = CONSTANT_Utf8;
1094 /* validate the string */
1095 if (!check_classbuffer_size(cb, length))
1099 !is_valid_utf((char *) (cb->pos + 1),
1100 (char *) (cb->pos + 1 + length))) {
1101 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1104 /* insert utf-string into the utf-symboltable */
1105 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1107 /* skip bytes of the string (buffer size check above) */
1108 skip_nbytes(cb, length);
1115 new_classformaterror(c, "Illegal constant pool type");
1121 /* resolve entries in temporary structures */
1123 while (forward_classes) {
1125 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1127 if (opt_verify && !is_valid_name_utf(name)) {
1129 new_classformaterror(c, "Class reference with invalid name");
1133 /* add all class references to the descriptor_pool */
1135 if (!descriptor_pool_add_class(descpool, name))
1138 cptags[forward_classes->thisindex] = CONSTANT_Class;
1143 if (!(tc = load_class_bootstrap(name)))
1146 /* link the class later, because we cannot link the class currently
1148 list_addfirst(&unlinkedclasses, tc);
1151 /* the classref is created later */
1152 cpinfos[forward_classes->thisindex] = name;
1154 nfc = forward_classes;
1155 forward_classes = forward_classes->next;
1158 while (forward_strings) {
1160 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1162 /* resolve utf-string */
1163 cptags[forward_strings->thisindex] = CONSTANT_String;
1164 cpinfos[forward_strings->thisindex] = text;
1166 nfs = forward_strings;
1167 forward_strings = forward_strings->next;
1170 while (forward_nameandtypes) {
1171 constant_nameandtype *cn = NEW(constant_nameandtype);
1173 #if defined(STATISTICS)
1175 count_const_pool_len += sizeof(constant_nameandtype);
1178 /* resolve simple name and descriptor */
1179 cn->name = class_getconstant(c,
1180 forward_nameandtypes->name_index,
1183 cn->descriptor = class_getconstant(c,
1184 forward_nameandtypes->sig_index,
1189 if (!is_valid_name_utf(cn->name)) {
1191 new_classformaterror(c,
1192 "Illegal Field name \"%s\"",
1198 /* disallow referencing <clinit> among others */
1199 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1201 new_exception_utfmessage(string_java_lang_InternalError,
1207 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1208 cpinfos[forward_nameandtypes->thisindex] = cn;
1210 nfn = forward_nameandtypes;
1211 forward_nameandtypes = forward_nameandtypes->next;
1214 while (forward_fieldmethints) {
1215 constant_nameandtype *nat;
1216 constant_FMIref *fmi = NEW(constant_FMIref);
1218 #if defined(STATISTICS)
1220 count_const_pool_len += sizeof(constant_FMIref);
1222 /* resolve simple name and descriptor */
1224 nat = class_getconstant(c,
1225 forward_fieldmethints->nameandtype_index,
1226 CONSTANT_NameAndType);
1228 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
1230 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
1233 /* the classref is created later */
1235 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
1236 fmi->name = nat->name;
1237 fmi->descriptor = nat->descriptor;
1239 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1240 cpinfos[forward_fieldmethints->thisindex] = fmi;
1242 nff = forward_fieldmethints;
1243 forward_fieldmethints = forward_fieldmethints->next;
1246 /* everything was ok */
1252 /* load_field ******************************************************************
1254 Load everything about a class field from the class file and fill a
1255 'fieldinfo' structure. For static fields, space in the data segment
1258 *******************************************************************************/
1260 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1262 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
1267 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1272 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1275 f->flags = suck_u2(cb);
1277 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1282 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1286 f->parseddesc = NULL;
1288 if (!descriptor_pool_add(descpool, u, NULL))
1293 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1294 *exceptionptr = new_classformaterror(c,
1295 "Illegal Field name \"%s\"",
1300 /* check flag consistency */
1301 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1303 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1304 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1306 new_classformaterror(c,
1307 "Illegal field modifiers: 0x%X",
1312 if (c->flags & ACC_INTERFACE) {
1313 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1314 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1315 f->flags & ACC_TRANSIENT) {
1317 new_classformaterror(c,
1318 "Illegal field modifiers: 0x%X",
1325 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1326 f->offset = 0; /* offset from start of object */
1331 case TYPE_INT: f->value.i = 0; break;
1332 case TYPE_FLOAT: f->value.f = 0.0; break;
1333 case TYPE_DOUBLE: f->value.d = 0.0; break;
1334 case TYPE_ADDRESS: f->value.a = NULL; break;
1337 f->value.l = 0; break;
1339 f->value.l.low = 0; f->value.l.high = 0; break;
1343 /* read attributes */
1344 if (!check_classbuffer_size(cb, 2))
1347 attrnum = suck_u2(cb);
1348 for (i = 0; i < attrnum; i++) {
1349 if (!check_classbuffer_size(cb, 2))
1352 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1355 if (u == utf_ConstantValue) {
1356 if (!check_classbuffer_size(cb, 4 + 2))
1359 /* check attribute length */
1360 if (suck_u4(cb) != 2) {
1362 new_classformaterror(c, "Wrong size for VALUE attribute");
1366 /* constant value attribute */
1367 if (pindex != field_load_NOVALUE) {
1369 new_classformaterror(c,
1370 "Multiple ConstantValue attributes");
1374 /* index of value in constantpool */
1375 pindex = suck_u2(cb);
1377 /* initialize field with value from constantpool */
1380 constant_integer *ci;
1382 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1385 f->value.i = ci->value;
1392 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1395 f->value.l = cl->value;
1402 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1405 f->value.f = cf->value;
1410 constant_double *cd;
1412 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1415 f->value.d = cd->value;
1420 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1423 /* create javastring from compressed utf8-string */
1424 f->value.a = literalstring_new(u);
1428 log_text("Invalid Constant - Type");
1432 /* unknown attribute */
1433 if (!skipattributebody(cb))
1438 /* everything was ok */
1444 /* load_method *****************************************************************
1446 Loads a method from the class file and fills an existing
1447 'methodinfo' structure. For native methods, the function pointer
1448 field is set to the real function pointer, for JavaVM methods a
1449 pointer to the compiler is used preliminarily.
1451 *******************************************************************************/
1453 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1464 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1465 initObjectLock(&m->header);
1470 count_all_methods++;
1473 m->thrownexceptionscount = 0;
1474 m->linenumbercount = 0;
1477 m->nativelyoverloaded = false;
1479 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1482 m->flags = suck_u2(cb);
1484 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1489 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1493 m->parseddesc = NULL;
1495 if (!descriptor_pool_add(descpool, u, &argcount))
1499 if (!is_valid_name_utf(m->name)) {
1500 log_text("Method with invalid name");
1504 if (m->name->text[0] == '<' &&
1505 m->name != utf_init && m->name != utf_clinit) {
1506 log_text("Method with invalid special name");
1511 if (!(m->flags & ACC_STATIC))
1512 argcount++; /* count the 'this' argument */
1515 if (argcount > 255) {
1517 new_classformaterror(c, "Too many arguments in signature");
1521 /* check flag consistency */
1522 if (m->name != utf_clinit) {
1523 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1525 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1527 new_classformaterror(c,
1528 "Illegal method modifiers: 0x%X",
1533 if (m->flags & ACC_ABSTRACT) {
1534 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1535 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1537 new_classformaterror(c,
1538 "Illegal method modifiers: 0x%X",
1544 if (c->flags & ACC_INTERFACE) {
1545 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1547 new_classformaterror(c,
1548 "Illegal method modifiers: 0x%X",
1554 if (m->name == utf_init) {
1555 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1556 ACC_NATIVE | ACC_ABSTRACT)) {
1557 log_text("Instance initialization method has invalid flags set");
1565 m->basicblockcount = 0;
1566 m->basicblocks = NULL;
1567 m->basicblockindex = NULL;
1568 m->instructioncount = 0;
1569 m->instructions = NULL;
1572 m->exceptiontable = NULL;
1573 m->stubroutine = NULL;
1575 m->entrypoint = NULL;
1576 m->methodUsed = NOTUSED;
1579 m->subRedefsUsed = 0;
1583 if (!check_classbuffer_size(cb, 2))
1586 attrnum = suck_u2(cb);
1587 for (i = 0; i < attrnum; i++) {
1590 if (!check_classbuffer_size(cb, 2))
1593 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1596 if (aname == utf_Code) {
1597 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1599 new_classformaterror(c,
1600 "Code attribute in native or abstract methods");
1607 new_classformaterror(c, "Multiple Code attributes");
1612 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1616 m->maxstack = suck_u2(cb);
1617 m->maxlocals = suck_u2(cb);
1619 if (m->maxlocals < argcount) {
1621 new_classformaterror(c, "Arguments can't fit into locals");
1626 if (!check_classbuffer_size(cb, 4))
1629 m->jcodelength = suck_u4(cb);
1631 if (m->jcodelength == 0) {
1633 new_classformaterror(c, "Code of a method has length 0");
1638 if (m->jcodelength > 65535) {
1640 new_classformaterror(c,
1641 "Code of a method longer than 65535 bytes");
1646 if (!check_classbuffer_size(cb, m->jcodelength))
1649 m->jcode = MNEW(u1, m->jcodelength);
1650 suck_nbytes(m->jcode, cb, m->jcodelength);
1652 if (!check_classbuffer_size(cb, 2))
1655 m->exceptiontablelength = suck_u2(cb);
1656 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1659 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1661 #if defined(STATISTICS)
1663 count_vmcode_len += m->jcodelength + 18;
1664 count_extable_len += 8 * m->exceptiontablelength;
1668 for (j = 0; j < m->exceptiontablelength; j++) {
1670 m->exceptiontable[j].startpc = suck_u2(cb);
1671 m->exceptiontable[j].endpc = suck_u2(cb);
1672 m->exceptiontable[j].handlerpc = suck_u2(cb);
1676 m->exceptiontable[j].catchtype.any = NULL;
1679 /* the classref is created later */
1680 if (!(m->exceptiontable[j].catchtype.any =
1681 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1686 if (!check_classbuffer_size(cb, 2))
1689 codeattrnum = suck_u2(cb);
1691 for (; codeattrnum > 0; codeattrnum--) {
1694 if (!check_classbuffer_size(cb, 2))
1697 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1700 if (caname == utf_LineNumberTable) {
1703 if (!check_classbuffer_size(cb, 4 + 2))
1707 m->linenumbercount = suck_u2(cb);
1709 if (!check_classbuffer_size(cb,
1710 (2 + 2) * m->linenumbercount))
1713 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1715 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1716 m->linenumbers[lncid].start_pc = suck_u2(cb);
1717 m->linenumbers[lncid].line_number = suck_u2(cb);
1721 if (!skipattributes(cb, codeattrnum))
1727 if (!skipattributebody(cb))
1732 } else if (aname == utf_Exceptions) {
1735 if (m->thrownexceptions) {
1737 new_classformaterror(c, "Multiple Exceptions attributes");
1741 if (!check_classbuffer_size(cb, 4 + 2))
1744 suck_u4(cb); /* length */
1745 m->thrownexceptionscount = suck_u2(cb);
1747 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1750 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1752 for (j = 0; j < m->thrownexceptionscount; j++) {
1753 /* the classref is created later */
1754 if (!((m->thrownexceptions)[j].any =
1755 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1760 if (!skipattributebody(cb))
1765 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1766 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1771 /* everything was ok */
1777 /* load_attribute **************************************************************
1779 Read attributes from classfile.
1781 *******************************************************************************/
1783 static bool load_attributes(classbuffer *cb, u4 num)
1791 for (i = 0; i < num; i++) {
1792 /* retrieve attribute name */
1793 if (!check_classbuffer_size(cb, 2))
1796 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1799 if (aname == utf_InnerClasses) {
1800 /* innerclasses attribute */
1801 if (c->innerclass) {
1803 new_classformaterror(c, "Multiple InnerClasses attributes");
1807 if (!check_classbuffer_size(cb, 4 + 2))
1810 /* skip attribute length */
1813 /* number of records */
1814 c->innerclasscount = suck_u2(cb);
1816 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1819 /* allocate memory for innerclass structure */
1820 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1822 for (j = 0; j < c->innerclasscount; j++) {
1823 /* The innerclass structure contains a class with an encoded
1824 name, its defining scope, its simple name and a bitmask of
1825 the access flags. If an inner class is not a member, its
1826 outer_class is NULL, if a class is anonymous, its name is
1829 innerclassinfo *info = c->innerclass + j;
1831 info->inner_class.ref =
1832 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1833 info->outer_class.ref =
1834 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1836 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1837 info->flags = suck_u2(cb);
1840 } else if (aname == utf_SourceFile) {
1841 if (!check_classbuffer_size(cb, 4 + 2))
1844 if (suck_u4(cb) != 2) {
1846 new_classformaterror(c, "Wrong size for VALUE attribute");
1850 if (c->sourcefile) {
1852 new_classformaterror(c, "Multiple SourceFile attributes");
1856 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1860 /* unknown attribute */
1861 if (!skipattributebody(cb))
1870 /* load_class_from_sysloader ***************************************************
1872 Load the class with the given name using the system class loader
1875 name.............the classname
1878 the loaded class, or
1879 NULL if an exception has been thrown
1881 *******************************************************************************/
1883 classinfo *load_class_from_sysloader(utf *name)
1886 java_objectheader *cl;
1889 #ifdef LOADER_VERBOSE
1890 char logtext[MAXLOGTEXT];
1891 LOADER_INDENT(logtext);
1892 sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1893 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1897 LOADER_ASSERT(class_java_lang_Object);
1898 LOADER_ASSERT(class_java_lang_ClassLoader);
1899 LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1901 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1902 utf_getSystemClassLoader,
1903 utf_void__java_lang_ClassLoader,
1904 class_java_lang_Object,
1910 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1915 r = load_class_from_classloader(name, cl);
1921 /* load_class_from_classloader *************************************************
1923 Load the class with the given name using the given user-defined class loader.
1926 name.............the classname
1927 cl...............user-defined class loader
1930 the loaded class, or
1931 NULL if an exception has been thrown
1933 *******************************************************************************/
1935 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1939 #ifdef LOADER_VERBOSE
1940 char logtext[MAXLOGTEXT];
1941 LOADER_INDENT(logtext);
1942 strcat(logtext,"load_class_from_classloader(");
1943 utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1944 if (!cl) strcat(logtext,"<bootstrap>");
1945 else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1946 else strcat(logtext,"<unknown class>");
1947 strcat(logtext,")");
1951 LOADER_ASSERT(name);
1953 /* lookup if this class has already been loaded */
1955 r = classcache_lookup(cl, name);
1957 #ifdef LOADER_VERBOSE
1959 dolog(" cached -> %p",(void*)r);
1965 /* if other class loader than bootstrap, call it */
1970 /* handle array classes */
1971 if (name->text[0] == '[') {
1977 utf_ptr = name->text + 1;
1978 len = name->blength - 1;
1986 /* load the component class */
1987 u = utf_new(utf_ptr, len);
1989 if (!(comp = load_class_from_classloader(u, cl))) {
1994 /* create the array class */
1995 r = class_array_of(comp, false);
1999 /* primitive array classes are loaded by the bootstrap loader */
2001 r = load_class_bootstrap(name);
2007 LOADER_ASSERT(class_java_lang_Object);
2009 lc = class_resolveclassmethod(cl->vftbl->class,
2011 utf_java_lang_String__java_lang_Class,
2012 class_java_lang_Object,
2016 return false; /* exception */
2019 r = (classinfo *) asm_calljavafunction(lc,
2021 javastring_new_slash_to_dot(name),
2026 /* store this class in the loaded class cache */
2027 /* If another class with the same (initloader,name) pair has been */
2028 /* stored earlier it will be returned by classcache_store */
2029 /* In this case classcache_store may not free the class because it*/
2030 /* has already been exposed to Java code which may have kept */
2031 /* references to that class. */
2032 classinfo *c = classcache_store(cl,r,false);
2034 /* exception, free the loaded class */
2045 r = load_class_bootstrap(name);
2052 /* load_class_bootstrap ********************************************************
2054 Load the class with the given name using the bootstrap class loader.
2057 name.............the classname
2060 loaded classinfo, or
2061 NULL if an exception has been thrown
2064 load_class_bootstrap is synchronized. It can be treated as an
2067 *******************************************************************************/
2069 classinfo *load_class_bootstrap(utf *name)
2074 #ifdef LOADER_VERBOSE
2075 char logtext[MAXLOGTEXT];
2080 LOADER_ASSERT(name);
2083 /* lookup if this class has already been loaded */
2085 if ((r = classcache_lookup(NULL, name)))
2088 #ifdef LOADER_VERBOSE
2089 LOADER_INDENT(logtext);
2090 strcat(logtext,"load_class_bootstrap(");
2091 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2095 /* create the classinfo */
2097 c = class_create_classinfo(name);
2099 /* handle array classes */
2101 if (name->text[0] == '[') {
2102 c = load_newly_created_array(c, NULL);
2104 goto return_exception;
2105 LOADER_ASSERT(c->loaded);
2110 #if defined(STATISTICS)
2113 if (getcompilingtime)
2114 compilingtime_stop();
2117 loadingtime_start();
2120 /* load classdata, throw exception on error */
2122 if ((cb = suck_start(c)) == NULL) {
2123 /* this normally means, the classpath was not set properly */
2125 if (name == utf_java_lang_Object)
2126 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2127 "java/lang/Object");
2130 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2132 goto return_exception;
2135 /* load the class from the buffer */
2137 r = load_class_from_classbuffer(cb);
2143 #if defined(STATISTICS)
2149 if (getcompilingtime)
2150 compilingtime_start();
2154 /* the class could not be loaded, free the classinfo struct */
2159 /* store this class in the loaded class cache */
2160 /* this step also checks the loading constraints */
2161 /* If the class has been loaded before, the */
2162 /* earlier loaded class is returned. */
2163 classinfo *res = classcache_store(NULL,c,true);
2172 goto return_exception;
2186 /* load_class_from_classbuffer *************************************************
2188 Loads everything interesting about a class from the class file. The
2189 'classinfo' structure must have been allocated previously.
2191 The super class and the interfaces implemented by this class need
2192 not be loaded. The link is set later by the function 'class_link'.
2194 The loaded class is removed from the list 'unloadedclasses' and
2195 added to the list 'unlinkedclasses'.
2198 This function is NOT synchronized!
2200 *******************************************************************************/
2202 classinfo *load_class_from_classbuffer(classbuffer *cb)
2210 descriptor_pool *descpool;
2211 #if defined(STATISTICS)
2215 #ifdef LOADER_VERBOSE
2216 char logtext[MAXLOGTEXT];
2219 /* get the classbuffer's class */
2223 /* maybe the class is already loaded */
2228 #ifdef LOADER_VERBOSE
2229 LOADER_INDENT(logtext);
2230 strcat(logtext,"load_class_from_classbuffer(");
2231 utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2236 #if defined(STATISTICS)
2238 count_class_loads++;
2241 /* output for debugging purposes */
2244 log_message_class("Loading class: ", c);
2246 /* mark start of dump memory area */
2248 dumpsize = dump_size();
2250 /* class is somewhat loaded */
2254 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2255 goto return_exception;
2257 /* check signature */
2259 if (suck_u4(cb) != MAGIC) {
2260 *exceptionptr = new_classformaterror(c, "Bad magic number");
2262 goto return_exception;
2270 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2272 new_unsupportedclassversionerror(c,
2273 "Unsupported major.minor version %d.%d",
2276 goto return_exception;
2279 /* create a new descriptor pool */
2281 descpool = descriptor_pool_new(c);
2283 /* load the constant pool */
2285 if (!load_constantpool(cb, descpool))
2286 goto return_exception;
2289 c->erroneous_state = 0;
2290 c->initializing_thread = 0;
2292 c->classUsed = NOTUSED; /* not used initially CO-RT */
2297 if (!check_classbuffer_size(cb, 2))
2298 goto return_exception;
2300 c->flags = suck_u2(cb);
2302 /* check ACC flags consistency */
2304 if (c->flags & ACC_INTERFACE) {
2305 if (!(c->flags & ACC_ABSTRACT)) {
2306 /* We work around this because interfaces in JDK 1.1 are
2307 * not declared abstract. */
2309 c->flags |= ACC_ABSTRACT;
2312 if (c->flags & ACC_FINAL) {
2314 new_classformaterror(c,
2315 "Illegal class modifiers: 0x%X", c->flags);
2317 goto return_exception;
2320 if (c->flags & ACC_SUPER) {
2321 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2325 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2327 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2329 goto return_exception;
2332 if (!check_classbuffer_size(cb, 2 + 2))
2333 goto return_exception;
2338 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2339 goto return_exception;
2341 if (c->name == utf_not_named_yet) {
2342 /* we finally have a name for this class */
2344 class_set_packagename(c);
2346 } else if (name != c->name) {
2350 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2351 utf_strlen(name) + strlen(")") + strlen("0");
2353 msg = MNEW(char, msglen);
2355 utf_sprint(msg, c->name);
2356 strcat(msg, " (wrong name: ");
2357 utf_strcat(msg, name);
2361 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2363 MFREE(msg, char, msglen);
2365 goto return_exception;
2368 /* retrieve superclass */
2370 c->super.any = NULL;
2371 if ((i = suck_u2(cb))) {
2372 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2373 goto return_exception;
2375 /* java.lang.Object may not have a super class. */
2377 if (c->name == utf_java_lang_Object) {
2379 new_exception_message(string_java_lang_ClassFormatError,
2380 "java.lang.Object with superclass");
2382 goto return_exception;
2385 /* Interfaces must have java.lang.Object as super class. */
2387 if ((c->flags & ACC_INTERFACE) &&
2388 supername != utf_java_lang_Object) {
2390 new_exception_message(string_java_lang_ClassFormatError,
2391 "Interfaces must have java.lang.Object as superclass");
2393 goto return_exception;
2399 /* This is only allowed for java.lang.Object. */
2401 if (c->name != utf_java_lang_Object) {
2402 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2404 goto return_exception;
2408 /* retrieve interfaces */
2410 if (!check_classbuffer_size(cb, 2))
2411 goto return_exception;
2413 c->interfacescount = suck_u2(cb);
2415 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2416 goto return_exception;
2418 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2419 for (i = 0; i < c->interfacescount; i++) {
2420 /* the classrefs are created later */
2421 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2422 goto return_exception;
2426 if (!check_classbuffer_size(cb, 2))
2427 goto return_exception;
2429 c->fieldscount = suck_u2(cb);
2430 c->fields = GCNEW(fieldinfo, c->fieldscount);
2431 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2432 for (i = 0; i < c->fieldscount; i++) {
2433 if (!load_field(cb, &(c->fields[i]),descpool))
2434 goto return_exception;
2438 if (!check_classbuffer_size(cb, 2))
2439 goto return_exception;
2441 c->methodscount = suck_u2(cb);
2442 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2443 c->methods = MNEW(methodinfo, c->methodscount);
2444 for (i = 0; i < c->methodscount; i++) {
2445 if (!load_method(cb, &(c->methods[i]),descpool))
2446 goto return_exception;
2449 /* create the class reference table */
2452 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2454 /* allocate space for the parsed descriptors */
2456 descriptor_pool_alloc_parsed_descriptors(descpool);
2458 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2460 #if defined(STATISTICS)
2462 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2463 count_classref_len += classrefsize;
2464 count_parsed_desc_len += descsize;
2468 /* put the classrefs in the constant pool */
2469 for (i = 0; i < c->cpcount; i++) {
2470 if (c->cptags[i] == CONSTANT_Class) {
2471 utf *name = (utf *) c->cpinfos[i];
2472 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2476 /* set the super class reference */
2479 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2481 goto return_exception;
2484 /* set the super interfaces references */
2486 for (i = 0; i < c->interfacescount; i++) {
2487 c->interfaces[i].ref =
2488 descriptor_pool_lookup_classref(descpool,
2489 (utf *) c->interfaces[i].any);
2490 if (!c->interfaces[i].ref)
2491 goto return_exception;
2494 /* parse field descriptors */
2496 for (i = 0; i < c->fieldscount; i++) {
2497 c->fields[i].parseddesc =
2498 descriptor_pool_parse_field_descriptor(descpool,
2499 c->fields[i].descriptor);
2500 if (!c->fields[i].parseddesc)
2501 goto return_exception;
2504 /* parse method descriptors */
2506 for (i = 0; i < c->methodscount; i++) {
2507 methodinfo *m = &c->methods[i];
2509 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2510 m->flags, class_get_self_classref(m->class));
2512 goto return_exception;
2514 for (j = 0; j < m->exceptiontablelength; j++) {
2515 if (!m->exceptiontable[j].catchtype.any)
2517 if ((m->exceptiontable[j].catchtype.ref =
2518 descriptor_pool_lookup_classref(descpool,
2519 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2520 goto return_exception;
2523 for (j = 0; j < m->thrownexceptionscount; j++) {
2524 if (!m->thrownexceptions[j].any)
2526 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2527 (utf *) m->thrownexceptions[j].any)) == NULL)
2528 goto return_exception;
2532 /* parse the loaded descriptors */
2534 for (i = 0; i < c->cpcount; i++) {
2535 constant_FMIref *fmi;
2538 switch (c->cptags[i]) {
2539 case CONSTANT_Fieldref:
2540 fmi = (constant_FMIref *) c->cpinfos[i];
2541 fmi->parseddesc.fd =
2542 descriptor_pool_parse_field_descriptor(descpool,
2544 if (!fmi->parseddesc.fd)
2545 goto return_exception;
2546 index = (int) (size_t) fmi->classref;
2548 (constant_classref *) class_getconstant(c, index,
2551 goto return_exception;
2553 case CONSTANT_Methodref:
2554 case CONSTANT_InterfaceMethodref:
2555 fmi = (constant_FMIref *) c->cpinfos[i];
2556 index = (int) (size_t) fmi->classref;
2558 (constant_classref *) class_getconstant(c, index,
2561 goto return_exception;
2562 fmi->parseddesc.md =
2563 descriptor_pool_parse_method_descriptor(descpool,
2567 if (!fmi->parseddesc.md)
2568 goto return_exception;
2573 /* Check if all fields and methods can be uniquely
2574 * identified by (name,descriptor). */
2577 /* We use a hash table here to avoid making the
2578 * average case quadratic in # of methods, fields.
2580 static int shift = 0;
2582 u2 *next; /* for chaining colliding hash entries */
2588 /* Allocate hashtable */
2589 len = c->methodscount;
2590 if (len < c->fieldscount) len = c->fieldscount;
2592 hashtab = MNEW(u2,(hashlen + len));
2593 next = hashtab + hashlen;
2595 /* Determine bitshift (to get good hash values) */
2605 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2607 for (i = 0; i < c->fieldscount; ++i) {
2608 fieldinfo *fi = c->fields + i;
2610 /* It's ok if we lose bits here */
2611 index = ((((size_t) fi->name) +
2612 ((size_t) fi->descriptor)) >> shift) % hashlen;
2614 if ((old = hashtab[index])) {
2618 if (c->fields[old].name == fi->name &&
2619 c->fields[old].descriptor == fi->descriptor) {
2621 new_classformaterror(c,
2622 "Repetitive field name/signature");
2624 goto return_exception;
2626 } while ((old = next[old]));
2628 hashtab[index] = i + 1;
2632 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2634 for (i = 0; i < c->methodscount; ++i) {
2635 methodinfo *mi = c->methods + i;
2637 /* It's ok if we lose bits here */
2638 index = ((((size_t) mi->name) +
2639 ((size_t) mi->descriptor)) >> shift) % hashlen;
2643 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2644 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2648 if ((old = hashtab[index])) {
2652 if (c->methods[old].name == mi->name &&
2653 c->methods[old].descriptor == mi->descriptor) {
2655 new_classformaterror(c,
2656 "Repetitive method name/signature");
2658 goto return_exception;
2660 } while ((old = next[old]));
2662 hashtab[index] = i + 1;
2665 MFREE(hashtab, u2, (hashlen + len));
2668 #if defined(STATISTICS)
2670 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2671 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2672 count_class_infos += sizeof(methodinfo) * c->methodscount;
2676 /* load attribute structures */
2678 if (!check_classbuffer_size(cb, 2))
2679 goto return_exception;
2681 if (!load_attributes(cb, suck_u2(cb)))
2682 goto return_exception;
2685 /* Pre java 1.5 version don't check this. This implementation is like
2686 java 1.5 do it: for class file version 45.3 we don't check it, older
2687 versions are checked.
2689 if ((ma == 45 && mi > 3) || ma > 45) {
2690 /* check if all data has been read */
2691 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2693 if (classdata_left > 0) {
2695 new_classformaterror(c, "Extra bytes at the end of class file");
2696 goto return_exception;
2701 /* release dump area */
2703 dump_release(dumpsize);
2706 log_message_class("Loading done class: ", c);
2712 /* release dump area */
2714 dump_release(dumpsize);
2716 /* an exception has been thrown */
2723 /* load_newly_created_array ****************************************************
2725 Load a newly created array class.
2728 c....................the array class C has been loaded
2729 other classinfo......the array class was found in the class cache,
2731 NULL.................an exception has been thrown
2734 This is an internal function. Do not use it unless you know exactly
2737 Use one of the load_class_... functions for general array class loading.
2739 *******************************************************************************/
2741 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2743 classinfo *comp = NULL;
2745 methoddesc *clonedesc;
2746 constant_classref *classrefs;
2748 java_objectheader *definingloader = NULL;
2751 #ifdef LOADER_VERBOSE
2752 char logtext[MAXLOGTEXT];
2753 LOADER_INDENT(logtext);
2754 strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2755 sprintf(logtext+strlen(logtext),") loader=%p",loader);
2759 /* Check array class name */
2761 namelen = c->name->blength;
2762 if (namelen < 2 || c->name->text[0] != '[') {
2763 *exceptionptr = new_internalerror("Invalid array class name");
2767 /* Check the component type */
2769 switch (c->name->text[1]) {
2771 /* c is an array of arrays. We have to create the component class. */
2773 u = utf_new_intern(c->name->text + 1, namelen - 1);
2775 if (!(comp = load_class_from_classloader(u, loader))) {
2780 LOADER_ASSERT(comp->loaded);
2784 definingloader = comp->classloader;
2788 /* c is an array of objects. */
2789 if (namelen < 4 || c->name->text[namelen - 1] != ';') {
2790 *exceptionptr = new_internalerror("Invalid array class name");
2794 u = utf_new_intern(c->name->text + 2, namelen - 3);
2797 if (!(comp = load_class_from_classloader(u, loader))) {
2802 LOADER_ASSERT(comp->loaded);
2806 definingloader = comp->classloader;
2810 LOADER_ASSERT(class_java_lang_Object);
2811 LOADER_ASSERT(class_java_lang_Cloneable);
2812 LOADER_ASSERT(class_java_io_Serializable);
2814 /* Setup the array class */
2816 c->super.cls = class_java_lang_Object;
2817 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2819 c->interfacescount = 2;
2820 c->interfaces = MNEW(classref_or_classinfo, 2);
2825 tc = class_java_lang_Cloneable;
2826 LOADER_ASSERT(tc->loaded);
2827 list_addfirst(&unlinkedclasses, tc);
2828 c->interfaces[0].cls = tc;
2830 tc = class_java_io_Serializable;
2831 LOADER_ASSERT(tc->loaded);
2832 list_addfirst(&unlinkedclasses, tc);
2833 c->interfaces[1].cls = tc;
2836 c->interfaces[0].cls = class_java_lang_Cloneable;
2837 c->interfaces[1].cls = class_java_io_Serializable;
2840 c->methodscount = 1;
2841 c->methods = MNEW(methodinfo, c->methodscount);
2843 classrefs = MNEW(constant_classref, 2);
2844 CLASSREF_INIT(classrefs[0], c, c->name);
2845 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2847 /* create descriptor for clone method */
2848 /* we need one paramslot which is reserved for the 'this' parameter */
2849 clonedesc = NEW(methoddesc);
2850 clonedesc->returntype.type = TYPE_ADDRESS;
2851 clonedesc->returntype.classref = classrefs + 1;
2852 clonedesc->returntype.arraydim = 0;
2853 clonedesc->paramcount = 0;
2854 clonedesc->paramslots = 0;
2855 clonedesc->paramtypes[0].classref = classrefs + 0;
2857 /* parse the descriptor to get the register allocation */
2859 if (!descriptor_params_from_paramtypes(clonedesc, ACC_NONE))
2863 MSET(clone, 0, methodinfo, 1);
2865 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2866 initObjectLock(&clone->header);
2869 clone->flags = ACC_PUBLIC;
2870 clone->name = utf_clone;
2871 clone->descriptor = utf_void__java_lang_Object;
2872 clone->parseddesc = clonedesc;
2874 clone->monoPoly = MONO;
2877 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2880 /* XXX: field: length? */
2882 /* array classes are not loaded from class files */
2885 c->parseddescs = (u1 *) clonedesc;
2886 c->parseddescsize = sizeof(methodinfo);
2887 c->classrefs = classrefs;
2888 c->classrefcount = 1;
2889 c->classloader = definingloader;
2891 /* insert class into the loaded class cache */
2892 /* XXX free classinfo if NULL returned? */
2894 return classcache_store(loader,c,true);
2898 /************************* Function: class_findfield ***************************
2900 Searches a 'classinfo' structure for a field having the given name and
2903 *******************************************************************************/
2905 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2909 for (i = 0; i < c->fieldscount; i++) {
2910 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2911 return &(c->fields[i]);
2914 log_text("Can not find field given in CONSTANT_Fieldref");
2917 /* keep compiler happy */
2923 /****************** Function: class_resolvefield_int ***************************
2925 This is an internally used helper function. Do not use this directly.
2927 Tries to resolve a field having the given name and type.
2928 If the field cannot be resolved, NULL is returned.
2930 *******************************************************************************/
2932 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2937 /* search for field in class c */
2939 for (i = 0; i < c->fieldscount; i++) {
2940 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2941 return &(c->fields[i]);
2945 /* try superinterfaces recursively */
2947 for (i = 0; i < c->interfacescount; i++) {
2948 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2953 /* try superclass */
2956 return class_resolvefield_int(c->super.cls, name, desc);
2964 /********************* Function: class_resolvefield ***************************
2966 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2968 If the field cannot be resolved the return value is NULL. If EXCEPT is
2969 true *exceptionptr is set, too.
2971 *******************************************************************************/
2973 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2974 classinfo *referer, bool except)
2978 /* XXX resolve class c */
2979 /* XXX check access from REFERER to C */
2981 fi = class_resolvefield_int(c, name, desc);
2986 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2992 /* XXX check access rights */
2998 /* class_findmethod ************************************************************
3000 Searches a 'classinfo' structure for a method having the given name
3001 and descriptor. If descriptor is NULL, it is ignored.
3003 *******************************************************************************/
3005 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3010 for (i = 0; i < c->methodscount; i++) {
3011 m = &(c->methods[i]);
3013 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
3021 /*********************** Function: class_fetchmethod **************************
3023 like class_findmethod, but aborts with an error if the method is not found
3025 *******************************************************************************/
3027 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3031 mi = class_findmethod(c, name, desc);
3034 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3035 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3036 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3038 log_text("Method not found");
3046 /************************* Function: class_findmethod_approx ******************
3048 like class_findmethod but ignores the return value when comparing the
3051 *******************************************************************************/
3053 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3057 for (i = 0; i < c->methodscount; i++) {
3058 if (c->methods[i].name == name) {
3059 utf *meth_descr = c->methods[i].descriptor;
3063 return &(c->methods[i]);
3065 if (desc->blength <= meth_descr->blength) {
3066 /* current position in utf text */
3067 char *desc_utf_ptr = desc->text;
3068 char *meth_utf_ptr = meth_descr->text;
3069 /* points behind utf strings */
3070 char *desc_end = UTF_END(desc);
3071 char *meth_end = UTF_END(meth_descr);
3074 /* compare argument types */
3075 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3077 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3078 break; /* no match */
3081 return &(c->methods[i]); /* all parameter types equal */
3091 /***************** Function: class_resolvemethod_approx ***********************
3093 Searches a class and every super class for a method (without paying
3094 attention to the return value)
3096 *******************************************************************************/
3098 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3101 /* search for method (ignore returntype) */
3102 methodinfo *m = class_findmethod_approx(c, name, desc);
3105 /* search superclass */
3113 /* class_resolvemethod *********************************************************
3115 Searches a class and it's super classes for a method.
3117 *******************************************************************************/
3119 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3124 m = class_findmethod(c, name, desc);
3136 /* class_resolveinterfacemethod_intern *****************************************
3138 Internally used helper function. Do not use this directly.
3140 *******************************************************************************/
3142 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
3143 utf *name, utf *desc)
3148 m = class_findmethod(c, name, desc);
3153 /* try the superinterfaces */
3155 for (i = 0; i < c->interfacescount; i++) {
3156 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3166 /* class_resolveinterfacemethod ************************************************
3168 Resolves a reference from REFERER to a method with NAME and DESC in
3171 If the method cannot be resolved the return value is NULL. If
3172 EXCEPT is true *exceptionptr is set, too.
3174 *******************************************************************************/
3176 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3177 classinfo *referer, bool except)
3181 /* XXX resolve class c */
3182 /* XXX check access from REFERER to C */
3184 if (!(c->flags & ACC_INTERFACE)) {
3187 new_exception(string_java_lang_IncompatibleClassChangeError);
3192 mi = class_resolveinterfacemethod_intern(c, name, desc);
3197 /* try class java.lang.Object */
3199 mi = class_findmethod(class_java_lang_Object, name, desc);
3206 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3212 /* class_resolveclassmethod ****************************************************
3214 Resolves a reference from REFERER to a method with NAME and DESC in
3217 If the method cannot be resolved the return value is NULL. If
3218 EXCEPT is true *exceptionptr is set, too.
3220 *******************************************************************************/
3222 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3223 classinfo *referer, bool except)
3231 /* XXX resolve class c */
3232 /* XXX check access from REFERER to C */
3234 /* if (c->flags & ACC_INTERFACE) { */
3236 /* *exceptionptr = */
3237 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3241 /* try class c and its superclasses */
3246 mi = class_findmethod(cls, name, desc);
3251 cls = cls->super.cls;
3254 /* try the superinterfaces */
3256 for (i = 0; i < c->interfacescount; i++) {
3257 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3265 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3266 utf_strlen(desc) + strlen("0");
3268 msg = MNEW(char, msglen);
3270 utf_sprint(msg, c->name);
3272 utf_sprint(msg + strlen(msg), name);
3273 utf_sprint(msg + strlen(msg), desc);
3276 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3278 MFREE(msg, char, msglen);
3284 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3286 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3291 /* XXX check access rights */
3297 /************************* Function: class_issubclass **************************
3299 Checks if sub is a descendant of super.
3301 *******************************************************************************/
3303 bool class_issubclass(classinfo *sub, classinfo *super)
3306 if (!sub) return false;
3307 if (sub == super) return true;
3308 sub = sub->super.cls;
3313 void class_showconstanti(classinfo *c, int ii)
3319 printf ("#%d: ", (int) i);
3321 switch (c->cptags [i]) {
3322 case CONSTANT_Class:
3323 printf("Classreference -> ");
3324 utf_display(((constant_classref*)e)->name);
3327 case CONSTANT_Fieldref:
3328 printf("Fieldref -> "); goto displayFMIi;
3329 case CONSTANT_Methodref:
3330 printf("Methodref -> "); goto displayFMIi;
3331 case CONSTANT_InterfaceMethodref:
3332 printf("InterfaceMethod -> "); goto displayFMIi;
3335 constant_FMIref *fmi = e;
3336 utf_display(fmi->classref->name);
3338 utf_display(fmi->name);
3340 utf_display(fmi->descriptor);
3344 case CONSTANT_String:
3345 printf("String -> ");
3348 case CONSTANT_Integer:
3349 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3351 case CONSTANT_Float:
3352 printf("Float -> %f", ((constant_float*)e)->value);
3354 case CONSTANT_Double:
3355 printf("Double -> %f", ((constant_double*)e)->value);
3359 u8 v = ((constant_long*)e)->value;
3361 printf("Long -> %ld", (long int) v);
3363 printf("Long -> HI: %ld, LO: %ld\n",
3364 (long int) v.high, (long int) v.low);
3368 case CONSTANT_NameAndType:
3370 constant_nameandtype *cnt = e;
3371 printf("NameAndType: ");
3372 utf_display(cnt->name);
3374 utf_display(cnt->descriptor);
3382 log_text("Invalid type of ConstantPool-Entry");
3390 void class_showconstantpool (classinfo *c)
3395 printf ("---- dump of constant pool ----\n");
3397 for (i=0; i<c->cpcount; i++) {
3398 printf ("#%d: ", (int) i);
3400 e = c -> cpinfos [i];
3403 switch (c -> cptags [i]) {
3404 case CONSTANT_Class:
3405 printf ("Classreference -> ");
3406 utf_display ( ((constant_classref*)e) -> name );
3409 case CONSTANT_Fieldref:
3410 printf ("Fieldref -> "); goto displayFMI;
3411 case CONSTANT_Methodref:
3412 printf ("Methodref -> "); goto displayFMI;
3413 case CONSTANT_InterfaceMethodref:
3414 printf ("InterfaceMethod -> "); goto displayFMI;
3417 constant_FMIref *fmi = e;
3418 utf_display ( fmi->classref->name );
3420 utf_display ( fmi->name);
3422 utf_display ( fmi->descriptor );
3426 case CONSTANT_String:
3427 printf ("String -> ");
3430 case CONSTANT_Integer:
3431 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3433 case CONSTANT_Float:
3434 printf ("Float -> %f", ((constant_float*)e) -> value);
3436 case CONSTANT_Double:
3437 printf ("Double -> %f", ((constant_double*)e) -> value);
3441 u8 v = ((constant_long*)e) -> value;
3443 printf ("Long -> %ld", (long int) v);
3445 printf ("Long -> HI: %ld, LO: %ld\n",
3446 (long int) v.high, (long int) v.low);
3450 case CONSTANT_NameAndType:
3452 constant_nameandtype *cnt = e;
3453 printf ("NameAndType: ");
3454 utf_display (cnt->name);
3456 utf_display (cnt->descriptor);
3460 printf ("Utf8 -> ");
3464 log_text("Invalid type of ConstantPool-Entry");
3475 /********** Function: class_showmethods (debugging only) *************/
3477 void class_showmethods (classinfo *c)
3481 printf ("--------- Fields and Methods ----------------\n");
3482 printf ("Flags: "); printflags (c->flags); printf ("\n");
3484 printf ("This: "); utf_display (c->name); printf ("\n");
3486 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3488 printf ("Index: %d\n", c->index);
3490 printf ("interfaces:\n");
3491 for (i=0; i < c-> interfacescount; i++) {
3493 utf_display (c -> interfaces[i].cls -> name);
3494 printf (" (%d)\n", c->interfaces[i].cls -> index);
3497 printf ("fields:\n");
3498 for (i=0; i < c -> fieldscount; i++) {
3499 field_display (&(c -> fields[i]));
3502 printf ("methods:\n");
3503 for (i=0; i < c -> methodscount; i++) {
3504 methodinfo *m = &(c->methods[i]);
3505 if ( !(m->flags & ACC_STATIC))
3506 printf ("vftblindex: %d ", m->vftblindex);
3508 method_display ( m );
3512 printf ("Virtual function table:\n");
3513 for (i=0; i<c->vftbl->vftbllength; i++) {
3514 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3520 /* loader_close ****************************************************************
3522 Frees all resources.
3524 *******************************************************************************/
3526 void loader_close(void)
3533 * These are local overrides for various environment variables in Emacs.
3534 * Please do not remove this and leave it at the end of the file, where
3535 * Emacs will automagically detect them.
3536 * ---------------------------------------------------------------------
3539 * indent-tabs-mode: t