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 3292 2005-09-28 10:36:34Z 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_Thread =
204 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
207 if (!(class_java_lang_ThreadGroup =
208 load_class_bootstrap(utf_java_lang_ThreadGroup)))
211 if (!(class_java_lang_VMThread =
212 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
216 /* some classes which may be used more often */
218 if (!(class_java_lang_StackTraceElement =
219 load_class_bootstrap(utf_java_lang_StackTraceElement)))
222 if (!(class_java_lang_reflect_Constructor =
223 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
226 if (!(class_java_lang_reflect_Field =
227 load_class_bootstrap(utf_java_lang_reflect_Field)))
230 if (!(class_java_lang_reflect_Method =
231 load_class_bootstrap(utf_java_lang_reflect_Method)))
234 if (!(class_java_security_PrivilegedAction =
235 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
238 if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
241 if (!(arrayclass_java_lang_Object =
242 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
245 #if defined(USE_THREADS)
246 if (stackbottom != 0)
254 /************* functions for reading classdata *********************************
256 getting classdata in blocks of variable size
257 (8,16,32,64-bit integer or float)
259 *******************************************************************************/
261 /* check_classbuffer_size ******************************************************
263 assert that at least <len> bytes are left to read
264 <len> is limited to the range of non-negative s4 values
266 *******************************************************************************/
268 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
270 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
272 new_classformaterror((cb)->class, "Truncated class file");
281 /* suck_nbytes *****************************************************************
283 transfer block of classfile data into a buffer
285 *******************************************************************************/
287 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
289 memcpy(buffer, cb->pos + 1, len);
294 /* skip_nbytes ****************************************************************
296 skip block of classfile data
298 *******************************************************************************/
300 inline void skip_nbytes(classbuffer *cb, s4 len)
306 inline u1 suck_u1(classbuffer *cb)
312 inline u2 suck_u2(classbuffer *cb)
316 return ((u2) a << 8) + (u2) b;
320 inline u4 suck_u4(classbuffer *cb)
326 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
330 /* get u8 from classfile data */
331 static u8 suck_u8(classbuffer *cb)
337 return (hi << 32) + lo;
340 v.high = suck_u4(cb);
347 /* get float from classfile data */
348 static float suck_float(classbuffer *cb)
356 for (i = 0; i < 4; i++)
357 buffer[3 - i] = suck_u1(cb);
359 memcpy((u1*) (&f), buffer, 4);
361 suck_nbytes((u1*) (&f), cb, 4);
364 if (sizeof(float) != 4) {
365 *exceptionptr = new_exception_message(string_java_lang_InternalError,
366 "Incompatible float-format");
368 /* XXX should we exit in such a case? */
369 throw_exception_exit();
376 /* get double from classfile data */
377 static double suck_double(classbuffer *cb)
385 #if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
387 * On little endian ARM processors when using FPA, word order
388 * of doubles is still big endian. So take that into account
389 * here. When using VFP, word order of doubles follows byte
390 * order. (michi 2005/07/24)
392 for (i = 0; i < 4; i++)
393 buffer[3 - i] = suck_u1(cb);
394 for (i = 0; i < 4; i++)
395 buffer[7 - i] = suck_u1(cb);
397 for (i = 0; i < 8; i++)
398 buffer[7 - i] = suck_u1(cb);
399 #endif /* defined(__ARM__) && ... */
401 memcpy((u1*) (&d), buffer, 8);
403 suck_nbytes((u1*) (&d), cb, 8);
406 if (sizeof(double) != 8) {
407 *exceptionptr = new_exception_message(string_java_lang_InternalError,
408 "Incompatible double-format");
410 /* XXX should we exit in such a case? */
411 throw_exception_exit();
418 /************************** function suck_init *********************************
420 called once at startup, sets the searchpath for the classfiles
422 *******************************************************************************/
424 void suck_init(char *classpath)
432 classpath_info *lastcpi;
436 /* search for last classpath entry (only if there already some) */
438 if ((lastcpi = classpath_entries)) {
439 while (lastcpi->next)
440 lastcpi = lastcpi->next;
443 for (start = classpath; (*start) != '\0';) {
445 /* search for ':' delimiter to get the end of the current entry */
446 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
450 filenamelen = end - start;
452 if (filenamelen > 3) {
453 if (strncasecmp(end - 3, "zip", 3) == 0 ||
454 strncasecmp(end - 3, "jar", 3) == 0) {
459 /* save classpath entries as absolute pathnames */
464 if (*start != '/') { /* XXX fix me for win32 */
466 cwdlen = strlen(cwd) + strlen("/");
469 /* allocate memory for filename and fill it */
471 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
475 strcpy(filename, cwd);
476 strcat(filename, "/");
477 strncat(filename, start, filenamelen);
479 /* add cwd length to file length */
480 filenamelen += cwdlen;
483 strncpy(filename, start, filenamelen);
484 filename[filenamelen] = '\0';
490 #if defined(USE_ZLIB)
491 unzFile uf = unzOpen(filename);
494 cpi = NEW(classpath_info);
495 cpi->type = CLASSPATH_ARCHIVE;
498 cpi->path = filename;
499 cpi->pathlen = filenamelen;
503 throw_cacao_exception_exit(string_java_lang_InternalError,
504 "zip/jar files not supported");
508 cpi = NEW(classpath_info);
509 cpi->type = CLASSPATH_PATH;
512 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
513 filename[filenamelen] = '/';
514 filename[filenamelen + 1] = '\0';
518 cpi->path = filename;
519 cpi->pathlen = filenamelen;
522 /* attach current classpath entry */
525 if (!classpath_entries)
526 classpath_entries = cpi;
534 /* goto next classpath entry, skip ':' delimiter */
546 /* loader_load_all_classes *****************************************************
548 Loads all classes specified in the BOOTCLASSPATH.
550 *******************************************************************************/
552 void loader_load_all_classes(void)
557 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
558 #if defined(USE_ZLIB)
559 if (cpi->type == CLASSPATH_ARCHIVE) {
563 s = (unz_s *) cpi->uf;
564 ce = s->cacao_dir_list;
567 /* skip all entries in META-INF and .properties files */
569 if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
570 !strstr(ce->name->text, ".properties"))
571 c = load_class_bootstrap(ce->name);
578 #if defined(USE_ZLIB)
585 /* suck_start ******************************************************************
587 Returns true if classbuffer is already loaded or a file for the
588 specified class has succussfully been read in. All directories of
589 the searchpath are used to find the classfile (<classname>.class).
590 Returns false if no classfile is found and writes an error message.
592 *******************************************************************************/
594 classbuffer *suck_start(classinfo *c)
606 /* initialize return value */
611 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
612 filename = MNEW(char, filenamelen);
614 utf_sprint(filename, c->name);
615 strcat(filename, ".class");
617 /* walk through all classpath entries */
619 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
620 #if defined(USE_ZLIB)
621 if (cpi->type == CLASSPATH_ARCHIVE) {
623 #if defined(USE_THREADS)
624 /* enter a monitor on zip/jar archives */
626 builtin_monitorenter((java_objectheader *) cpi);
629 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
630 unz_file_info file_info;
632 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
633 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
634 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
635 cb = NEW(classbuffer);
637 cb->size = file_info.uncompressed_size;
638 cb->data = MNEW(u1, cb->size);
639 cb->pos = cb->data - 1;
641 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
643 if (len != cb->size) {
645 log_text("Error while unzipping");
652 log_text("Error while opening file in archive");
656 log_text("Error while retrieving fileinfo");
659 unzCloseCurrentFile(cpi->uf);
661 #if defined(USE_THREADS)
662 /* leave the monitor */
664 builtin_monitorexit((java_objectheader *) cpi);
668 #endif /* defined(USE_ZLIB) */
670 path = MNEW(char, cpi->pathlen + filenamelen);
671 strcpy(path, cpi->path);
672 strcat(path, filename);
674 classfile = fopen(path, "r");
676 if (classfile) { /* file exists */
677 if (!stat(path, &buffer)) { /* read classfile data */
678 cb = NEW(classbuffer);
680 cb->size = buffer.st_size;
681 cb->data = MNEW(u1, cb->size);
682 cb->pos = cb->data - 1;
684 /* read class data */
685 len = fread(cb->data, 1, cb->size, classfile);
687 if (len != buffer.st_size) {
689 /* if (ferror(classfile)) { */
698 MFREE(path, char, cpi->pathlen + filenamelen);
699 #if defined(USE_ZLIB)
706 dolog("Warning: Can not open class file '%s'", filename);
708 if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
716 MFREE(filename, char, filenamelen);
722 /************************** function suck_stop *********************************
724 frees memory for buffer with classfile data.
725 Caution: this function may only be called if buffer has been allocated
726 by suck_start with reading a file
728 *******************************************************************************/
730 void suck_stop(classbuffer *cb)
734 MFREE(cb->data, u1, cb->size);
735 FREE(cb, classbuffer);
739 /******************************************************************************/
740 /******************* Some support functions ***********************************/
741 /******************************************************************************/
743 void fprintflags (FILE *fp, u2 f)
745 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
746 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
747 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
748 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
749 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
750 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
751 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
752 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
753 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
754 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
755 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
759 /********** internal function: printflags (only for debugging) ***************/
761 void printflags(u2 f)
763 fprintflags(stdout,f);
767 /********************** Function: skipattributebody ****************************
769 skips an attribute after the 16 bit reference to attribute_name has already
772 *******************************************************************************/
774 static bool skipattributebody(classbuffer *cb)
778 if (!check_classbuffer_size(cb, 4))
783 if (!check_classbuffer_size(cb, len))
786 skip_nbytes(cb, len);
792 /************************* Function: skipattributes ****************************
794 skips num attribute structures
796 *******************************************************************************/
798 static bool skipattributes(classbuffer *cb, u4 num)
803 for (i = 0; i < num; i++) {
804 if (!check_classbuffer_size(cb, 2 + 4))
810 if (!check_classbuffer_size(cb, len))
813 skip_nbytes(cb, len);
820 /* load_constantpool ***********************************************************
822 Loads the constantpool of a class, the entries are transformed into
823 a simpler format by resolving references (a detailed overview of
824 the compact structures can be found in global.h).
826 *******************************************************************************/
828 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
831 /* The following structures are used to save information which cannot be
832 processed during the first pass. After the complete constantpool has
833 been traversed the references can be resolved.
834 (only in specific order) */
836 /* CONSTANT_Class entries */
837 typedef struct forward_class {
838 struct forward_class *next;
843 /* CONSTANT_String */
844 typedef struct forward_string {
845 struct forward_string *next;
850 /* CONSTANT_NameAndType */
851 typedef struct forward_nameandtype {
852 struct forward_nameandtype *next;
856 } forward_nameandtype;
858 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
859 typedef struct forward_fieldmethint {
860 struct forward_fieldmethint *next;
864 u2 nameandtype_index;
865 } forward_fieldmethint;
871 forward_class *forward_classes = NULL;
872 forward_string *forward_strings = NULL;
873 forward_nameandtype *forward_nameandtypes = NULL;
874 forward_fieldmethint *forward_fieldmethints = NULL;
878 forward_nameandtype *nfn;
879 forward_fieldmethint *nff;
887 /* number of entries in the constant_pool table plus one */
888 if (!check_classbuffer_size(cb, 2))
891 cpcount = c->cpcount = suck_u2(cb);
893 /* allocate memory */
894 cptags = c->cptags = MNEW(u1, cpcount);
895 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
898 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
902 #if defined(STATISTICS)
904 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
907 /* initialize constantpool */
908 for (idx = 0; idx < cpcount; idx++) {
909 cptags[idx] = CONSTANT_UNUSED;
914 /******* first pass *******/
915 /* entries which cannot be resolved now are written into
916 temporary structures and traversed again later */
919 while (idx < cpcount) {
922 /* get constant type */
923 if (!check_classbuffer_size(cb, 1))
930 nfc = DNEW(forward_class);
932 nfc->next = forward_classes;
933 forward_classes = nfc;
935 nfc->thisindex = idx;
936 /* reference to CONSTANT_NameAndType */
937 if (!check_classbuffer_size(cb, 2))
940 nfc->name_index = suck_u2(cb);
945 case CONSTANT_String:
946 nfs = DNEW(forward_string);
948 nfs->next = forward_strings;
949 forward_strings = nfs;
951 nfs->thisindex = idx;
953 /* reference to CONSTANT_Utf8_info with string characters */
954 if (!check_classbuffer_size(cb, 2))
957 nfs->string_index = suck_u2(cb);
962 case CONSTANT_NameAndType:
963 nfn = DNEW(forward_nameandtype);
965 nfn->next = forward_nameandtypes;
966 forward_nameandtypes = nfn;
968 nfn->thisindex = idx;
970 if (!check_classbuffer_size(cb, 2 + 2))
973 /* reference to CONSTANT_Utf8_info containing simple name */
974 nfn->name_index = suck_u2(cb);
976 /* reference to CONSTANT_Utf8_info containing field or method
978 nfn->sig_index = suck_u2(cb);
983 case CONSTANT_Fieldref:
984 case CONSTANT_Methodref:
985 case CONSTANT_InterfaceMethodref:
986 nff = DNEW(forward_fieldmethint);
988 nff->next = forward_fieldmethints;
989 forward_fieldmethints = nff;
991 nff->thisindex = idx;
995 if (!check_classbuffer_size(cb, 2 + 2))
998 /* class or interface type that contains the declaration of the
1000 nff->class_index = suck_u2(cb);
1002 /* name and descriptor of the field or method */
1003 nff->nameandtype_index = suck_u2(cb);
1008 case CONSTANT_Integer: {
1009 constant_integer *ci = NEW(constant_integer);
1011 #if defined(STATISTICS)
1013 count_const_pool_len += sizeof(constant_integer);
1016 if (!check_classbuffer_size(cb, 4))
1019 ci->value = suck_s4(cb);
1020 cptags[idx] = CONSTANT_Integer;
1027 case CONSTANT_Float: {
1028 constant_float *cf = NEW(constant_float);
1030 #if defined(STATISTICS)
1032 count_const_pool_len += sizeof(constant_float);
1035 if (!check_classbuffer_size(cb, 4))
1038 cf->value = suck_float(cb);
1039 cptags[idx] = CONSTANT_Float;
1046 case CONSTANT_Long: {
1047 constant_long *cl = NEW(constant_long);
1049 #if defined(STATISTICS)
1051 count_const_pool_len += sizeof(constant_long);
1054 if (!check_classbuffer_size(cb, 8))
1057 cl->value = suck_s8(cb);
1058 cptags[idx] = CONSTANT_Long;
1061 if (idx > cpcount) {
1063 new_classformaterror(c, "Invalid constant pool entry");
1069 case CONSTANT_Double: {
1070 constant_double *cd = NEW(constant_double);
1072 #if defined(STATISTICS)
1074 count_const_pool_len += sizeof(constant_double);
1077 if (!check_classbuffer_size(cb, 8))
1080 cd->value = suck_double(cb);
1081 cptags[idx] = CONSTANT_Double;
1084 if (idx > cpcount) {
1086 new_classformaterror(c, "Invalid constant pool entry");
1092 case CONSTANT_Utf8: {
1095 /* number of bytes in the bytes array (not string-length) */
1096 if (!check_classbuffer_size(cb, 2))
1099 length = suck_u2(cb);
1100 cptags[idx] = CONSTANT_Utf8;
1102 /* validate the string */
1103 if (!check_classbuffer_size(cb, length))
1107 !is_valid_utf((char *) (cb->pos + 1),
1108 (char *) (cb->pos + 1 + length))) {
1109 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1112 /* insert utf-string into the utf-symboltable */
1113 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1115 /* skip bytes of the string (buffer size check above) */
1116 skip_nbytes(cb, length);
1123 new_classformaterror(c, "Illegal constant pool type");
1129 /* resolve entries in temporary structures */
1131 while (forward_classes) {
1133 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1135 if (opt_verify && !is_valid_name_utf(name)) {
1137 new_classformaterror(c, "Class reference with invalid name");
1141 /* add all class references to the descriptor_pool */
1143 if (!descriptor_pool_add_class(descpool, name))
1146 cptags[forward_classes->thisindex] = CONSTANT_Class;
1151 if (!(tc = load_class_bootstrap(name)))
1154 /* link the class later, because we cannot link the class currently
1156 list_addfirst(&unlinkedclasses, tc);
1159 /* the classref is created later */
1160 cpinfos[forward_classes->thisindex] = name;
1162 nfc = forward_classes;
1163 forward_classes = forward_classes->next;
1166 while (forward_strings) {
1168 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1170 /* resolve utf-string */
1171 cptags[forward_strings->thisindex] = CONSTANT_String;
1172 cpinfos[forward_strings->thisindex] = text;
1174 nfs = forward_strings;
1175 forward_strings = forward_strings->next;
1178 while (forward_nameandtypes) {
1179 constant_nameandtype *cn = NEW(constant_nameandtype);
1181 #if defined(STATISTICS)
1183 count_const_pool_len += sizeof(constant_nameandtype);
1186 /* resolve simple name and descriptor */
1187 cn->name = class_getconstant(c,
1188 forward_nameandtypes->name_index,
1191 cn->descriptor = class_getconstant(c,
1192 forward_nameandtypes->sig_index,
1197 if (!is_valid_name_utf(cn->name)) {
1199 new_classformaterror(c,
1200 "Illegal Field name \"%s\"",
1206 /* disallow referencing <clinit> among others */
1207 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1209 new_exception_utfmessage(string_java_lang_InternalError,
1215 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1216 cpinfos[forward_nameandtypes->thisindex] = cn;
1218 nfn = forward_nameandtypes;
1219 forward_nameandtypes = forward_nameandtypes->next;
1222 while (forward_fieldmethints) {
1223 constant_nameandtype *nat;
1224 constant_FMIref *fmi = NEW(constant_FMIref);
1226 #if defined(STATISTICS)
1228 count_const_pool_len += sizeof(constant_FMIref);
1230 /* resolve simple name and descriptor */
1232 nat = class_getconstant(c,
1233 forward_fieldmethints->nameandtype_index,
1234 CONSTANT_NameAndType);
1236 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
1238 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
1241 /* the classref is created later */
1243 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
1244 fmi->name = nat->name;
1245 fmi->descriptor = nat->descriptor;
1247 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1248 cpinfos[forward_fieldmethints->thisindex] = fmi;
1250 nff = forward_fieldmethints;
1251 forward_fieldmethints = forward_fieldmethints->next;
1254 /* everything was ok */
1260 /* load_field ******************************************************************
1262 Load everything about a class field from the class file and fill a
1263 'fieldinfo' structure. For static fields, space in the data segment
1266 *******************************************************************************/
1268 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1270 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
1275 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1280 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1283 f->flags = suck_u2(cb);
1285 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1290 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1294 f->parseddesc = NULL;
1296 if (!descriptor_pool_add(descpool, u, NULL))
1301 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1302 *exceptionptr = new_classformaterror(c,
1303 "Illegal Field name \"%s\"",
1308 /* check flag consistency */
1309 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1311 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1312 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1314 new_classformaterror(c,
1315 "Illegal field modifiers: 0x%X",
1320 if (c->flags & ACC_INTERFACE) {
1321 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1322 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1323 f->flags & ACC_TRANSIENT) {
1325 new_classformaterror(c,
1326 "Illegal field modifiers: 0x%X",
1333 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1334 f->offset = 0; /* offset from start of object */
1339 case TYPE_INT: f->value.i = 0; break;
1340 case TYPE_FLOAT: f->value.f = 0.0; break;
1341 case TYPE_DOUBLE: f->value.d = 0.0; break;
1342 case TYPE_ADDRESS: f->value.a = NULL; break;
1345 f->value.l = 0; break;
1347 f->value.l.low = 0; f->value.l.high = 0; break;
1351 /* read attributes */
1352 if (!check_classbuffer_size(cb, 2))
1355 attrnum = suck_u2(cb);
1356 for (i = 0; i < attrnum; i++) {
1357 if (!check_classbuffer_size(cb, 2))
1360 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1363 if (u == utf_ConstantValue) {
1364 if (!check_classbuffer_size(cb, 4 + 2))
1367 /* check attribute length */
1368 if (suck_u4(cb) != 2) {
1370 new_classformaterror(c, "Wrong size for VALUE attribute");
1374 /* constant value attribute */
1375 if (pindex != field_load_NOVALUE) {
1377 new_classformaterror(c,
1378 "Multiple ConstantValue attributes");
1382 /* index of value in constantpool */
1383 pindex = suck_u2(cb);
1385 /* initialize field with value from constantpool */
1388 constant_integer *ci;
1390 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1393 f->value.i = ci->value;
1400 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1403 f->value.l = cl->value;
1410 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1413 f->value.f = cf->value;
1418 constant_double *cd;
1420 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1423 f->value.d = cd->value;
1428 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1431 /* create javastring from compressed utf8-string */
1432 f->value.a = literalstring_new(u);
1436 log_text("Invalid Constant - Type");
1440 /* unknown attribute */
1441 if (!skipattributebody(cb))
1446 /* everything was ok */
1452 /* load_method *****************************************************************
1454 Loads a method from the class file and fills an existing
1455 'methodinfo' structure. For native methods, the function pointer
1456 field is set to the real function pointer, for JavaVM methods a
1457 pointer to the compiler is used preliminarily.
1459 *******************************************************************************/
1461 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1472 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1473 initObjectLock(&m->header);
1478 count_all_methods++;
1481 m->thrownexceptionscount = 0;
1482 m->linenumbercount = 0;
1485 m->nativelyoverloaded = false;
1487 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1490 m->flags = suck_u2(cb);
1492 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1497 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1501 m->parseddesc = NULL;
1503 if (!descriptor_pool_add(descpool, u, &argcount))
1507 if (!is_valid_name_utf(m->name)) {
1508 log_text("Method with invalid name");
1512 if (m->name->text[0] == '<' &&
1513 m->name != utf_init && m->name != utf_clinit) {
1514 log_text("Method with invalid special name");
1519 if (!(m->flags & ACC_STATIC))
1520 argcount++; /* count the 'this' argument */
1523 if (argcount > 255) {
1525 new_classformaterror(c, "Too many arguments in signature");
1529 /* check flag consistency */
1530 if (m->name != utf_clinit) {
1531 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1533 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1535 new_classformaterror(c,
1536 "Illegal method modifiers: 0x%X",
1541 if (m->flags & ACC_ABSTRACT) {
1542 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1543 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1545 new_classformaterror(c,
1546 "Illegal method modifiers: 0x%X",
1552 if (c->flags & ACC_INTERFACE) {
1553 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1555 new_classformaterror(c,
1556 "Illegal method modifiers: 0x%X",
1562 if (m->name == utf_init) {
1563 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1564 ACC_NATIVE | ACC_ABSTRACT)) {
1565 log_text("Instance initialization method has invalid flags set");
1573 m->basicblockcount = 0;
1574 m->basicblocks = NULL;
1575 m->basicblockindex = NULL;
1576 m->instructioncount = 0;
1577 m->instructions = NULL;
1580 m->exceptiontable = NULL;
1581 m->stubroutine = NULL;
1583 m->entrypoint = NULL;
1584 m->methodUsed = NOTUSED;
1587 m->subRedefsUsed = 0;
1591 if (!check_classbuffer_size(cb, 2))
1594 attrnum = suck_u2(cb);
1595 for (i = 0; i < attrnum; i++) {
1598 if (!check_classbuffer_size(cb, 2))
1601 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1604 if (aname == utf_Code) {
1605 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1607 new_classformaterror(c,
1608 "Code attribute in native or abstract methods");
1615 new_classformaterror(c, "Multiple Code attributes");
1620 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1624 m->maxstack = suck_u2(cb);
1625 m->maxlocals = suck_u2(cb);
1627 if (m->maxlocals < argcount) {
1629 new_classformaterror(c, "Arguments can't fit into locals");
1634 if (!check_classbuffer_size(cb, 4))
1637 m->jcodelength = suck_u4(cb);
1639 if (m->jcodelength == 0) {
1641 new_classformaterror(c, "Code of a method has length 0");
1646 if (m->jcodelength > 65535) {
1648 new_classformaterror(c,
1649 "Code of a method longer than 65535 bytes");
1654 if (!check_classbuffer_size(cb, m->jcodelength))
1657 m->jcode = MNEW(u1, m->jcodelength);
1658 suck_nbytes(m->jcode, cb, m->jcodelength);
1660 if (!check_classbuffer_size(cb, 2))
1663 m->exceptiontablelength = suck_u2(cb);
1664 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1667 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1669 #if defined(STATISTICS)
1671 count_vmcode_len += m->jcodelength + 18;
1672 count_extable_len += 8 * m->exceptiontablelength;
1676 for (j = 0; j < m->exceptiontablelength; j++) {
1678 m->exceptiontable[j].startpc = suck_u2(cb);
1679 m->exceptiontable[j].endpc = suck_u2(cb);
1680 m->exceptiontable[j].handlerpc = suck_u2(cb);
1684 m->exceptiontable[j].catchtype.any = NULL;
1687 /* the classref is created later */
1688 if (!(m->exceptiontable[j].catchtype.any =
1689 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1694 if (!check_classbuffer_size(cb, 2))
1697 codeattrnum = suck_u2(cb);
1699 for (; codeattrnum > 0; codeattrnum--) {
1702 if (!check_classbuffer_size(cb, 2))
1705 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1708 if (caname == utf_LineNumberTable) {
1711 if (!check_classbuffer_size(cb, 4 + 2))
1715 m->linenumbercount = suck_u2(cb);
1717 if (!check_classbuffer_size(cb,
1718 (2 + 2) * m->linenumbercount))
1721 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1723 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1724 m->linenumbers[lncid].start_pc = suck_u2(cb);
1725 m->linenumbers[lncid].line_number = suck_u2(cb);
1729 if (!skipattributes(cb, codeattrnum))
1735 if (!skipattributebody(cb))
1740 } else if (aname == utf_Exceptions) {
1743 if (m->thrownexceptions) {
1745 new_classformaterror(c, "Multiple Exceptions attributes");
1749 if (!check_classbuffer_size(cb, 4 + 2))
1752 suck_u4(cb); /* length */
1753 m->thrownexceptionscount = suck_u2(cb);
1755 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1758 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1760 for (j = 0; j < m->thrownexceptionscount; j++) {
1761 /* the classref is created later */
1762 if (!((m->thrownexceptions)[j].any =
1763 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1768 if (!skipattributebody(cb))
1773 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1774 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1779 /* everything was ok */
1785 /* load_attribute **************************************************************
1787 Read attributes from classfile.
1789 *******************************************************************************/
1791 static bool load_attributes(classbuffer *cb, u4 num)
1799 for (i = 0; i < num; i++) {
1800 /* retrieve attribute name */
1801 if (!check_classbuffer_size(cb, 2))
1804 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1807 if (aname == utf_InnerClasses) {
1808 /* innerclasses attribute */
1809 if (c->innerclass) {
1811 new_classformaterror(c, "Multiple InnerClasses attributes");
1815 if (!check_classbuffer_size(cb, 4 + 2))
1818 /* skip attribute length */
1821 /* number of records */
1822 c->innerclasscount = suck_u2(cb);
1824 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1827 /* allocate memory for innerclass structure */
1828 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1830 for (j = 0; j < c->innerclasscount; j++) {
1831 /* The innerclass structure contains a class with an encoded
1832 name, its defining scope, its simple name and a bitmask of
1833 the access flags. If an inner class is not a member, its
1834 outer_class is NULL, if a class is anonymous, its name is
1837 innerclassinfo *info = c->innerclass + j;
1839 info->inner_class.ref =
1840 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1841 info->outer_class.ref =
1842 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1844 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1845 info->flags = suck_u2(cb);
1848 } else if (aname == utf_SourceFile) {
1849 if (!check_classbuffer_size(cb, 4 + 2))
1852 if (suck_u4(cb) != 2) {
1854 new_classformaterror(c, "Wrong size for VALUE attribute");
1858 if (c->sourcefile) {
1860 new_classformaterror(c, "Multiple SourceFile attributes");
1864 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1868 /* unknown attribute */
1869 if (!skipattributebody(cb))
1878 /* load_class_from_sysloader ***************************************************
1880 Load the class with the given name using the system class loader
1883 name.............the classname
1886 the loaded class, or
1887 NULL if an exception has been thrown
1889 *******************************************************************************/
1891 classinfo *load_class_from_sysloader(utf *name)
1894 java_objectheader *cl;
1897 #ifdef LOADER_VERBOSE
1898 char logtext[MAXLOGTEXT];
1899 LOADER_INDENT(logtext);
1900 sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1901 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1905 LOADER_ASSERT(class_java_lang_Object);
1906 LOADER_ASSERT(class_java_lang_ClassLoader);
1907 LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1909 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1910 utf_getSystemClassLoader,
1911 utf_void__java_lang_ClassLoader,
1912 class_java_lang_Object,
1918 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1923 r = load_class_from_classloader(name, cl);
1929 /* load_class_from_classloader *************************************************
1931 Load the class with the given name using the given user-defined class loader.
1934 name.............the classname
1935 cl...............user-defined class loader
1938 the loaded class, or
1939 NULL if an exception has been thrown
1941 *******************************************************************************/
1943 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1947 #ifdef LOADER_VERBOSE
1948 char logtext[MAXLOGTEXT];
1949 LOADER_INDENT(logtext);
1950 strcat(logtext,"load_class_from_classloader(");
1951 utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1952 if (!cl) strcat(logtext,"<bootstrap>");
1953 else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1954 else strcat(logtext,"<unknown class>");
1955 strcat(logtext,")");
1959 LOADER_ASSERT(name);
1961 /* lookup if this class has already been loaded */
1963 r = classcache_lookup(cl, name);
1965 #ifdef LOADER_VERBOSE
1967 dolog(" cached -> %p",(void*)r);
1973 /* if other class loader than bootstrap, call it */
1981 namelen = name->blength;
1983 /* handle array classes */
1984 if (text[0] == '[') {
1990 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1991 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1992 *exceptionptr = new_classnotfoundexception(name);
1996 u = utf_new(text + 2, namelen - 3);
1998 if (!(comp = load_class_from_classloader(u, cl)))
2001 /* create the array class */
2002 return class_array_of(comp, false);
2005 /* load the component class */
2007 u = utf_new(text + 1, namelen - 1);
2009 if (!(comp = load_class_from_classloader(u, cl)))
2012 /* create the array class */
2013 return class_array_of(comp, false);
2016 /* primitive array classes are loaded by the bootstrap loader */
2017 return load_class_bootstrap(name);
2021 LOADER_ASSERT(class_java_lang_Object);
2023 lc = class_resolveclassmethod(cl->vftbl->class,
2025 utf_java_lang_String__java_lang_Class,
2026 class_java_lang_Object,
2030 return false; /* exception */
2033 r = (classinfo *) asm_calljavafunction(lc,
2035 javastring_new_slash_to_dot(name),
2040 /* store this class in the loaded class cache */
2041 /* If another class with the same (initloader,name) pair has been */
2042 /* stored earlier it will be returned by classcache_store */
2043 /* In this case classcache_store may not free the class because it*/
2044 /* has already been exposed to Java code which may have kept */
2045 /* references to that class. */
2046 classinfo *c = classcache_store(cl,r,false);
2048 /* exception, free the loaded class */
2059 r = load_class_bootstrap(name);
2066 /* load_class_bootstrap ********************************************************
2068 Load the class with the given name using the bootstrap class loader.
2071 name.............the classname
2074 loaded classinfo, or
2075 NULL if an exception has been thrown
2078 load_class_bootstrap is synchronized. It can be treated as an
2081 *******************************************************************************/
2083 classinfo *load_class_bootstrap(utf *name)
2088 #ifdef LOADER_VERBOSE
2089 char logtext[MAXLOGTEXT];
2094 LOADER_ASSERT(name);
2097 /* lookup if this class has already been loaded */
2099 if ((r = classcache_lookup(NULL, name)))
2102 #ifdef LOADER_VERBOSE
2103 LOADER_INDENT(logtext);
2104 strcat(logtext,"load_class_bootstrap(");
2105 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2109 /* create the classinfo */
2111 c = class_create_classinfo(name);
2113 /* handle array classes */
2115 if (name->text[0] == '[') {
2116 c = load_newly_created_array(c, NULL);
2118 goto return_exception;
2119 LOADER_ASSERT(c->loaded);
2124 #if defined(STATISTICS)
2127 if (getcompilingtime)
2128 compilingtime_stop();
2131 loadingtime_start();
2134 /* load classdata, throw exception on error */
2136 if ((cb = suck_start(c)) == NULL) {
2137 /* this normally means, the classpath was not set properly */
2139 if (name == utf_java_lang_Object)
2140 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2141 "java/lang/Object");
2144 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2146 goto return_exception;
2149 /* load the class from the buffer */
2151 r = load_class_from_classbuffer(cb);
2157 #if defined(STATISTICS)
2163 if (getcompilingtime)
2164 compilingtime_start();
2168 /* the class could not be loaded, free the classinfo struct */
2173 /* store this class in the loaded class cache */
2174 /* this step also checks the loading constraints */
2175 /* If the class has been loaded before, the */
2176 /* earlier loaded class is returned. */
2177 classinfo *res = classcache_store(NULL,c,true);
2186 goto return_exception;
2200 /* load_class_from_classbuffer *************************************************
2202 Loads everything interesting about a class from the class file. The
2203 'classinfo' structure must have been allocated previously.
2205 The super class and the interfaces implemented by this class need
2206 not be loaded. The link is set later by the function 'class_link'.
2208 The loaded class is removed from the list 'unloadedclasses' and
2209 added to the list 'unlinkedclasses'.
2212 This function is NOT synchronized!
2214 *******************************************************************************/
2216 classinfo *load_class_from_classbuffer(classbuffer *cb)
2224 descriptor_pool *descpool;
2225 #if defined(STATISTICS)
2229 #ifdef LOADER_VERBOSE
2230 char logtext[MAXLOGTEXT];
2233 /* get the classbuffer's class */
2237 /* maybe the class is already loaded */
2242 #ifdef LOADER_VERBOSE
2243 LOADER_INDENT(logtext);
2244 strcat(logtext,"load_class_from_classbuffer(");
2245 utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2250 #if defined(STATISTICS)
2252 count_class_loads++;
2255 /* output for debugging purposes */
2258 log_message_class("Loading class: ", c);
2260 /* mark start of dump memory area */
2262 dumpsize = dump_size();
2264 /* class is somewhat loaded */
2268 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2269 goto return_exception;
2271 /* check signature */
2273 if (suck_u4(cb) != MAGIC) {
2274 *exceptionptr = new_classformaterror(c, "Bad magic number");
2276 goto return_exception;
2284 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2286 new_unsupportedclassversionerror(c,
2287 "Unsupported major.minor version %d.%d",
2290 goto return_exception;
2293 /* create a new descriptor pool */
2295 descpool = descriptor_pool_new(c);
2297 /* load the constant pool */
2299 if (!load_constantpool(cb, descpool))
2300 goto return_exception;
2303 c->erroneous_state = 0;
2304 c->initializing_thread = 0;
2306 c->classUsed = NOTUSED; /* not used initially CO-RT */
2311 if (!check_classbuffer_size(cb, 2))
2312 goto return_exception;
2314 c->flags = suck_u2(cb);
2316 /* check ACC flags consistency */
2318 if (c->flags & ACC_INTERFACE) {
2319 if (!(c->flags & ACC_ABSTRACT)) {
2320 /* We work around this because interfaces in JDK 1.1 are
2321 * not declared abstract. */
2323 c->flags |= ACC_ABSTRACT;
2326 if (c->flags & ACC_FINAL) {
2328 new_classformaterror(c,
2329 "Illegal class modifiers: 0x%X", c->flags);
2331 goto return_exception;
2334 if (c->flags & ACC_SUPER) {
2335 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2339 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2341 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2343 goto return_exception;
2346 if (!check_classbuffer_size(cb, 2 + 2))
2347 goto return_exception;
2352 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2353 goto return_exception;
2355 if (c->name == utf_not_named_yet) {
2356 /* we finally have a name for this class */
2358 class_set_packagename(c);
2360 } else if (name != c->name) {
2364 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2365 utf_strlen(name) + strlen(")") + strlen("0");
2367 msg = MNEW(char, msglen);
2369 utf_sprint(msg, c->name);
2370 strcat(msg, " (wrong name: ");
2371 utf_strcat(msg, name);
2375 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2377 MFREE(msg, char, msglen);
2379 goto return_exception;
2382 /* retrieve superclass */
2384 c->super.any = NULL;
2385 if ((i = suck_u2(cb))) {
2386 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2387 goto return_exception;
2389 /* java.lang.Object may not have a super class. */
2391 if (c->name == utf_java_lang_Object) {
2393 new_exception_message(string_java_lang_ClassFormatError,
2394 "java.lang.Object with superclass");
2396 goto return_exception;
2399 /* Interfaces must have java.lang.Object as super class. */
2401 if ((c->flags & ACC_INTERFACE) &&
2402 supername != utf_java_lang_Object) {
2404 new_exception_message(string_java_lang_ClassFormatError,
2405 "Interfaces must have java.lang.Object as superclass");
2407 goto return_exception;
2413 /* This is only allowed for java.lang.Object. */
2415 if (c->name != utf_java_lang_Object) {
2416 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2418 goto return_exception;
2422 /* retrieve interfaces */
2424 if (!check_classbuffer_size(cb, 2))
2425 goto return_exception;
2427 c->interfacescount = suck_u2(cb);
2429 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2430 goto return_exception;
2432 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2433 for (i = 0; i < c->interfacescount; i++) {
2434 /* the classrefs are created later */
2435 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2436 goto return_exception;
2440 if (!check_classbuffer_size(cb, 2))
2441 goto return_exception;
2443 c->fieldscount = suck_u2(cb);
2444 c->fields = GCNEW(fieldinfo, c->fieldscount);
2445 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2446 for (i = 0; i < c->fieldscount; i++) {
2447 if (!load_field(cb, &(c->fields[i]),descpool))
2448 goto return_exception;
2452 if (!check_classbuffer_size(cb, 2))
2453 goto return_exception;
2455 c->methodscount = suck_u2(cb);
2456 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2457 c->methods = MNEW(methodinfo, c->methodscount);
2458 for (i = 0; i < c->methodscount; i++) {
2459 if (!load_method(cb, &(c->methods[i]),descpool))
2460 goto return_exception;
2463 /* create the class reference table */
2466 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2468 /* allocate space for the parsed descriptors */
2470 descriptor_pool_alloc_parsed_descriptors(descpool);
2472 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2474 #if defined(STATISTICS)
2476 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2477 count_classref_len += classrefsize;
2478 count_parsed_desc_len += descsize;
2482 /* put the classrefs in the constant pool */
2483 for (i = 0; i < c->cpcount; i++) {
2484 if (c->cptags[i] == CONSTANT_Class) {
2485 utf *name = (utf *) c->cpinfos[i];
2486 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2490 /* set the super class reference */
2493 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2495 goto return_exception;
2498 /* set the super interfaces references */
2500 for (i = 0; i < c->interfacescount; i++) {
2501 c->interfaces[i].ref =
2502 descriptor_pool_lookup_classref(descpool,
2503 (utf *) c->interfaces[i].any);
2504 if (!c->interfaces[i].ref)
2505 goto return_exception;
2508 /* parse field descriptors */
2510 for (i = 0; i < c->fieldscount; i++) {
2511 c->fields[i].parseddesc =
2512 descriptor_pool_parse_field_descriptor(descpool,
2513 c->fields[i].descriptor);
2514 if (!c->fields[i].parseddesc)
2515 goto return_exception;
2518 /* parse method descriptors */
2520 for (i = 0; i < c->methodscount; i++) {
2521 methodinfo *m = &c->methods[i];
2523 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2524 m->flags, class_get_self_classref(m->class));
2526 goto return_exception;
2528 for (j = 0; j < m->exceptiontablelength; j++) {
2529 if (!m->exceptiontable[j].catchtype.any)
2531 if ((m->exceptiontable[j].catchtype.ref =
2532 descriptor_pool_lookup_classref(descpool,
2533 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2534 goto return_exception;
2537 for (j = 0; j < m->thrownexceptionscount; j++) {
2538 if (!m->thrownexceptions[j].any)
2540 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2541 (utf *) m->thrownexceptions[j].any)) == NULL)
2542 goto return_exception;
2546 /* parse the loaded descriptors */
2548 for (i = 0; i < c->cpcount; i++) {
2549 constant_FMIref *fmi;
2552 switch (c->cptags[i]) {
2553 case CONSTANT_Fieldref:
2554 fmi = (constant_FMIref *) c->cpinfos[i];
2555 fmi->parseddesc.fd =
2556 descriptor_pool_parse_field_descriptor(descpool,
2558 if (!fmi->parseddesc.fd)
2559 goto return_exception;
2560 index = (int) (size_t) fmi->classref;
2562 (constant_classref *) class_getconstant(c, index,
2565 goto return_exception;
2567 case CONSTANT_Methodref:
2568 case CONSTANT_InterfaceMethodref:
2569 fmi = (constant_FMIref *) c->cpinfos[i];
2570 index = (int) (size_t) fmi->classref;
2572 (constant_classref *) class_getconstant(c, index,
2575 goto return_exception;
2576 fmi->parseddesc.md =
2577 descriptor_pool_parse_method_descriptor(descpool,
2581 if (!fmi->parseddesc.md)
2582 goto return_exception;
2587 /* Check if all fields and methods can be uniquely
2588 * identified by (name,descriptor). */
2591 /* We use a hash table here to avoid making the
2592 * average case quadratic in # of methods, fields.
2594 static int shift = 0;
2596 u2 *next; /* for chaining colliding hash entries */
2602 /* Allocate hashtable */
2603 len = c->methodscount;
2604 if (len < c->fieldscount) len = c->fieldscount;
2606 hashtab = MNEW(u2,(hashlen + len));
2607 next = hashtab + hashlen;
2609 /* Determine bitshift (to get good hash values) */
2619 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2621 for (i = 0; i < c->fieldscount; ++i) {
2622 fieldinfo *fi = c->fields + i;
2624 /* It's ok if we lose bits here */
2625 index = ((((size_t) fi->name) +
2626 ((size_t) fi->descriptor)) >> shift) % hashlen;
2628 if ((old = hashtab[index])) {
2632 if (c->fields[old].name == fi->name &&
2633 c->fields[old].descriptor == fi->descriptor) {
2635 new_classformaterror(c,
2636 "Repetitive field name/signature");
2638 goto return_exception;
2640 } while ((old = next[old]));
2642 hashtab[index] = i + 1;
2646 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2648 for (i = 0; i < c->methodscount; ++i) {
2649 methodinfo *mi = c->methods + i;
2651 /* It's ok if we lose bits here */
2652 index = ((((size_t) mi->name) +
2653 ((size_t) mi->descriptor)) >> shift) % hashlen;
2657 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2658 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2662 if ((old = hashtab[index])) {
2666 if (c->methods[old].name == mi->name &&
2667 c->methods[old].descriptor == mi->descriptor) {
2669 new_classformaterror(c,
2670 "Repetitive method name/signature");
2672 goto return_exception;
2674 } while ((old = next[old]));
2676 hashtab[index] = i + 1;
2679 MFREE(hashtab, u2, (hashlen + len));
2682 #if defined(STATISTICS)
2684 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2685 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2686 count_class_infos += sizeof(methodinfo) * c->methodscount;
2690 /* load attribute structures */
2692 if (!check_classbuffer_size(cb, 2))
2693 goto return_exception;
2695 if (!load_attributes(cb, suck_u2(cb)))
2696 goto return_exception;
2699 /* Pre java 1.5 version don't check this. This implementation is like
2700 java 1.5 do it: for class file version 45.3 we don't check it, older
2701 versions are checked.
2703 if ((ma == 45 && mi > 3) || ma > 45) {
2704 /* check if all data has been read */
2705 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2707 if (classdata_left > 0) {
2709 new_classformaterror(c, "Extra bytes at the end of class file");
2710 goto return_exception;
2715 /* release dump area */
2717 dump_release(dumpsize);
2720 log_message_class("Loading done class: ", c);
2726 /* release dump area */
2728 dump_release(dumpsize);
2730 /* an exception has been thrown */
2737 /* load_newly_created_array ****************************************************
2739 Load a newly created array class.
2742 c....................the array class C has been loaded
2743 other classinfo......the array class was found in the class cache,
2745 NULL.................an exception has been thrown
2748 This is an internal function. Do not use it unless you know exactly
2751 Use one of the load_class_... functions for general array class loading.
2753 *******************************************************************************/
2755 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2757 classinfo *comp = NULL;
2759 methoddesc *clonedesc;
2760 constant_classref *classrefs;
2765 #ifdef LOADER_VERBOSE
2766 char logtext[MAXLOGTEXT];
2767 LOADER_INDENT(logtext);
2768 strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2769 sprintf(logtext+strlen(logtext),") loader=%p",loader);
2773 text = c->name->text;
2774 namelen = c->name->blength;
2776 /* Check array class name */
2778 if (namelen < 2 || text[0] != '[') {
2779 *exceptionptr = new_classnotfoundexception(c->name);
2783 /* Check the element type */
2787 /* c is an array of arrays. We have to create the component class. */
2789 u = utf_new_intern(text + 1, namelen - 1);
2791 if (!(comp = load_class_from_classloader(u, loader))) {
2796 LOADER_ASSERT(comp->loaded);
2801 /* the array's flags are that of the component class */
2802 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2803 c->classloader = comp->classloader;
2807 /* c is an array of objects. */
2809 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2810 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2811 *exceptionptr = new_classnotfoundexception(c->name);
2815 u = utf_new_intern(text + 2, namelen - 3);
2818 if (!(comp = load_class_from_classloader(u, loader))) {
2823 LOADER_ASSERT(comp->loaded);
2828 /* the array's flags are that of the component class */
2829 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2830 c->classloader = comp->classloader;
2834 /* c is an array of a primitive type */
2836 /* check for cases like `[II' */
2838 *exceptionptr = new_classnotfoundexception(c->name);
2842 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2843 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2844 c->classloader = NULL;
2847 LOADER_ASSERT(class_java_lang_Object);
2848 LOADER_ASSERT(class_java_lang_Cloneable);
2849 LOADER_ASSERT(class_java_io_Serializable);
2851 /* setup the array class */
2853 c->super.cls = class_java_lang_Object;
2855 c->interfacescount = 2;
2856 c->interfaces = MNEW(classref_or_classinfo, 2);
2861 tc = class_java_lang_Cloneable;
2862 LOADER_ASSERT(tc->loaded);
2863 list_addfirst(&unlinkedclasses, tc);
2864 c->interfaces[0].cls = tc;
2866 tc = class_java_io_Serializable;
2867 LOADER_ASSERT(tc->loaded);
2868 list_addfirst(&unlinkedclasses, tc);
2869 c->interfaces[1].cls = tc;
2872 c->interfaces[0].cls = class_java_lang_Cloneable;
2873 c->interfaces[1].cls = class_java_io_Serializable;
2876 c->methodscount = 1;
2877 c->methods = MNEW(methodinfo, c->methodscount);
2879 classrefs = MNEW(constant_classref, 2);
2880 CLASSREF_INIT(classrefs[0], c, c->name);
2881 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2883 /* create descriptor for clone method */
2884 /* we need one paramslot which is reserved for the 'this' parameter */
2885 clonedesc = NEW(methoddesc);
2886 clonedesc->returntype.type = TYPE_ADDRESS;
2887 clonedesc->returntype.classref = classrefs + 1;
2888 clonedesc->returntype.arraydim = 0;
2889 /* initialize params to "empty", add real params below in
2890 descriptor_params_from_paramtypes */
2891 clonedesc->paramcount = 0;
2892 clonedesc->paramslots = 0;
2893 clonedesc->paramtypes[0].classref = classrefs + 0;
2895 /* create methodinfo */
2898 MSET(clone, 0, methodinfo, 1);
2900 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2901 initObjectLock(&clone->header);
2904 /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter
2906 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2907 clone->name = utf_clone;
2908 clone->descriptor = utf_void__java_lang_Object;
2909 clone->parseddesc = clonedesc;
2911 clone->monoPoly = MONO;
2913 /* parse the descriptor to get the register allocation */
2915 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2919 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2921 /* XXX: field: length? */
2923 /* array classes are not loaded from class files */
2926 c->parseddescs = (u1 *) clonedesc;
2927 c->parseddescsize = sizeof(methodinfo);
2928 c->classrefs = classrefs;
2929 c->classrefcount = 1;
2931 /* insert class into the loaded class cache */
2932 /* XXX free classinfo if NULL returned? */
2934 return classcache_store(loader,c,true);
2938 /************************* Function: class_findfield ***************************
2940 Searches a 'classinfo' structure for a field having the given name and
2943 *******************************************************************************/
2945 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2949 for (i = 0; i < c->fieldscount; i++) {
2950 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2951 return &(c->fields[i]);
2954 log_text("Can not find field given in CONSTANT_Fieldref");
2957 /* keep compiler happy */
2963 /****************** Function: class_resolvefield_int ***************************
2965 This is an internally used helper function. Do not use this directly.
2967 Tries to resolve a field having the given name and type.
2968 If the field cannot be resolved, NULL is returned.
2970 *******************************************************************************/
2972 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2977 /* search for field in class c */
2979 for (i = 0; i < c->fieldscount; i++) {
2980 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2981 return &(c->fields[i]);
2985 /* try superinterfaces recursively */
2987 for (i = 0; i < c->interfacescount; i++) {
2988 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2993 /* try superclass */
2996 return class_resolvefield_int(c->super.cls, name, desc);
3004 /********************* Function: class_resolvefield ***************************
3006 Resolves a reference from REFERER to a field with NAME and DESC in class C.
3008 If the field cannot be resolved the return value is NULL. If EXCEPT is
3009 true *exceptionptr is set, too.
3011 *******************************************************************************/
3013 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
3014 classinfo *referer, bool except)
3018 /* XXX resolve class c */
3019 /* XXX check access from REFERER to C */
3021 fi = class_resolvefield_int(c, name, desc);
3026 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
3032 /* XXX check access rights */
3038 /* class_findmethod ************************************************************
3040 Searches a 'classinfo' structure for a method having the given name
3041 and descriptor. If descriptor is NULL, it is ignored.
3043 *******************************************************************************/
3045 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3050 for (i = 0; i < c->methodscount; i++) {
3051 m = &(c->methods[i]);
3053 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
3061 /*********************** Function: class_fetchmethod **************************
3063 like class_findmethod, but aborts with an error if the method is not found
3065 *******************************************************************************/
3067 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3071 mi = class_findmethod(c, name, desc);
3074 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3075 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3076 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3078 log_text("Method not found");
3086 /************************* Function: class_findmethod_approx ******************
3088 like class_findmethod but ignores the return value when comparing the
3091 *******************************************************************************/
3093 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3097 for (i = 0; i < c->methodscount; i++) {
3098 if (c->methods[i].name == name) {
3099 utf *meth_descr = c->methods[i].descriptor;
3103 return &(c->methods[i]);
3105 if (desc->blength <= meth_descr->blength) {
3106 /* current position in utf text */
3107 char *desc_utf_ptr = desc->text;
3108 char *meth_utf_ptr = meth_descr->text;
3109 /* points behind utf strings */
3110 char *desc_end = UTF_END(desc);
3111 char *meth_end = UTF_END(meth_descr);
3114 /* compare argument types */
3115 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3117 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3118 break; /* no match */
3121 return &(c->methods[i]); /* all parameter types equal */
3131 /***************** Function: class_resolvemethod_approx ***********************
3133 Searches a class and every super class for a method (without paying
3134 attention to the return value)
3136 *******************************************************************************/
3138 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3141 /* search for method (ignore returntype) */
3142 methodinfo *m = class_findmethod_approx(c, name, desc);
3145 /* search superclass */
3153 /* class_resolvemethod *********************************************************
3155 Searches a class and it's super classes for a method.
3157 *******************************************************************************/
3159 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3164 m = class_findmethod(c, name, desc);
3176 /* class_resolveinterfacemethod_intern *****************************************
3178 Internally used helper function. Do not use this directly.
3180 *******************************************************************************/
3182 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
3183 utf *name, utf *desc)
3188 m = class_findmethod(c, name, desc);
3193 /* try the superinterfaces */
3195 for (i = 0; i < c->interfacescount; i++) {
3196 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3206 /* class_resolveinterfacemethod ************************************************
3208 Resolves a reference from REFERER to a method with NAME and DESC in
3211 If the method cannot be resolved the return value is NULL. If
3212 EXCEPT is true *exceptionptr is set, too.
3214 *******************************************************************************/
3216 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3217 classinfo *referer, bool except)
3221 /* XXX resolve class c */
3222 /* XXX check access from REFERER to C */
3224 if (!(c->flags & ACC_INTERFACE)) {
3227 new_exception(string_java_lang_IncompatibleClassChangeError);
3232 mi = class_resolveinterfacemethod_intern(c, name, desc);
3237 /* try class java.lang.Object */
3239 mi = class_findmethod(class_java_lang_Object, name, desc);
3246 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3252 /* class_resolveclassmethod ****************************************************
3254 Resolves a reference from REFERER to a method with NAME and DESC in
3257 If the method cannot be resolved the return value is NULL. If
3258 EXCEPT is true *exceptionptr is set, too.
3260 *******************************************************************************/
3262 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3263 classinfo *referer, bool except)
3271 /* XXX resolve class c */
3272 /* XXX check access from REFERER to C */
3274 /* if (c->flags & ACC_INTERFACE) { */
3276 /* *exceptionptr = */
3277 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3281 /* try class c and its superclasses */
3286 mi = class_findmethod(cls, name, desc);
3291 cls = cls->super.cls;
3294 /* try the superinterfaces */
3296 for (i = 0; i < c->interfacescount; i++) {
3297 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
3305 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3306 utf_strlen(desc) + strlen("0");
3308 msg = MNEW(char, msglen);
3310 utf_sprint(msg, c->name);
3312 utf_sprint(msg + strlen(msg), name);
3313 utf_sprint(msg + strlen(msg), desc);
3316 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3318 MFREE(msg, char, msglen);
3324 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3326 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3331 /* XXX check access rights */
3337 /************************* Function: class_issubclass **************************
3339 Checks if sub is a descendant of super.
3341 *******************************************************************************/
3343 bool class_issubclass(classinfo *sub, classinfo *super)
3346 if (!sub) return false;
3347 if (sub == super) return true;
3348 sub = sub->super.cls;
3353 void class_showconstanti(classinfo *c, int ii)
3359 printf ("#%d: ", (int) i);
3361 switch (c->cptags [i]) {
3362 case CONSTANT_Class:
3363 printf("Classreference -> ");
3364 utf_display(((constant_classref*)e)->name);
3367 case CONSTANT_Fieldref:
3368 printf("Fieldref -> "); goto displayFMIi;
3369 case CONSTANT_Methodref:
3370 printf("Methodref -> "); goto displayFMIi;
3371 case CONSTANT_InterfaceMethodref:
3372 printf("InterfaceMethod -> "); goto displayFMIi;
3375 constant_FMIref *fmi = e;
3376 utf_display(fmi->classref->name);
3378 utf_display(fmi->name);
3380 utf_display(fmi->descriptor);
3384 case CONSTANT_String:
3385 printf("String -> ");
3388 case CONSTANT_Integer:
3389 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3391 case CONSTANT_Float:
3392 printf("Float -> %f", ((constant_float*)e)->value);
3394 case CONSTANT_Double:
3395 printf("Double -> %f", ((constant_double*)e)->value);
3399 u8 v = ((constant_long*)e)->value;
3401 printf("Long -> %ld", (long int) v);
3403 printf("Long -> HI: %ld, LO: %ld\n",
3404 (long int) v.high, (long int) v.low);
3408 case CONSTANT_NameAndType:
3410 constant_nameandtype *cnt = e;
3411 printf("NameAndType: ");
3412 utf_display(cnt->name);
3414 utf_display(cnt->descriptor);
3422 log_text("Invalid type of ConstantPool-Entry");
3430 void class_showconstantpool (classinfo *c)
3435 printf ("---- dump of constant pool ----\n");
3437 for (i=0; i<c->cpcount; i++) {
3438 printf ("#%d: ", (int) i);
3440 e = c -> cpinfos [i];
3443 switch (c -> cptags [i]) {
3444 case CONSTANT_Class:
3445 printf ("Classreference -> ");
3446 utf_display ( ((constant_classref*)e) -> name );
3449 case CONSTANT_Fieldref:
3450 printf ("Fieldref -> "); goto displayFMI;
3451 case CONSTANT_Methodref:
3452 printf ("Methodref -> "); goto displayFMI;
3453 case CONSTANT_InterfaceMethodref:
3454 printf ("InterfaceMethod -> "); goto displayFMI;
3457 constant_FMIref *fmi = e;
3458 utf_display ( fmi->classref->name );
3460 utf_display ( fmi->name);
3462 utf_display ( fmi->descriptor );
3466 case CONSTANT_String:
3467 printf ("String -> ");
3470 case CONSTANT_Integer:
3471 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3473 case CONSTANT_Float:
3474 printf ("Float -> %f", ((constant_float*)e) -> value);
3476 case CONSTANT_Double:
3477 printf ("Double -> %f", ((constant_double*)e) -> value);
3481 u8 v = ((constant_long*)e) -> value;
3483 printf ("Long -> %ld", (long int) v);
3485 printf ("Long -> HI: %ld, LO: %ld\n",
3486 (long int) v.high, (long int) v.low);
3490 case CONSTANT_NameAndType:
3492 constant_nameandtype *cnt = e;
3493 printf ("NameAndType: ");
3494 utf_display (cnt->name);
3496 utf_display (cnt->descriptor);
3500 printf ("Utf8 -> ");
3504 log_text("Invalid type of ConstantPool-Entry");
3515 /********** Function: class_showmethods (debugging only) *************/
3517 void class_showmethods (classinfo *c)
3521 printf ("--------- Fields and Methods ----------------\n");
3522 printf ("Flags: "); printflags (c->flags); printf ("\n");
3524 printf ("This: "); utf_display (c->name); printf ("\n");
3526 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3528 printf ("Index: %d\n", c->index);
3530 printf ("interfaces:\n");
3531 for (i=0; i < c-> interfacescount; i++) {
3533 utf_display (c -> interfaces[i].cls -> name);
3534 printf (" (%d)\n", c->interfaces[i].cls -> index);
3537 printf ("fields:\n");
3538 for (i=0; i < c -> fieldscount; i++) {
3539 field_display (&(c -> fields[i]));
3542 printf ("methods:\n");
3543 for (i=0; i < c -> methodscount; i++) {
3544 methodinfo *m = &(c->methods[i]);
3545 if ( !(m->flags & ACC_STATIC))
3546 printf ("vftblindex: %d ", m->vftblindex);
3548 method_display ( m );
3552 printf ("Virtual function table:\n");
3553 for (i=0; i<c->vftbl->vftbllength; i++) {
3554 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3560 /* loader_close ****************************************************************
3562 Frees all resources.
3564 *******************************************************************************/
3566 void loader_close(void)
3573 * These are local overrides for various environment variables in Emacs.
3574 * Please do not remove this and leave it at the end of the file, where
3575 * Emacs will automagically detect them.
3576 * ---------------------------------------------------------------------
3579 * indent-tabs-mode: t