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 2300 2005-04-14 06:07:11Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Throwable.h"
50 #if defined(USE_THREADS)
51 # if defined(NATIVE_THREADS)
52 # include "threads/native/threads.h"
54 # include "threads/green/threads.h"
55 # include "threads/green/locks.h"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
61 #include "vm/exceptions.h"
62 #include "vm/builtin.h"
63 #include "vm/global.h"
64 #include "vm/linker.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69 #include "vm/tables.h"
70 #include "vm/classcache.h"
73 # include "vm/unzip.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/codegen.inc.h"
80 /******************************************************************************/
82 /******************************************************************************/
84 /*#define LOADER_VERBOSE*/
91 #define LOADER_ASSERT(cond) assert(cond)
93 #define LOADER_ASSERT(cond)
100 #ifdef LOADER_VERBOSE
101 static int loader_recursion = 0;
102 #define LOADER_INDENT(str) do { int i; for(i=0;i<loader_recursion*4;++i) {str[i]=' ';} str[i]=0;} while (0)
103 #define LOADER_INC() loader_recursion++
104 #define LOADER_DEC() loader_recursion--
111 /********************************************************************
112 list of classpath entries (either filesystem directories or
114 ********************************************************************/
116 classpath_info *classpath_entries = NULL;
118 /* loader_init *****************************************************************
120 Initializes all lists and loads all classes required for the system
123 *******************************************************************************/
125 bool loader_init(u1 *stackbottom)
129 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
130 /* Initialize the monitor pointer for zip/jar file locking. */
132 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
133 if (cpi->type == CLASSPATH_ARCHIVE)
134 initObjectLock(&cpi->header);
138 /* load some important classes */
140 if (!load_class_bootstrap(utf_java_lang_Object, &class_java_lang_Object))
143 if (!load_class_bootstrap(utf_java_lang_String, &class_java_lang_String))
146 if (!load_class_bootstrap(utf_java_lang_Cloneable, &class_java_lang_Cloneable))
149 if (!load_class_bootstrap(utf_java_io_Serializable, &class_java_io_Serializable))
153 /* load classes for wrapping primitive types */
155 if (!load_class_bootstrap(utf_java_lang_Void, &class_java_lang_Void))
158 if (!load_class_bootstrap(utf_java_lang_Boolean, &class_java_lang_Boolean))
161 if (!load_class_bootstrap(utf_java_lang_Byte, &class_java_lang_Byte))
164 if (!load_class_bootstrap(utf_java_lang_Character, &class_java_lang_Character))
167 if (!load_class_bootstrap(utf_java_lang_Short, &class_java_lang_Short))
170 if (!load_class_bootstrap(utf_java_lang_Integer, &class_java_lang_Integer))
173 if (!load_class_bootstrap(utf_java_lang_Long, &class_java_lang_Long))
176 if (!load_class_bootstrap(utf_java_lang_Float, &class_java_lang_Float))
179 if (!load_class_bootstrap(utf_java_lang_Double, &class_java_lang_Double))
183 /* load some other important classes */
185 if (!load_class_bootstrap(utf_java_lang_Class, &class_java_lang_Class))
188 if (!load_class_bootstrap(utf_java_lang_ClassLoader, &class_java_lang_ClassLoader))
191 if (!load_class_bootstrap(utf_java_lang_SecurityManager, &class_java_lang_SecurityManager))
194 if (!load_class_bootstrap(utf_java_lang_System, &class_java_lang_System))
198 if (!load_class_bootstrap(utf_java_util_Vector, &class_java_util_Vector))
201 #if defined(USE_THREADS)
202 if (stackbottom != 0)
210 /************* functions for reading classdata *********************************
212 getting classdata in blocks of variable size
213 (8,16,32,64-bit integer or float)
215 *******************************************************************************/
217 /* check_classbuffer_size ******************************************************
219 assert that at least <len> bytes are left to read
220 <len> is limited to the range of non-negative s4 values
222 *******************************************************************************/
224 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
226 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
228 new_classformaterror((cb)->class, "Truncated class file");
237 /* suck_nbytes *****************************************************************
239 transfer block of classfile data into a buffer
241 *******************************************************************************/
243 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
245 memcpy(buffer, cb->pos + 1, len);
250 /* skip_nbytes ****************************************************************
252 skip block of classfile data
254 *******************************************************************************/
256 inline void skip_nbytes(classbuffer *cb, s4 len)
262 inline u1 suck_u1(classbuffer *cb)
268 inline u2 suck_u2(classbuffer *cb)
272 return ((u2) a << 8) + (u2) b;
276 inline u4 suck_u4(classbuffer *cb)
282 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
286 /* get u8 from classfile data */
287 static u8 suck_u8(classbuffer *cb)
293 return (hi << 32) + lo;
296 v.high = suck_u4(cb);
303 /* get float from classfile data */
304 static float suck_float(classbuffer *cb)
312 for (i = 0; i < 4; i++)
313 buffer[3 - i] = suck_u1(cb);
315 memcpy((u1*) (&f), buffer, 4);
317 suck_nbytes((u1*) (&f), cb, 4);
320 if (sizeof(float) != 4) {
321 *exceptionptr = new_exception_message(string_java_lang_InternalError,
322 "Incompatible float-format");
324 /* XXX should we exit in such a case? */
325 throw_exception_exit();
332 /* get double from classfile data */
333 static double suck_double(classbuffer *cb)
341 for (i = 0; i < 8; i++)
342 buffer[7 - i] = suck_u1(cb);
344 memcpy((u1*) (&d), buffer, 8);
346 suck_nbytes((u1*) (&d), cb, 8);
349 if (sizeof(double) != 8) {
350 *exceptionptr = new_exception_message(string_java_lang_InternalError,
351 "Incompatible double-format");
353 /* XXX should we exit in such a case? */
354 throw_exception_exit();
361 /************************** function suck_init *********************************
363 called once at startup, sets the searchpath for the classfiles
365 *******************************************************************************/
367 void suck_init(char *classpath)
375 classpath_info *lastcpi;
379 /* search for last classpath entry (only if there already some) */
381 if ((lastcpi = classpath_entries)) {
382 while (lastcpi->next)
383 lastcpi = lastcpi->next;
386 for (start = classpath; (*start) != '\0';) {
388 /* search for ':' delimiter to get the end of the current entry */
389 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
393 filenamelen = end - start;
395 if (filenamelen > 3) {
396 if (strncasecmp(end - 3, "zip", 3) == 0 ||
397 strncasecmp(end - 3, "jar", 3) == 0) {
402 /* save classpath entries as absolute pathnames */
407 if (*start != '/') { /* XXX fix me for win32 */
409 cwdlen = strlen(cwd) + strlen("/");
412 /* allocate memory for filename and fill it */
414 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
418 strcpy(filename, cwd);
419 strcat(filename, "/");
420 strncat(filename, start, filenamelen);
422 /* add cwd length to file length */
423 filenamelen += cwdlen;
426 strncpy(filename, start, filenamelen);
427 filename[filenamelen] = '\0';
433 #if defined(USE_ZLIB)
434 unzFile uf = unzOpen(filename);
437 cpi = NEW(classpath_info);
438 cpi->type = CLASSPATH_ARCHIVE;
441 cpi->path = filename;
442 cpi->pathlen = filenamelen;
446 throw_cacao_exception_exit(string_java_lang_InternalError,
447 "zip/jar files not supported");
451 cpi = NEW(classpath_info);
452 cpi->type = CLASSPATH_PATH;
455 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
456 filename[filenamelen] = '/';
457 filename[filenamelen + 1] = '\0';
461 cpi->path = filename;
462 cpi->pathlen = filenamelen;
465 /* attach current classpath entry */
468 if (!classpath_entries)
469 classpath_entries = cpi;
477 /* goto next classpath entry, skip ':' delimiter */
489 void create_all_classes()
494 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
495 #if defined(USE_ZLIB)
496 if (cpi->type == CLASSPATH_ARCHIVE) {
500 s = (unz_s *) cpi->uf;
501 ce = s->cacao_dir_list;
504 load_class_bootstrap(ce->name,&c);
510 #if defined(USE_ZLIB)
517 /* suck_start ******************************************************************
519 Returns true if classbuffer is already loaded or a file for the
520 specified class has succussfully been read in. All directories of
521 the searchpath are used to find the classfile (<classname>.class).
522 Returns false if no classfile is found and writes an error message.
524 *******************************************************************************/
526 classbuffer *suck_start(classinfo *c)
538 /* initialize return value */
543 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
544 filename = MNEW(char, filenamelen);
546 utf_sprint(filename, c->name);
547 strcat(filename, ".class");
549 /* walk through all classpath entries */
551 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
552 #if defined(USE_ZLIB)
553 if (cpi->type == CLASSPATH_ARCHIVE) {
555 #if defined(USE_THREADS)
556 /* enter a monitor on zip/jar archives */
558 builtin_monitorenter((java_objectheader *) cpi);
561 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
562 unz_file_info file_info;
564 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
565 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
566 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
567 cb = NEW(classbuffer);
569 cb->size = file_info.uncompressed_size;
570 cb->data = MNEW(u1, cb->size);
571 cb->pos = cb->data - 1;
573 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
575 if (len != cb->size) {
577 log_text("Error while unzipping");
584 log_text("Error while opening file in archive");
588 log_text("Error while retrieving fileinfo");
591 unzCloseCurrentFile(cpi->uf);
593 #if defined(USE_THREADS)
594 /* leave the monitor */
596 builtin_monitorexit((java_objectheader *) cpi);
600 #endif /* defined(USE_ZLIB) */
602 path = MNEW(char, cpi->pathlen + filenamelen);
603 strcpy(path, cpi->path);
604 strcat(path, filename);
606 classfile = fopen(path, "r");
608 if (classfile) { /* file exists */
609 if (!stat(path, &buffer)) { /* read classfile data */
610 cb = NEW(classbuffer);
612 cb->size = buffer.st_size;
613 cb->data = MNEW(u1, cb->size);
614 cb->pos = cb->data - 1;
616 /* read class data */
617 len = fread(cb->data, 1, cb->size, classfile);
619 if (len != buffer.st_size) {
621 /* if (ferror(classfile)) { */
630 MFREE(path, char, cpi->pathlen + filenamelen);
631 #if defined(USE_ZLIB)
638 dolog("Warning: Can not open class file '%s'", filename);
640 MFREE(filename, char, filenamelen);
646 /************************** function suck_stop *********************************
648 frees memory for buffer with classfile data.
649 Caution: this function may only be called if buffer has been allocated
650 by suck_start with reading a file
652 *******************************************************************************/
654 void suck_stop(classbuffer *cb)
658 MFREE(cb->data, u1, cb->size);
659 FREE(cb, classbuffer);
663 /******************************************************************************/
664 /******************* Some support functions ***********************************/
665 /******************************************************************************/
667 void fprintflags (FILE *fp, u2 f)
669 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
670 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
671 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
672 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
673 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
674 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
675 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
676 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
677 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
678 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
679 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
683 /********** internal function: printflags (only for debugging) ***************/
685 void printflags(u2 f)
687 fprintflags(stdout,f);
691 /********************** Function: skipattributebody ****************************
693 skips an attribute after the 16 bit reference to attribute_name has already
696 *******************************************************************************/
698 static bool skipattributebody(classbuffer *cb)
702 if (!check_classbuffer_size(cb, 4))
707 if (!check_classbuffer_size(cb, len))
710 skip_nbytes(cb, len);
716 /************************* Function: skipattributes ****************************
718 skips num attribute structures
720 *******************************************************************************/
722 static bool skipattributes(classbuffer *cb, u4 num)
727 for (i = 0; i < num; i++) {
728 if (!check_classbuffer_size(cb, 2 + 4))
734 if (!check_classbuffer_size(cb, len))
737 skip_nbytes(cb, len);
744 /* load_constantpool ***********************************************************
746 Loads the constantpool of a class, the entries are transformed into
747 a simpler format by resolving references (a detailed overview of
748 the compact structures can be found in global.h).
750 *******************************************************************************/
752 static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
755 /* The following structures are used to save information which cannot be
756 processed during the first pass. After the complete constantpool has
757 been traversed the references can be resolved.
758 (only in specific order) */
760 /* CONSTANT_Class entries */
761 typedef struct forward_class {
762 struct forward_class *next;
767 /* CONSTANT_String */
768 typedef struct forward_string {
769 struct forward_string *next;
774 /* CONSTANT_NameAndType */
775 typedef struct forward_nameandtype {
776 struct forward_nameandtype *next;
780 } forward_nameandtype;
782 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
783 typedef struct forward_fieldmethint {
784 struct forward_fieldmethint *next;
788 u2 nameandtype_index;
789 } forward_fieldmethint;
795 forward_class *forward_classes = NULL;
796 forward_string *forward_strings = NULL;
797 forward_nameandtype *forward_nameandtypes = NULL;
798 forward_fieldmethint *forward_fieldmethints = NULL;
802 forward_nameandtype *nfn;
803 forward_fieldmethint *nff;
811 /* number of entries in the constant_pool table plus one */
812 if (!check_classbuffer_size(cb, 2))
815 cpcount = c->cpcount = suck_u2(cb);
817 /* allocate memory */
818 cptags = c->cptags = MNEW(u1, cpcount);
819 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
822 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
826 #if defined(STATISTICS)
828 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
831 /* initialize constantpool */
832 for (idx = 0; idx < cpcount; idx++) {
833 cptags[idx] = CONSTANT_UNUSED;
838 /******* first pass *******/
839 /* entries which cannot be resolved now are written into
840 temporary structures and traversed again later */
843 while (idx < cpcount) {
846 /* get constant type */
847 if (!check_classbuffer_size(cb, 1))
854 nfc = DNEW(forward_class);
856 nfc->next = forward_classes;
857 forward_classes = nfc;
859 nfc->thisindex = idx;
860 /* reference to CONSTANT_NameAndType */
861 if (!check_classbuffer_size(cb, 2))
864 nfc->name_index = suck_u2(cb);
869 case CONSTANT_String:
870 nfs = DNEW(forward_string);
872 nfs->next = forward_strings;
873 forward_strings = nfs;
875 nfs->thisindex = idx;
877 /* reference to CONSTANT_Utf8_info with string characters */
878 if (!check_classbuffer_size(cb, 2))
881 nfs->string_index = suck_u2(cb);
886 case CONSTANT_NameAndType:
887 nfn = DNEW(forward_nameandtype);
889 nfn->next = forward_nameandtypes;
890 forward_nameandtypes = nfn;
892 nfn->thisindex = idx;
894 if (!check_classbuffer_size(cb, 2 + 2))
897 /* reference to CONSTANT_Utf8_info containing simple name */
898 nfn->name_index = suck_u2(cb);
900 /* reference to CONSTANT_Utf8_info containing field or method
902 nfn->sig_index = suck_u2(cb);
907 case CONSTANT_Fieldref:
908 case CONSTANT_Methodref:
909 case CONSTANT_InterfaceMethodref:
910 nff = DNEW(forward_fieldmethint);
912 nff->next = forward_fieldmethints;
913 forward_fieldmethints = nff;
915 nff->thisindex = idx;
919 if (!check_classbuffer_size(cb, 2 + 2))
922 /* class or interface type that contains the declaration of the
924 nff->class_index = suck_u2(cb);
926 /* name and descriptor of the field or method */
927 nff->nameandtype_index = suck_u2(cb);
932 case CONSTANT_Integer: {
933 constant_integer *ci = NEW(constant_integer);
935 #if defined(STATISTICS)
937 count_const_pool_len += sizeof(constant_integer);
940 if (!check_classbuffer_size(cb, 4))
943 ci->value = suck_s4(cb);
944 cptags[idx] = CONSTANT_Integer;
951 case CONSTANT_Float: {
952 constant_float *cf = NEW(constant_float);
954 #if defined(STATISTICS)
956 count_const_pool_len += sizeof(constant_float);
959 if (!check_classbuffer_size(cb, 4))
962 cf->value = suck_float(cb);
963 cptags[idx] = CONSTANT_Float;
970 case CONSTANT_Long: {
971 constant_long *cl = NEW(constant_long);
973 #if defined(STATISTICS)
975 count_const_pool_len += sizeof(constant_long);
978 if (!check_classbuffer_size(cb, 8))
981 cl->value = suck_s8(cb);
982 cptags[idx] = CONSTANT_Long;
987 new_classformaterror(c, "Invalid constant pool entry");
993 case CONSTANT_Double: {
994 constant_double *cd = NEW(constant_double);
996 #if defined(STATISTICS)
998 count_const_pool_len += sizeof(constant_double);
1001 if (!check_classbuffer_size(cb, 8))
1004 cd->value = suck_double(cb);
1005 cptags[idx] = CONSTANT_Double;
1008 if (idx > cpcount) {
1010 new_classformaterror(c, "Invalid constant pool entry");
1016 case CONSTANT_Utf8: {
1019 /* number of bytes in the bytes array (not string-length) */
1020 if (!check_classbuffer_size(cb, 2))
1023 length = suck_u2(cb);
1024 cptags[idx] = CONSTANT_Utf8;
1026 /* validate the string */
1027 if (!check_classbuffer_size(cb, length))
1031 !is_valid_utf((char *) (cb->pos + 1),
1032 (char *) (cb->pos + 1 + length))) {
1033 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1034 panic("Invalid UTF-8 string");
1036 /* insert utf-string into the utf-symboltable */
1037 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1039 /* skip bytes of the string (buffer size check above) */
1040 skip_nbytes(cb, length);
1047 new_classformaterror(c, "Illegal constant pool type");
1052 /* add all class references to the descriptor_pool */
1053 for (nfc=forward_classes; nfc; nfc=nfc->next) {
1054 utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
1055 if (!descriptor_pool_add_class(descpool,name))
1058 /* add all descriptors in NameAndTypes to the descriptor_pool */
1059 for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
1060 utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
1061 if (!descriptor_pool_add(descpool,desc,NULL))
1065 /* resolve entries in temporary structures */
1067 while (forward_classes) {
1069 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1071 if (opt_verify && !is_valid_name_utf(name)) {
1073 new_classformaterror(c, "Class reference with invalid name");
1077 cptags[forward_classes->thisindex] = CONSTANT_Class;
1078 /* the classref is created later */
1079 cpinfos[forward_classes->thisindex] = name;
1081 nfc = forward_classes;
1082 forward_classes = forward_classes->next;
1085 while (forward_strings) {
1087 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1089 /* resolve utf-string */
1090 cptags[forward_strings->thisindex] = CONSTANT_String;
1091 cpinfos[forward_strings->thisindex] = text;
1093 nfs = forward_strings;
1094 forward_strings = forward_strings->next;
1097 while (forward_nameandtypes) {
1098 constant_nameandtype *cn = NEW(constant_nameandtype);
1100 #if defined(STATISTICS)
1102 count_const_pool_len += sizeof(constant_nameandtype);
1105 /* resolve simple name and descriptor */
1106 cn->name = class_getconstant(c,
1107 forward_nameandtypes->name_index,
1110 cn->descriptor = class_getconstant(c,
1111 forward_nameandtypes->sig_index,
1116 if (!is_valid_name_utf(cn->name)) {
1118 new_classformaterror(c,
1119 "Illegal Field name \"%s\"",
1125 /* disallow referencing <clinit> among others */
1126 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1128 new_exception_utfmessage(string_java_lang_InternalError,
1134 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1135 cpinfos[forward_nameandtypes->thisindex] = cn;
1137 nfn = forward_nameandtypes;
1138 forward_nameandtypes = forward_nameandtypes->next;
1141 while (forward_fieldmethints) {
1142 constant_nameandtype *nat;
1143 constant_FMIref *fmi = NEW(constant_FMIref);
1145 #if defined(STATISTICS)
1147 count_const_pool_len += sizeof(constant_FMIref);
1149 /* resolve simple name and descriptor */
1150 nat = class_getconstant(c,
1151 forward_fieldmethints->nameandtype_index,
1152 CONSTANT_NameAndType);
1154 /* the classref is created later */
1155 fmi->classref = (constant_classref*) (size_t) forward_fieldmethints->class_index;
1156 fmi->name = nat->name;
1157 fmi->descriptor = nat->descriptor;
1159 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1160 cpinfos[forward_fieldmethints->thisindex] = fmi;
1162 nff = forward_fieldmethints;
1163 forward_fieldmethints = forward_fieldmethints->next;
1166 /* everything was ok */
1172 /* load_field ******************************************************************
1174 Load everything about a class field from the class file and fill a
1175 'fieldinfo' structure. For static fields, space in the data segment
1178 *******************************************************************************/
1180 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1182 static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
1187 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1192 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1195 f->flags = suck_u2(cb);
1197 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1201 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1204 f->parseddesc = NULL;
1205 if (!descriptor_pool_add(descpool,u,NULL))
1210 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1211 *exceptionptr = new_classformaterror(c,
1212 "Illegal Field name \"%s\"",
1217 /* check flag consistency */
1218 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1220 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1221 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1223 new_classformaterror(c,
1224 "Illegal field modifiers: 0x%X",
1229 if (c->flags & ACC_INTERFACE) {
1230 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1231 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1232 f->flags & ACC_TRANSIENT) {
1234 new_classformaterror(c,
1235 "Illegal field modifiers: 0x%X",
1242 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1243 f->offset = 0; /* offset from start of object */
1248 case TYPE_INT: f->value.i = 0; break;
1249 case TYPE_FLOAT: f->value.f = 0.0; break;
1250 case TYPE_DOUBLE: f->value.d = 0.0; break;
1251 case TYPE_ADDRESS: f->value.a = NULL; break;
1254 f->value.l = 0; break;
1256 f->value.l.low = 0; f->value.l.high = 0; break;
1260 /* read attributes */
1261 if (!check_classbuffer_size(cb, 2))
1264 attrnum = suck_u2(cb);
1265 for (i = 0; i < attrnum; i++) {
1266 if (!check_classbuffer_size(cb, 2))
1269 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1272 if (u == utf_ConstantValue) {
1273 if (!check_classbuffer_size(cb, 4 + 2))
1276 /* check attribute length */
1277 if (suck_u4(cb) != 2) {
1279 new_classformaterror(c, "Wrong size for VALUE attribute");
1283 /* constant value attribute */
1284 if (pindex != field_load_NOVALUE) {
1286 new_classformaterror(c,
1287 "Multiple ConstantValue attributes");
1291 /* index of value in constantpool */
1292 pindex = suck_u2(cb);
1294 /* initialize field with value from constantpool */
1297 constant_integer *ci;
1299 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1302 f->value.i = ci->value;
1309 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1312 f->value.l = cl->value;
1319 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1322 f->value.f = cf->value;
1327 constant_double *cd;
1329 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1332 f->value.d = cd->value;
1337 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1340 /* create javastring from compressed utf8-string */
1341 f->value.a = literalstring_new(u);
1345 log_text("Invalid Constant - Type");
1349 /* unknown attribute */
1350 if (!skipattributebody(cb))
1355 /* everything was ok */
1361 /* load_method *****************************************************************
1363 Loads a method from the class file and fills an existing
1364 'methodinfo' structure. For native methods, the function pointer
1365 field is set to the real function pointer, for JavaVM methods a
1366 pointer to the compiler is used preliminarily.
1368 *******************************************************************************/
1370 static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
1381 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1382 initObjectLock(&m->header);
1387 count_all_methods++;
1390 m->thrownexceptionscount = 0;
1391 m->linenumbercount = 0;
1394 m->nativelyoverloaded = false;
1396 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1399 m->flags = suck_u2(cb);
1401 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1405 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1408 m->parseddesc = NULL;
1409 if (!descriptor_pool_add(descpool,u,&argcount))
1413 if (!is_valid_name_utf(m->name))
1414 panic("Method with invalid name");
1416 if (m->name->text[0] == '<'
1417 && m->name != utf_init && m->name != utf_clinit)
1418 panic("Method with invalid special name");
1421 if (!(m->flags & ACC_STATIC))
1422 argcount++; /* count the 'this' argument */
1425 if (argcount > 255) {
1427 new_classformaterror(c, "Too many arguments in signature");
1431 /* check flag consistency */
1432 if (m->name != utf_clinit) {
1433 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1435 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1437 new_classformaterror(c,
1438 "Illegal method modifiers: 0x%X",
1443 if (m->flags & ACC_ABSTRACT) {
1444 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1445 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1447 new_classformaterror(c,
1448 "Illegal method modifiers: 0x%X",
1454 if (c->flags & ACC_INTERFACE) {
1455 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1457 new_classformaterror(c,
1458 "Illegal method modifiers: 0x%X",
1464 if (m->name == utf_init) {
1465 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1466 ACC_NATIVE | ACC_ABSTRACT))
1467 panic("Instance initialization method has invalid flags set");
1473 m->basicblockcount = 0;
1474 m->basicblocks = NULL;
1475 m->basicblockindex = NULL;
1476 m->instructioncount = 0;
1477 m->instructions = NULL;
1480 m->exceptiontable = NULL;
1481 m->stubroutine = NULL;
1483 m->entrypoint = NULL;
1484 m->methodUsed = NOTUSED;
1487 m->subRedefsUsed = 0;
1491 if (!check_classbuffer_size(cb, 2))
1494 attrnum = suck_u2(cb);
1495 for (i = 0; i < attrnum; i++) {
1498 if (!check_classbuffer_size(cb, 2))
1501 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1504 if (aname == utf_Code) {
1505 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1507 new_classformaterror(c,
1508 "Code attribute in native or abstract methods");
1515 new_classformaterror(c, "Multiple Code attributes");
1520 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1524 m->maxstack = suck_u2(cb);
1525 m->maxlocals = suck_u2(cb);
1527 if (m->maxlocals < argcount) {
1529 new_classformaterror(c, "Arguments can't fit into locals");
1534 if (!check_classbuffer_size(cb, 4))
1537 m->jcodelength = suck_u4(cb);
1539 if (m->jcodelength == 0) {
1541 new_classformaterror(c, "Code of a method has length 0");
1546 if (m->jcodelength > 65535) {
1548 new_classformaterror(c,
1549 "Code of a method longer than 65535 bytes");
1554 if (!check_classbuffer_size(cb, m->jcodelength))
1557 m->jcode = MNEW(u1, m->jcodelength);
1558 suck_nbytes(m->jcode, cb, m->jcodelength);
1560 if (!check_classbuffer_size(cb, 2))
1563 m->exceptiontablelength = suck_u2(cb);
1564 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1567 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1569 #if defined(STATISTICS)
1571 count_vmcode_len += m->jcodelength + 18;
1572 count_extable_len += 8 * m->exceptiontablelength;
1576 for (j = 0; j < m->exceptiontablelength; j++) {
1578 m->exceptiontable[j].startpc = suck_u2(cb);
1579 m->exceptiontable[j].endpc = suck_u2(cb);
1580 m->exceptiontable[j].handlerpc = suck_u2(cb);
1584 m->exceptiontable[j].catchtype.any = NULL;
1587 /* the classref is created later */
1588 if (!(m->exceptiontable[j].catchtype.any =
1589 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1594 if (!check_classbuffer_size(cb, 2))
1597 codeattrnum = suck_u2(cb);
1599 for (; codeattrnum > 0; codeattrnum--) {
1602 if (!check_classbuffer_size(cb, 2))
1605 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1608 if (caname == utf_LineNumberTable) {
1611 if (!check_classbuffer_size(cb, 4 + 2))
1615 m->linenumbercount = suck_u2(cb);
1617 if (!check_classbuffer_size(cb,
1618 (2 + 2) * m->linenumbercount))
1621 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1623 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1624 m->linenumbers[lncid].start_pc = suck_u2(cb);
1625 m->linenumbers[lncid].line_number = suck_u2(cb);
1629 if (!skipattributes(cb, codeattrnum))
1635 if (!skipattributebody(cb))
1640 } else if (aname == utf_Exceptions) {
1643 if (m->thrownexceptions) {
1645 new_classformaterror(c, "Multiple Exceptions attributes");
1649 if (!check_classbuffer_size(cb, 4 + 2))
1652 suck_u4(cb); /* length */
1653 m->thrownexceptionscount = suck_u2(cb);
1655 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1658 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1660 for (j = 0; j < m->thrownexceptionscount; j++) {
1661 /* the classref is created later */
1662 if (!((m->thrownexceptions)[j].any =
1663 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1668 if (!skipattributebody(cb))
1673 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1674 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1679 /* everything was ok */
1685 /* load_attribute **************************************************************
1687 Read attributes from classfile.
1689 *******************************************************************************/
1691 static bool load_attributes(classbuffer *cb, u4 num)
1699 for (i = 0; i < num; i++) {
1700 /* retrieve attribute name */
1701 if (!check_classbuffer_size(cb, 2))
1704 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1707 if (aname == utf_InnerClasses) {
1708 /* innerclasses attribute */
1709 if (c->innerclass) {
1711 new_classformaterror(c, "Multiple InnerClasses attributes");
1715 if (!check_classbuffer_size(cb, 4 + 2))
1718 /* skip attribute length */
1721 /* number of records */
1722 c->innerclasscount = suck_u2(cb);
1724 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1727 /* allocate memory for innerclass structure */
1728 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1730 for (j = 0; j < c->innerclasscount; j++) {
1731 /* The innerclass structure contains a class with an encoded
1732 name, its defining scope, its simple name and a bitmask of
1733 the access flags. If an inner class is not a member, its
1734 outer_class is NULL, if a class is anonymous, its name is
1737 innerclassinfo *info = c->innerclass + j;
1739 info->inner_class.ref =
1740 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1741 info->outer_class.ref =
1742 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1744 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1745 info->flags = suck_u2(cb);
1748 } else if (aname == utf_SourceFile) {
1749 if (!check_classbuffer_size(cb, 4 + 2))
1752 if (suck_u4(cb) != 2) {
1754 new_classformaterror(c, "Wrong size for VALUE attribute");
1758 if (c->sourcefile) {
1760 new_classformaterror(c, "Multiple SourceFile attributes");
1764 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1768 /* unknown attribute */
1769 if (!skipattributebody(cb))
1777 /* load_class_from_sysloader ***************************************************
1779 Load the class with the given name using the system class loader
1782 name.............the classname
1786 *result..........set to the loaded class
1789 true.............everything ok
1790 false............an exception has been thrown
1792 *******************************************************************************/
1794 bool load_class_from_sysloader(utf *name,classinfo **result)
1797 java_objectheader *cl;
1800 #ifdef LOADER_VERBOSE
1801 char logtext[MAXLOGTEXT];
1802 LOADER_INDENT(logtext);
1803 sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1804 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1808 LOADER_ASSERT(class_java_lang_Object);
1809 LOADER_ASSERT(class_java_lang_ClassLoader);
1810 LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1812 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1813 utf_new_char("getSystemClassLoader"), /* XXX use variable */
1814 utf_new_char("()Ljava/lang/ClassLoader;"), /* XXX use variable */
1815 class_java_lang_Object,
1819 return false; /* exception */
1821 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1823 return false; /* exception */
1826 success = load_class_from_classloader(name,cl,result);
1831 /* load_class_from_classloader *************************************************
1833 Load the class with the given name using the given user-defined class loader.
1836 name.............the classname
1837 cl...............user-defined class loader
1841 *result..........set to the loaded class
1844 true.............everything ok
1845 false............an exception has been thrown
1847 *******************************************************************************/
1849 bool load_class_from_classloader(utf *name,java_objectheader *cl,classinfo **result)
1854 #ifdef LOADER_VERBOSE
1855 char logtext[MAXLOGTEXT];
1856 LOADER_INDENT(logtext);
1857 strcat(logtext,"load_class_from_classloader(");
1858 utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1859 if (!cl) strcat(logtext,"<bootstrap>");
1860 else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1861 else strcat(logtext,"<unknown class>");
1862 strcat(logtext,")");
1866 LOADER_ASSERT(name);
1867 LOADER_ASSERT(result);
1869 /* lookup if this class has already been loaded */
1870 *result = classcache_lookup(cl,name);
1871 #ifdef LOADER_VERBOSE
1873 dolog(" cached -> %p",(void*)(*result));
1879 /* if other class loader than bootstrap, call it */
1884 /* handle array classes */
1885 if (name->text[0] == '[') {
1886 char *utf_ptr = name->text + 1;
1887 int len = name->blength - 1;
1895 /* load the component class */
1897 if (!load_class_from_classloader(utf_new(utf_ptr,len),cl,&comp)) {
1902 /* create the array class */
1903 *result = class_array_of(comp,false);
1904 return (*result != 0);
1907 /* primitive array classes are loaded by the bootstrap loader */
1909 success = load_class_bootstrap(name,result);
1915 LOADER_ASSERT(class_java_lang_Object);
1917 lc = class_resolveclassmethod(cl->vftbl->class,
1919 utf_java_lang_String__java_lang_Class,
1920 class_java_lang_Object,
1924 return false; /* exception */
1927 r = (classinfo *) asm_calljavafunction(lc,
1929 javastring_new_slash_to_dot(name),
1933 /* store this class in the loaded class cache */
1934 if (r && !classcache_store(cl,r)) {
1937 r = NULL; /* exception */
1945 success = load_class_bootstrap(name,result);
1951 /* load_class_bootstrap ********************************************************
1953 Load the class with the given name using the bootstrap class loader.
1956 name.............the classname
1959 *result..........set to the loaded class
1962 true.............everything ok
1963 false............an exception has been thrown
1965 *******************************************************************************/
1967 bool load_class_bootstrap(utf *name, classinfo **result)
1972 #ifdef LOADER_VERBOSE
1973 char logtext[MAXLOGTEXT];
1976 LOADER_ASSERT(name);
1977 LOADER_ASSERT(result);
1979 /* lookup if this class has already been loaded */
1980 *result = classcache_lookup(NULL, name);
1984 /* check if this class has already been defined */
1985 *result = classcache_lookup_defined(NULL, name);
1989 #ifdef LOADER_VERBOSE
1990 LOADER_INDENT(logtext);
1991 strcat(logtext,"load_class_bootstrap(");
1992 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1996 /* create the classinfo */
1997 c = class_create_classinfo(name);
1999 /* handle array classes */
2000 if (name->text[0] == '[') {
2002 if (!load_newly_created_array(c, NULL))
2005 LOADER_ASSERT(c->loaded);
2010 #if defined(USE_THREADS)
2011 /* enter a monitor on the class */
2013 builtin_monitorenter((java_objectheader *) c);
2016 #if defined(STATISTICS)
2018 if (getcompilingtime)
2019 compilingtime_stop();
2022 loadingtime_start();
2025 /* load classdata, throw exception on error */
2027 if ((cb = suck_start(c)) == NULL) {
2028 /* this means, the classpath was not set properly */
2029 if (name == utf_java_lang_Object)
2030 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2031 "java/lang/Object");
2034 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2037 #if defined(USE_THREADS)
2038 builtin_monitorexit((java_objectheader *) c);
2044 /* load the class from the buffer */
2047 r = load_class_from_classbuffer(cb);
2053 #if defined(STATISTICS)
2058 if (getcompilingtime)
2059 compilingtime_start();
2063 #if defined(USE_THREADS)
2064 builtin_monitorexit((java_objectheader *) c);
2069 /* store this class in the loaded class cache */
2070 if (r && !classcache_store(NULL, c)) {
2071 #if defined(USE_THREADS)
2072 builtin_monitorexit((java_objectheader *) c);
2075 r = NULL; /* exception */
2078 #if defined(USE_THREADS)
2079 /* leave the monitor */
2080 if (c) builtin_monitorexit((java_objectheader *) c);
2088 /* load_class_from_classbuffer *************************************************
2090 Loads everything interesting about a class from the class file. The
2091 'classinfo' structure must have been allocated previously.
2093 The super class and the interfaces implemented by this class need
2094 not be loaded. The link is set later by the function 'class_link'.
2096 The loaded class is removed from the list 'unloadedclasses' and
2097 added to the list 'unlinkedclasses'.
2099 *******************************************************************************/
2101 classinfo *load_class_from_classbuffer(classbuffer *cb)
2109 descriptor_pool *descpool;
2110 char msg[MAXLOGTEXT]; /* maybe we get an exception */ /* XXX BUFFER OVERFLOW! */
2111 #if defined(STATISTICS)
2115 #ifdef LOADER_VERBOSE
2116 char logtext[MAXLOGTEXT];
2119 /* get the classbuffer's class */
2122 /* maybe the class is already loaded */
2126 #ifdef LOADER_VERBOSE
2127 LOADER_INDENT(logtext);
2128 strcat(logtext,"load_class_from_classbuffer(");
2129 utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2134 #if defined(STATISTICS)
2136 count_class_loads++;
2139 /* output for debugging purposes */
2141 log_message_class("Loading class: ", c);
2143 /* mark start of dump memory area */
2144 dumpsize = dump_size();
2146 /* class is somewhat loaded */
2149 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2150 goto return_exception;
2152 /* check signature */
2153 if (suck_u4(cb) != MAGIC) {
2154 *exceptionptr = new_classformaterror(c, "Bad magic number");
2156 goto return_exception;
2163 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2165 new_unsupportedclassversionerror(c,
2166 "Unsupported major.minor version %d.%d",
2169 goto return_exception;
2172 /* create a new descriptor pool */
2173 descpool = descriptor_pool_new(c);
2175 /* load the constant pool */
2176 if (!load_constantpool(cb,descpool))
2177 goto return_exception;
2180 c->erroneous_state = 0;
2181 c->initializing_thread = 0;
2183 c->classUsed = NOTUSED; /* not used initially CO-RT */
2187 if (!check_classbuffer_size(cb, 2))
2188 goto return_exception;
2190 c->flags = suck_u2(cb);
2192 /* check ACC flags consistency */
2193 if (c->flags & ACC_INTERFACE) {
2194 if (!(c->flags & ACC_ABSTRACT)) {
2195 /* We work around this because interfaces in JDK 1.1 are
2196 * not declared abstract. */
2198 c->flags |= ACC_ABSTRACT;
2201 if (c->flags & ACC_FINAL) {
2203 new_classformaterror(c,
2204 "Illegal class modifiers: 0x%X", c->flags);
2206 goto return_exception;
2209 if (c->flags & ACC_SUPER) {
2210 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2214 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2216 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2218 goto return_exception;
2221 if (!check_classbuffer_size(cb, 2 + 2))
2222 goto return_exception;
2226 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2227 goto return_exception;
2229 if (c->name == utf_not_named_yet) {
2230 /* we finally have a name for this class */
2232 class_set_packagename(c);
2234 else if (name != c->name) {
2235 utf_sprint(msg, c->name);
2236 strcat(msg, " (wrong name: ");
2237 utf_strcat(msg, name);
2241 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2243 goto return_exception;
2246 /* retrieve superclass */
2247 c->super.any = NULL;
2248 if ((i = suck_u2(cb))) {
2249 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2250 goto return_exception;
2252 /* java.lang.Object may not have a super class. */
2253 if (c->name == utf_java_lang_Object) {
2255 new_exception_message(string_java_lang_ClassFormatError,
2256 "java.lang.Object with superclass");
2258 goto return_exception;
2261 /* Interfaces must have java.lang.Object as super class. */
2262 if ((c->flags & ACC_INTERFACE) &&
2263 supername != utf_java_lang_Object) {
2265 new_exception_message(string_java_lang_ClassFormatError,
2266 "Interfaces must have java.lang.Object as superclass");
2268 goto return_exception;
2274 /* This is only allowed for java.lang.Object. */
2275 if (c->name != utf_java_lang_Object) {
2276 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2278 goto return_exception;
2282 /* retrieve interfaces */
2283 if (!check_classbuffer_size(cb, 2))
2284 goto return_exception;
2286 c->interfacescount = suck_u2(cb);
2288 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2289 goto return_exception;
2291 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2292 for (i = 0; i < c->interfacescount; i++) {
2293 /* the classrefs are created later */
2294 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2295 goto return_exception;
2299 if (!check_classbuffer_size(cb, 2))
2300 goto return_exception;
2302 c->fieldscount = suck_u2(cb);
2303 c->fields = GCNEW(fieldinfo, c->fieldscount);
2304 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2305 for (i = 0; i < c->fieldscount; i++) {
2306 if (!load_field(cb, &(c->fields[i]),descpool))
2307 goto return_exception;
2311 if (!check_classbuffer_size(cb, 2))
2312 goto return_exception;
2314 c->methodscount = suck_u2(cb);
2315 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2316 c->methods = MNEW(methodinfo, c->methodscount);
2317 for (i = 0; i < c->methodscount; i++) {
2318 if (!load_method(cb, &(c->methods[i]),descpool))
2319 goto return_exception;
2322 /* create the class reference table */
2323 c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
2325 /* allocate space for the parsed descriptors */
2326 descriptor_pool_alloc_parsed_descriptors(descpool);
2327 c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
2329 #if defined(STATISTICS)
2331 descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
2332 count_classref_len += classrefsize;
2333 count_parsed_desc_len += descsize;
2337 /* put the classrefs in the constant pool */
2338 for (i = 0; i < c->cpcount; i++) {
2339 if (c->cptags[i] == CONSTANT_Class) {
2340 utf *name = (utf *) c->cpinfos[i];
2341 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2345 /* set the super class reference */
2347 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2349 goto return_exception;
2352 /* set the super interfaces references */
2353 for (i = 0; i < c->interfacescount; i++) {
2354 c->interfaces[i].ref = descriptor_pool_lookup_classref(descpool, (utf *) c->interfaces[i].any);
2355 if (!c->interfaces[i].ref)
2356 goto return_exception;
2359 /* parse the loaded descriptors */
2360 for (i = 0; i < c->cpcount; i++) {
2361 constant_FMIref *fmi;
2364 switch (c->cptags[i]) {
2365 case CONSTANT_Fieldref:
2366 fmi = (constant_FMIref *) c->cpinfos[i];
2367 fmi->parseddesc.fd =
2368 descriptor_pool_parse_field_descriptor(descpool, fmi->descriptor);
2369 if (!fmi->parseddesc.fd)
2370 goto return_exception;
2371 index = (int) (size_t) fmi->classref;
2372 fmi->classref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
2374 goto return_exception;
2376 case CONSTANT_Methodref:
2377 case CONSTANT_InterfaceMethodref:
2378 fmi = (constant_FMIref *) c->cpinfos[i];
2379 fmi->parseddesc.md =
2380 descriptor_pool_parse_method_descriptor(descpool, fmi->descriptor);
2381 if (!fmi->parseddesc.md)
2382 goto return_exception;
2383 index = (int) (size_t) fmi->classref;
2384 fmi->classref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
2386 goto return_exception;
2391 for (i = 0; i < c->fieldscount; i++) {
2392 c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool, c->fields[i].descriptor);
2393 if (!c->fields[i].parseddesc)
2394 goto return_exception;
2397 for (i = 0; i < c->methodscount; i++) {
2398 methodinfo *m = c->methods + i;
2399 m->parseddesc = descriptor_pool_parse_method_descriptor(descpool, m->descriptor);
2401 goto return_exception;
2403 for (j = 0; j < m->exceptiontablelength; j++) {
2404 if (!m->exceptiontable[j].catchtype.any)
2406 if ((m->exceptiontable[j].catchtype.ref =
2407 descriptor_pool_lookup_classref(descpool,
2408 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2409 goto return_exception;
2412 for (j = 0; j < m->thrownexceptionscount; j++) {
2413 if (!m->thrownexceptions[j].any)
2415 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2416 (utf *) m->thrownexceptions[j].any)) == NULL)
2417 goto return_exception;
2421 /* Check if all fields and methods can be uniquely
2422 * identified by (name,descriptor). */
2424 /* We use a hash table here to avoid making the
2425 * average case quadratic in # of methods, fields.
2427 static int shift = 0;
2429 u2 *next; /* for chaining colliding hash entries */
2435 /* Allocate hashtable */
2436 len = c->methodscount;
2437 if (len < c->fieldscount) len = c->fieldscount;
2439 hashtab = MNEW(u2,(hashlen + len));
2440 next = hashtab + hashlen;
2442 /* Determine bitshift (to get good hash values) */
2452 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2454 for (i = 0; i < c->fieldscount; ++i) {
2455 fieldinfo *fi = c->fields + i;
2457 /* It's ok if we lose bits here */
2458 index = ((((size_t) fi->name) +
2459 ((size_t) fi->descriptor)) >> shift) % hashlen;
2461 if ((old = hashtab[index])) {
2465 if (c->fields[old].name == fi->name &&
2466 c->fields[old].descriptor == fi->descriptor) {
2468 new_classformaterror(c,
2469 "Repetitive field name/signature");
2471 goto return_exception;
2473 } while ((old = next[old]));
2475 hashtab[index] = i + 1;
2479 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2481 for (i = 0; i < c->methodscount; ++i) {
2482 methodinfo *mi = c->methods + i;
2484 /* It's ok if we lose bits here */
2485 index = ((((size_t) mi->name) +
2486 ((size_t) mi->descriptor)) >> shift) % hashlen;
2490 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2491 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2495 if ((old = hashtab[index])) {
2499 if (c->methods[old].name == mi->name &&
2500 c->methods[old].descriptor == mi->descriptor) {
2502 new_classformaterror(c,
2503 "Repetitive method name/signature");
2505 goto return_exception;
2507 } while ((old = next[old]));
2509 hashtab[index] = i + 1;
2512 MFREE(hashtab, u2, (hashlen + len));
2515 #if defined(STATISTICS)
2517 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2518 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2519 count_class_infos += sizeof(methodinfo) * c->methodscount;
2523 /* load attribute structures */
2524 if (!check_classbuffer_size(cb, 2))
2525 goto return_exception;
2527 if (!load_attributes(cb, suck_u2(cb)))
2528 goto return_exception;
2531 /* Pre java 1.5 version don't check this. This implementation is like
2532 java 1.5 do it: for class file version 45.3 we don't check it, older
2533 versions are checked.
2535 if ((ma == 45 && mi > 3) || ma > 45) {
2536 /* check if all data has been read */
2537 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2539 if (classdata_left > 0) {
2541 new_classformaterror(c, "Extra bytes at the end of class file");
2542 goto return_exception;
2547 /* release dump area */
2548 dump_release(dumpsize);
2551 log_message_class("Loading done class: ", c);
2557 /* release dump area */
2558 dump_release(dumpsize);
2560 /* an exception has been thrown */
2567 /* load_newly_created_array ****************************************************
2569 Load a newly created array class.
2572 This is an internal function. Do not use it unless you know exactly
2575 Use one of the load_class_... functions for general array class loading.
2577 *******************************************************************************/
2579 bool load_newly_created_array(classinfo *c,java_objectheader *loader)
2581 classinfo *comp = NULL;
2583 methoddesc *clonedesc;
2584 constant_classref *classrefs;
2586 java_objectheader *definingloader = NULL;
2588 #ifdef LOADER_VERBOSE
2589 char logtext[MAXLOGTEXT];
2590 LOADER_INDENT(logtext);
2591 strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2592 sprintf(logtext+strlen(logtext),") loader=%p",loader);
2596 /* Check array class name */
2597 namelen = c->name->blength;
2598 if (namelen < 2 || c->name->text[0] != '[') {
2599 *exceptionptr = new_internalerror("Invalid array class name");
2603 /* Check the component type */
2604 switch (c->name->text[1]) {
2606 /* c is an array of arrays. We have to create the component class. */
2608 if (!load_class_from_classloader(utf_new_intern(c->name->text + 1,
2617 LOADER_ASSERT(comp->loaded);
2621 definingloader = comp->classloader;
2625 /* c is an array of objects. */
2626 if (namelen < 4 || c->name->text[namelen - 1] != ';') {
2627 *exceptionptr = new_internalerror("Invalid array class name");
2632 if (!load_class_from_classloader(utf_new_intern(c->name->text + 2,
2641 LOADER_ASSERT(comp->loaded);
2645 definingloader = comp->classloader;
2649 LOADER_ASSERT(class_java_lang_Object);
2650 LOADER_ASSERT(class_java_lang_Cloneable);
2651 LOADER_ASSERT(class_java_io_Serializable);
2653 /* Setup the array class */
2654 c->super.cls = class_java_lang_Object;
2655 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2657 c->interfacescount = 2;
2658 c->interfaces = MNEW(classref_or_classinfo, 2);
2663 tc = class_java_lang_Cloneable;
2664 LOADER_ASSERT(tc->loaded);
2665 list_addfirst(&unlinkedclasses, tc);
2666 c->interfaces[0].cls = tc;
2668 tc = class_java_io_Serializable;
2669 LOADER_ASSERT(tc->loaded);
2670 list_addfirst(&unlinkedclasses, tc);
2671 c->interfaces[1].cls = tc;
2674 c->interfaces[0].cls = class_java_lang_Cloneable;
2675 c->interfaces[1].cls = class_java_io_Serializable;
2678 c->methodscount = 1;
2679 c->methods = MNEW(methodinfo, c->methodscount);
2681 classrefs = MNEW(constant_classref,1);
2682 CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
2684 clonedesc = NEW(methoddesc);
2685 clonedesc->returntype.type = TYPE_ADDRESS;
2686 clonedesc->returntype.classref = classrefs;
2687 clonedesc->returntype.arraydim = 0;
2688 clonedesc->paramcount = 0;
2689 clonedesc->paramslots = 0;
2692 MSET(clone, 0, methodinfo, 1);
2693 clone->flags = ACC_PUBLIC;
2694 clone->name = utf_new_char("clone");
2695 clone->descriptor = utf_void__java_lang_Object;
2696 clone->parseddesc = clonedesc;
2698 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2699 clone->monoPoly = MONO;
2701 /* XXX: field: length? */
2703 /* array classes are not loaded from class files */
2705 c->parseddescs = (u1*) clonedesc;
2706 c->parseddescsize = sizeof(methodinfo);
2707 c->classrefs = classrefs;
2708 c->classrefcount = 1;
2709 c->classloader = definingloader;
2711 /* insert class into the loaded class cache */
2712 if (!classcache_store(loader,c))
2719 /************************* Function: class_findfield ***************************
2721 Searches a 'classinfo' structure for a field having the given name and
2724 *******************************************************************************/
2726 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2730 for (i = 0; i < c->fieldscount; i++) {
2731 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2732 return &(c->fields[i]);
2735 panic("Can not find field given in CONSTANT_Fieldref");
2737 /* keep compiler happy */
2742 /****************** Function: class_resolvefield_int ***************************
2744 This is an internally used helper function. Do not use this directly.
2746 Tries to resolve a field having the given name and type.
2747 If the field cannot be resolved, NULL is returned.
2749 *******************************************************************************/
2751 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2756 /* search for field in class c */
2758 for (i = 0; i < c->fieldscount; i++) {
2759 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2760 return &(c->fields[i]);
2764 /* try superinterfaces recursively */
2766 for (i = 0; i < c->interfacescount; i++) {
2767 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2772 /* try superclass */
2775 return class_resolvefield_int(c->super.cls, name, desc);
2783 /********************* Function: class_resolvefield ***************************
2785 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2787 If the field cannot be resolved the return value is NULL. If EXCEPT is
2788 true *exceptionptr is set, too.
2790 *******************************************************************************/
2792 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2793 classinfo *referer, bool except)
2797 /* XXX resolve class c */
2798 /* XXX check access from REFERER to C */
2800 fi = class_resolvefield_int(c, name, desc);
2805 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2811 /* XXX check access rights */
2817 /* class_findmethod ************************************************************
2819 Searches a 'classinfo' structure for a method having the given name
2820 and descriptor. If descriptor is NULL, it is ignored.
2822 *******************************************************************************/
2824 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2829 for (i = 0; i < c->methodscount; i++) {
2830 m = &(c->methods[i]);
2832 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2840 /*********************** Function: class_fetchmethod **************************
2842 like class_findmethod, but aborts with an error if the method is not found
2844 *******************************************************************************/
2846 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2850 mi = class_findmethod(c, name, desc);
2853 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2854 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2855 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2856 panic("Method not found");
2863 /************************* Function: class_findmethod_approx ******************
2865 like class_findmethod but ignores the return value when comparing the
2868 *******************************************************************************/
2870 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2874 for (i = 0; i < c->methodscount; i++) {
2875 if (c->methods[i].name == name) {
2876 utf *meth_descr = c->methods[i].descriptor;
2880 return &(c->methods[i]);
2882 if (desc->blength <= meth_descr->blength) {
2883 /* current position in utf text */
2884 char *desc_utf_ptr = desc->text;
2885 char *meth_utf_ptr = meth_descr->text;
2886 /* points behind utf strings */
2887 char *desc_end = utf_end(desc);
2888 char *meth_end = utf_end(meth_descr);
2891 /* compare argument types */
2892 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2894 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2895 break; /* no match */
2898 return &(c->methods[i]); /* all parameter types equal */
2908 /***************** Function: class_resolvemethod_approx ***********************
2910 Searches a class and every super class for a method (without paying
2911 attention to the return value)
2913 *******************************************************************************/
2915 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2918 /* search for method (ignore returntype) */
2919 methodinfo *m = class_findmethod_approx(c, name, desc);
2922 /* search superclass */
2930 /* class_resolvemethod *********************************************************
2932 Searches a class and it's super classes for a method.
2934 *******************************************************************************/
2936 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2941 m = class_findmethod(c, name, desc);
2953 /* class_resolveinterfacemethod_intern *****************************************
2955 Internally used helper function. Do not use this directly.
2957 *******************************************************************************/
2959 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2960 utf *name, utf *desc)
2965 m = class_findmethod(c, name, desc);
2970 /* try the superinterfaces */
2972 for (i = 0; i < c->interfacescount; i++) {
2973 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2982 /* class_resolveinterfacemethod ************************************************
2984 Resolves a reference from REFERER to a method with NAME and DESC in
2987 If the method cannot be resolved the return value is NULL. If
2988 EXCEPT is true *exceptionptr is set, too.
2990 *******************************************************************************/
2992 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2993 classinfo *referer, bool except)
2997 /* XXX resolve class c */
2998 /* XXX check access from REFERER to C */
3000 if (!(c->flags & ACC_INTERFACE)) {
3003 new_exception(string_java_lang_IncompatibleClassChangeError);
3008 mi = class_resolveinterfacemethod_intern(c, name, desc);
3013 /* try class java.lang.Object */
3014 LOADER_ASSERT(class_java_lang_Object);
3015 mi = class_findmethod(class_java_lang_Object, name, desc);
3022 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3028 /* class_resolveclassmethod ****************************************************
3030 Resolves a reference from REFERER to a method with NAME and DESC in
3033 If the method cannot be resolved the return value is NULL. If EXCEPT is
3034 true *exceptionptr is set, too.
3036 *******************************************************************************/
3038 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3039 classinfo *referer, bool except)
3047 /* XXX resolve class c */
3048 /* XXX check access from REFERER to C */
3050 /* if (c->flags & ACC_INTERFACE) { */
3052 /* *exceptionptr = */
3053 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3057 /* try class c and its superclasses */
3062 mi = class_findmethod(cls, name, desc);
3067 cls = cls->super.cls;
3070 /* try the superinterfaces */
3072 for (i = 0; i < c->interfacescount; i++) {
3073 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
3080 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
3081 utf_strlen(desc) + strlen("0");
3083 msg = MNEW(char, msglen);
3085 utf_sprint(msg, c->name);
3087 utf_sprint(msg + strlen(msg), name);
3088 utf_sprint(msg + strlen(msg), desc);
3091 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3093 MFREE(msg, char, msglen);
3099 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3101 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3106 /* XXX check access rights */
3112 /************************* Function: class_issubclass **************************
3114 Checks if sub is a descendant of super.
3116 *******************************************************************************/
3118 bool class_issubclass(classinfo *sub, classinfo *super)
3121 if (!sub) return false;
3122 if (sub == super) return true;
3123 sub = sub->super.cls;
3128 void class_showconstanti(classinfo *c, int ii)
3134 printf ("#%d: ", (int) i);
3136 switch (c->cptags [i]) {
3137 case CONSTANT_Class:
3138 printf("Classreference -> ");
3139 utf_display(((constant_classref*)e)->name);
3142 case CONSTANT_Fieldref:
3143 printf("Fieldref -> "); goto displayFMIi;
3144 case CONSTANT_Methodref:
3145 printf("Methodref -> "); goto displayFMIi;
3146 case CONSTANT_InterfaceMethodref:
3147 printf("InterfaceMethod -> "); goto displayFMIi;
3150 constant_FMIref *fmi = e;
3151 utf_display(fmi->classref->name);
3153 utf_display(fmi->name);
3155 utf_display(fmi->descriptor);
3159 case CONSTANT_String:
3160 printf("String -> ");
3163 case CONSTANT_Integer:
3164 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3166 case CONSTANT_Float:
3167 printf("Float -> %f", ((constant_float*)e)->value);
3169 case CONSTANT_Double:
3170 printf("Double -> %f", ((constant_double*)e)->value);
3174 u8 v = ((constant_long*)e)->value;
3176 printf("Long -> %ld", (long int) v);
3178 printf("Long -> HI: %ld, LO: %ld\n",
3179 (long int) v.high, (long int) v.low);
3183 case CONSTANT_NameAndType:
3185 constant_nameandtype *cnt = e;
3186 printf("NameAndType: ");
3187 utf_display(cnt->name);
3189 utf_display(cnt->descriptor);
3197 panic("Invalid type of ConstantPool-Entry");
3204 void class_showconstantpool (classinfo *c)
3209 printf ("---- dump of constant pool ----\n");
3211 for (i=0; i<c->cpcount; i++) {
3212 printf ("#%d: ", (int) i);
3214 e = c -> cpinfos [i];
3217 switch (c -> cptags [i]) {
3218 case CONSTANT_Class:
3219 printf ("Classreference -> ");
3220 utf_display ( ((constant_classref*)e) -> name );
3223 case CONSTANT_Fieldref:
3224 printf ("Fieldref -> "); goto displayFMI;
3225 case CONSTANT_Methodref:
3226 printf ("Methodref -> "); goto displayFMI;
3227 case CONSTANT_InterfaceMethodref:
3228 printf ("InterfaceMethod -> "); goto displayFMI;
3231 constant_FMIref *fmi = e;
3232 utf_display ( fmi->classref->name );
3234 utf_display ( fmi->name);
3236 utf_display ( fmi->descriptor );
3240 case CONSTANT_String:
3241 printf ("String -> ");
3244 case CONSTANT_Integer:
3245 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3247 case CONSTANT_Float:
3248 printf ("Float -> %f", ((constant_float*)e) -> value);
3250 case CONSTANT_Double:
3251 printf ("Double -> %f", ((constant_double*)e) -> value);
3255 u8 v = ((constant_long*)e) -> value;
3257 printf ("Long -> %ld", (long int) v);
3259 printf ("Long -> HI: %ld, LO: %ld\n",
3260 (long int) v.high, (long int) v.low);
3264 case CONSTANT_NameAndType:
3266 constant_nameandtype *cnt = e;
3267 printf ("NameAndType: ");
3268 utf_display (cnt->name);
3270 utf_display (cnt->descriptor);
3274 printf ("Utf8 -> ");
3278 panic ("Invalid type of ConstantPool-Entry");
3288 /********** Function: class_showmethods (debugging only) *************/
3290 void class_showmethods (classinfo *c)
3294 printf ("--------- Fields and Methods ----------------\n");
3295 printf ("Flags: "); printflags (c->flags); printf ("\n");
3297 printf ("This: "); utf_display (c->name); printf ("\n");
3299 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3301 printf ("Index: %d\n", c->index);
3303 printf ("interfaces:\n");
3304 for (i=0; i < c-> interfacescount; i++) {
3306 utf_display (c -> interfaces[i].cls -> name);
3307 printf (" (%d)\n", c->interfaces[i].cls -> index);
3310 printf ("fields:\n");
3311 for (i=0; i < c -> fieldscount; i++) {
3312 field_display (&(c -> fields[i]));
3315 printf ("methods:\n");
3316 for (i=0; i < c -> methodscount; i++) {
3317 methodinfo *m = &(c->methods[i]);
3318 if ( !(m->flags & ACC_STATIC))
3319 printf ("vftblindex: %d ", m->vftblindex);
3321 method_display ( m );
3325 printf ("Virtual function table:\n");
3326 for (i=0; i<c->vftbl->vftbllength; i++) {
3327 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3333 /* loader_close ****************************************************************
3335 Frees all resources.
3337 *******************************************************************************/
3339 void loader_close(void)
3346 * These are local overrides for various environment variables in Emacs.
3347 * Please do not remove this and leave it at the end of the file, where
3348 * Emacs will automagically detect them.
3349 * ---------------------------------------------------------------------
3352 * indent-tabs-mode: t