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 3513 2005-10-28 11:30:19Z 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_internalerror("Incompatible float-format");
367 /* XXX should we exit in such a case? */
368 throw_exception_exit();
375 /* get double from classfile data */
376 static double suck_double(classbuffer *cb)
384 #if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
386 * On little endian ARM processors when using FPA, word order
387 * of doubles is still big endian. So take that into account
388 * here. When using VFP, word order of doubles follows byte
389 * order. (michi 2005/07/24)
391 for (i = 0; i < 4; i++)
392 buffer[3 - i] = suck_u1(cb);
393 for (i = 0; i < 4; i++)
394 buffer[7 - i] = suck_u1(cb);
396 for (i = 0; i < 8; i++)
397 buffer[7 - i] = suck_u1(cb);
398 #endif /* defined(__ARM__) && ... */
400 memcpy((u1*) (&d), buffer, 8);
402 suck_nbytes((u1*) (&d), cb, 8);
405 if (sizeof(double) != 8) {
406 *exceptionptr = new_internalerror("Incompatible double-format");
408 /* XXX should we exit in such a case? */
409 throw_exception_exit();
416 /************************** function suck_init *********************************
418 called once at startup, sets the searchpath for the classfiles
420 *******************************************************************************/
422 void suck_init(char *classpath)
430 classpath_info *lastcpi;
434 /* search for last classpath entry (only if there already some) */
436 if ((lastcpi = classpath_entries)) {
437 while (lastcpi->next)
438 lastcpi = lastcpi->next;
441 for (start = classpath; (*start) != '\0';) {
443 /* search for ':' delimiter to get the end of the current entry */
444 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
448 filenamelen = end - start;
450 if (filenamelen > 3) {
451 if (strncasecmp(end - 3, "zip", 3) == 0 ||
452 strncasecmp(end - 3, "jar", 3) == 0) {
457 /* save classpath entries as absolute pathnames */
462 if (*start != '/') { /* XXX fix me for win32 */
464 cwdlen = strlen(cwd) + strlen("/");
467 /* allocate memory for filename and fill it */
469 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
473 strcpy(filename, cwd);
474 strcat(filename, "/");
475 strncat(filename, start, filenamelen);
477 /* add cwd length to file length */
478 filenamelen += cwdlen;
481 strncpy(filename, start, filenamelen);
482 filename[filenamelen] = '\0';
488 #if defined(USE_ZLIB)
489 unzFile uf = unzOpen(filename);
492 cpi = NEW(classpath_info);
493 cpi->type = CLASSPATH_ARCHIVE;
496 cpi->path = filename;
497 cpi->pathlen = filenamelen;
499 /* SUN compatible -verbose:class output */
501 if (opt_verboseclass)
502 printf("[Opened %s]\n", filename);
506 throw_cacao_exception_exit(string_java_lang_InternalError,
507 "zip/jar files not supported");
511 cpi = NEW(classpath_info);
512 cpi->type = CLASSPATH_PATH;
515 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
516 filename[filenamelen] = '/';
517 filename[filenamelen + 1] = '\0';
521 cpi->path = filename;
522 cpi->pathlen = filenamelen;
525 /* attach current classpath entry */
528 if (!classpath_entries)
529 classpath_entries = cpi;
537 /* goto next classpath entry, skip ':' delimiter */
549 /* loader_load_all_classes *****************************************************
551 Loads all classes specified in the BOOTCLASSPATH.
553 *******************************************************************************/
555 void loader_load_all_classes(void)
560 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
561 #if defined(USE_ZLIB)
562 if (cpi->type == CLASSPATH_ARCHIVE) {
566 s = (unz_s *) cpi->uf;
567 ce = s->cacao_dir_list;
570 /* skip all entries in META-INF and .properties, .png files */
572 if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
573 !strstr(ce->name->text, ".properties") &&
574 !strstr(ce->name->text, ".png"))
575 c = load_class_bootstrap(ce->name);
582 #if defined(USE_ZLIB)
589 /* suck_start ******************************************************************
591 Returns true if classbuffer is already loaded or a file for the
592 specified class has succussfully been read in. All directories of
593 the searchpath are used to find the classfile (<classname>.class).
594 Returns false if no classfile is found and writes an error message.
596 *******************************************************************************/
598 classbuffer *suck_start(classinfo *c)
610 /* initialize return value */
615 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
616 filename = MNEW(char, filenamelen);
618 utf_sprint(filename, c->name);
619 strcat(filename, ".class");
621 /* walk through all classpath entries */
623 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
624 #if defined(USE_ZLIB)
625 if (cpi->type == CLASSPATH_ARCHIVE) {
627 #if defined(USE_THREADS)
628 /* enter a monitor on zip/jar archives */
630 builtin_monitorenter((java_objectheader *) cpi);
633 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
634 unz_file_info file_info;
636 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
637 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
638 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
639 cb = NEW(classbuffer);
641 cb->size = file_info.uncompressed_size;
642 cb->data = MNEW(u1, cb->size);
643 cb->pos = cb->data - 1;
644 cb->path = cpi->path;
646 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
648 if (len != cb->size) {
650 log_text("Error while unzipping");
657 log_text("Error while opening file in archive");
661 log_text("Error while retrieving fileinfo");
664 unzCloseCurrentFile(cpi->uf);
666 #if defined(USE_THREADS)
667 /* leave the monitor */
669 builtin_monitorexit((java_objectheader *) cpi);
673 #endif /* defined(USE_ZLIB) */
675 path = MNEW(char, cpi->pathlen + filenamelen);
676 strcpy(path, cpi->path);
677 strcat(path, filename);
679 classfile = fopen(path, "r");
681 if (classfile) { /* file exists */
682 if (!stat(path, &buffer)) { /* read classfile data */
683 cb = NEW(classbuffer);
685 cb->size = buffer.st_size;
686 cb->data = MNEW(u1, cb->size);
687 cb->pos = cb->data - 1;
688 cb->path = cpi->path;
690 /* read class data */
691 len = fread(cb->data, 1, cb->size, classfile);
693 if (len != buffer.st_size) {
695 /* if (ferror(classfile)) { */
704 MFREE(path, char, cpi->pathlen + filenamelen);
705 #if defined(USE_ZLIB)
712 dolog("Warning: Can not open class file '%s'", filename);
714 if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
722 MFREE(filename, char, filenamelen);
728 /************************** function suck_stop *********************************
730 frees memory for buffer with classfile data.
731 Caution: this function may only be called if buffer has been allocated
732 by suck_start with reading a file
734 *******************************************************************************/
736 void suck_stop(classbuffer *cb)
740 MFREE(cb->data, u1, cb->size);
741 FREE(cb, classbuffer);
745 /******************************************************************************/
746 /******************* Some support functions ***********************************/
747 /******************************************************************************/
749 void fprintflags (FILE *fp, u2 f)
751 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
752 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
753 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
754 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
755 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
756 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
757 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
758 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
759 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
760 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
761 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
765 /********** internal function: printflags (only for debugging) ***************/
767 void printflags(u2 f)
769 fprintflags(stdout,f);
773 /********************** Function: skipattributebody ****************************
775 skips an attribute after the 16 bit reference to attribute_name has already
778 *******************************************************************************/
780 static bool skipattributebody(classbuffer *cb)
784 if (!check_classbuffer_size(cb, 4))
789 if (!check_classbuffer_size(cb, len))
792 skip_nbytes(cb, len);
798 /************************* Function: skipattributes ****************************
800 skips num attribute structures
802 *******************************************************************************/
804 static bool skipattributes(classbuffer *cb, u4 num)
809 for (i = 0; i < num; i++) {
810 if (!check_classbuffer_size(cb, 2 + 4))
816 if (!check_classbuffer_size(cb, len))
819 skip_nbytes(cb, len);
826 /* load_constantpool ***********************************************************
828 Loads the constantpool of a class, the entries are transformed into
829 a simpler format by resolving references (a detailed overview of
830 the compact structures can be found in global.h).
832 *******************************************************************************/
834 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
837 /* The following structures are used to save information which cannot be
838 processed during the first pass. After the complete constantpool has
839 been traversed the references can be resolved.
840 (only in specific order) */
842 /* CONSTANT_Class entries */
843 typedef struct forward_class {
844 struct forward_class *next;
849 /* CONSTANT_String */
850 typedef struct forward_string {
851 struct forward_string *next;
856 /* CONSTANT_NameAndType */
857 typedef struct forward_nameandtype {
858 struct forward_nameandtype *next;
862 } forward_nameandtype;
864 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
865 typedef struct forward_fieldmethint {
866 struct forward_fieldmethint *next;
870 u2 nameandtype_index;
871 } forward_fieldmethint;
877 forward_class *forward_classes = NULL;
878 forward_string *forward_strings = NULL;
879 forward_nameandtype *forward_nameandtypes = NULL;
880 forward_fieldmethint *forward_fieldmethints = NULL;
884 forward_nameandtype *nfn;
885 forward_fieldmethint *nff;
893 /* number of entries in the constant_pool table plus one */
894 if (!check_classbuffer_size(cb, 2))
897 cpcount = c->cpcount = suck_u2(cb);
899 /* allocate memory */
900 cptags = c->cptags = MNEW(u1, cpcount);
901 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
904 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
908 #if defined(STATISTICS)
910 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
913 /* initialize constantpool */
914 for (idx = 0; idx < cpcount; idx++) {
915 cptags[idx] = CONSTANT_UNUSED;
920 /******* first pass *******/
921 /* entries which cannot be resolved now are written into
922 temporary structures and traversed again later */
925 while (idx < cpcount) {
928 /* get constant type */
929 if (!check_classbuffer_size(cb, 1))
936 nfc = DNEW(forward_class);
938 nfc->next = forward_classes;
939 forward_classes = nfc;
941 nfc->thisindex = idx;
942 /* reference to CONSTANT_NameAndType */
943 if (!check_classbuffer_size(cb, 2))
946 nfc->name_index = suck_u2(cb);
951 case CONSTANT_String:
952 nfs = DNEW(forward_string);
954 nfs->next = forward_strings;
955 forward_strings = nfs;
957 nfs->thisindex = idx;
959 /* reference to CONSTANT_Utf8_info with string characters */
960 if (!check_classbuffer_size(cb, 2))
963 nfs->string_index = suck_u2(cb);
968 case CONSTANT_NameAndType:
969 nfn = DNEW(forward_nameandtype);
971 nfn->next = forward_nameandtypes;
972 forward_nameandtypes = nfn;
974 nfn->thisindex = idx;
976 if (!check_classbuffer_size(cb, 2 + 2))
979 /* reference to CONSTANT_Utf8_info containing simple name */
980 nfn->name_index = suck_u2(cb);
982 /* reference to CONSTANT_Utf8_info containing field or method
984 nfn->sig_index = suck_u2(cb);
989 case CONSTANT_Fieldref:
990 case CONSTANT_Methodref:
991 case CONSTANT_InterfaceMethodref:
992 nff = DNEW(forward_fieldmethint);
994 nff->next = forward_fieldmethints;
995 forward_fieldmethints = nff;
997 nff->thisindex = idx;
1001 if (!check_classbuffer_size(cb, 2 + 2))
1004 /* class or interface type that contains the declaration of the
1006 nff->class_index = suck_u2(cb);
1008 /* name and descriptor of the field or method */
1009 nff->nameandtype_index = suck_u2(cb);
1014 case CONSTANT_Integer: {
1015 constant_integer *ci = NEW(constant_integer);
1017 #if defined(STATISTICS)
1019 count_const_pool_len += sizeof(constant_integer);
1022 if (!check_classbuffer_size(cb, 4))
1025 ci->value = suck_s4(cb);
1026 cptags[idx] = CONSTANT_Integer;
1033 case CONSTANT_Float: {
1034 constant_float *cf = NEW(constant_float);
1036 #if defined(STATISTICS)
1038 count_const_pool_len += sizeof(constant_float);
1041 if (!check_classbuffer_size(cb, 4))
1044 cf->value = suck_float(cb);
1045 cptags[idx] = CONSTANT_Float;
1052 case CONSTANT_Long: {
1053 constant_long *cl = NEW(constant_long);
1055 #if defined(STATISTICS)
1057 count_const_pool_len += sizeof(constant_long);
1060 if (!check_classbuffer_size(cb, 8))
1063 cl->value = suck_s8(cb);
1064 cptags[idx] = CONSTANT_Long;
1067 if (idx > cpcount) {
1069 new_classformaterror(c, "Invalid constant pool entry");
1075 case CONSTANT_Double: {
1076 constant_double *cd = NEW(constant_double);
1078 #if defined(STATISTICS)
1080 count_const_pool_len += sizeof(constant_double);
1083 if (!check_classbuffer_size(cb, 8))
1086 cd->value = suck_double(cb);
1087 cptags[idx] = CONSTANT_Double;
1090 if (idx > cpcount) {
1092 new_classformaterror(c, "Invalid constant pool entry");
1098 case CONSTANT_Utf8: {
1101 /* number of bytes in the bytes array (not string-length) */
1102 if (!check_classbuffer_size(cb, 2))
1105 length = suck_u2(cb);
1106 cptags[idx] = CONSTANT_Utf8;
1108 /* validate the string */
1109 if (!check_classbuffer_size(cb, length))
1113 !is_valid_utf((char *) (cb->pos + 1),
1114 (char *) (cb->pos + 1 + length))) {
1115 *exceptionptr = new_classformaterror(c,"Invalid UTF-8 string");
1118 /* insert utf-string into the utf-symboltable */
1119 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1121 /* skip bytes of the string (buffer size check above) */
1122 skip_nbytes(cb, length);
1129 new_classformaterror(c, "Illegal constant pool type");
1135 /* resolve entries in temporary structures */
1137 while (forward_classes) {
1139 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1143 if (opt_verify && !is_valid_name_utf(name)) {
1145 new_classformaterror(c, "Class reference with invalid name");
1149 /* add all class references to the descriptor_pool */
1151 if (!descriptor_pool_add_class(descpool, name))
1154 cptags[forward_classes->thisindex] = CONSTANT_Class;
1159 if (!(tc = load_class_bootstrap(name)))
1162 /* link the class later, because we cannot link the class currently
1164 list_addfirst(&unlinkedclasses, tc);
1167 /* the classref is created later */
1168 cpinfos[forward_classes->thisindex] = name;
1170 nfc = forward_classes;
1171 forward_classes = forward_classes->next;
1174 while (forward_strings) {
1176 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1180 /* resolve utf-string */
1181 cptags[forward_strings->thisindex] = CONSTANT_String;
1182 cpinfos[forward_strings->thisindex] = text;
1184 nfs = forward_strings;
1185 forward_strings = forward_strings->next;
1188 while (forward_nameandtypes) {
1189 constant_nameandtype *cn = NEW(constant_nameandtype);
1191 #if defined(STATISTICS)
1193 count_const_pool_len += sizeof(constant_nameandtype);
1196 /* resolve simple name and descriptor */
1197 cn->name = class_getconstant(c,
1198 forward_nameandtypes->name_index,
1203 cn->descriptor = class_getconstant(c,
1204 forward_nameandtypes->sig_index,
1206 if (!cn->descriptor)
1211 if (!is_valid_name_utf(cn->name)) {
1213 new_classformaterror(c,
1214 "Illegal Field name \"%s\"",
1220 /* disallow referencing <clinit> among others */
1221 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1223 new_classformaterror(c,"Illegal reference to special method");
1228 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1229 cpinfos[forward_nameandtypes->thisindex] = cn;
1231 nfn = forward_nameandtypes;
1232 forward_nameandtypes = forward_nameandtypes->next;
1235 while (forward_fieldmethints) {
1236 constant_nameandtype *nat;
1237 constant_FMIref *fmi = NEW(constant_FMIref);
1239 #if defined(STATISTICS)
1241 count_const_pool_len += sizeof(constant_FMIref);
1243 /* resolve simple name and descriptor */
1245 nat = class_getconstant(c,
1246 forward_fieldmethints->nameandtype_index,
1247 CONSTANT_NameAndType);
1251 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
1253 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
1256 /* the classref is created later */
1258 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
1259 fmi->name = nat->name;
1260 fmi->descriptor = nat->descriptor;
1262 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1263 cpinfos[forward_fieldmethints->thisindex] = fmi;
1265 nff = forward_fieldmethints;
1266 forward_fieldmethints = forward_fieldmethints->next;
1269 /* everything was ok */
1275 /* load_field ******************************************************************
1277 Load everything about a class field from the class file and fill a
1278 'fieldinfo' structure. For static fields, space in the data segment
1281 *******************************************************************************/
1283 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1285 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
1290 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1295 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1298 f->flags = suck_u2(cb);
1300 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1305 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1309 f->parseddesc = NULL;
1311 if (!descriptor_pool_add(descpool, u, NULL))
1314 /* descriptor_pool_add accepts method descriptors, so we have to check */
1315 /* against them here before the call of desc_to_type below. */
1316 if (u->text[0] == '(') {
1317 *exceptionptr = new_classformaterror(c,"Method descriptor used for field");
1323 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1324 *exceptionptr = new_classformaterror(c,
1325 "Illegal Field name \"%s\"",
1330 /* check flag consistency */
1331 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1333 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1334 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1336 new_classformaterror(c,
1337 "Illegal field modifiers: 0x%X",
1342 if (c->flags & ACC_INTERFACE) {
1343 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1344 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1345 f->flags & ACC_TRANSIENT) {
1347 new_classformaterror(c,
1348 "Illegal field modifiers: 0x%X",
1355 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1356 f->offset = 0; /* offset from start of object */
1361 case TYPE_INT: f->value.i = 0; break;
1362 case TYPE_FLOAT: f->value.f = 0.0; break;
1363 case TYPE_DOUBLE: f->value.d = 0.0; break;
1364 case TYPE_ADDRESS: f->value.a = NULL; break;
1367 f->value.l = 0; break;
1369 f->value.l.low = 0; f->value.l.high = 0; break;
1373 /* read attributes */
1374 if (!check_classbuffer_size(cb, 2))
1377 attrnum = suck_u2(cb);
1378 for (i = 0; i < attrnum; i++) {
1379 if (!check_classbuffer_size(cb, 2))
1382 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1385 if (u == utf_ConstantValue) {
1386 if (!check_classbuffer_size(cb, 4 + 2))
1389 /* check attribute length */
1390 if (suck_u4(cb) != 2) {
1392 new_classformaterror(c, "Wrong size for VALUE attribute");
1396 /* constant value attribute */
1397 if (pindex != field_load_NOVALUE) {
1399 new_classformaterror(c,
1400 "Multiple ConstantValue attributes");
1404 /* index of value in constantpool */
1405 pindex = suck_u2(cb);
1407 /* initialize field with value from constantpool */
1410 constant_integer *ci;
1412 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1415 f->value.i = ci->value;
1422 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1425 f->value.l = cl->value;
1432 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1435 f->value.f = cf->value;
1440 constant_double *cd;
1442 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1445 f->value.d = cd->value;
1450 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1453 /* create javastring from compressed utf8-string */
1454 f->value.a = literalstring_new(u);
1458 log_text("Invalid Constant - Type");
1462 /* unknown attribute */
1463 if (!skipattributebody(cb))
1468 /* everything was ok */
1474 /* load_method *****************************************************************
1476 Loads a method from the class file and fills an existing
1477 'methodinfo' structure. For native methods, the function pointer
1478 field is set to the real function pointer, for JavaVM methods a
1479 pointer to the compiler is used preliminarily.
1481 *******************************************************************************/
1483 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1494 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1495 initObjectLock(&m->header);
1500 count_all_methods++;
1503 m->thrownexceptionscount = 0;
1504 m->linenumbercount = 0;
1507 m->nativelyoverloaded = false;
1509 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1512 m->flags = suck_u2(cb);
1514 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1519 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1523 m->parseddesc = NULL;
1525 if (!descriptor_pool_add(descpool, u, &argcount))
1529 if (!is_valid_name_utf(m->name)) {
1530 *exceptionptr = new_classformaterror(c,"Method with invalid name");
1534 if (m->name->text[0] == '<' &&
1535 m->name != utf_init && m->name != utf_clinit) {
1536 *exceptionptr = new_classformaterror(c,"Method with invalid special name");
1541 if (!(m->flags & ACC_STATIC))
1542 argcount++; /* count the 'this' argument */
1545 if (argcount > 255) {
1547 new_classformaterror(c, "Too many arguments in signature");
1551 /* check flag consistency */
1552 if (m->name != utf_clinit) {
1553 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1555 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1557 new_classformaterror(c,
1558 "Illegal method modifiers: 0x%X",
1563 if (m->flags & ACC_ABSTRACT) {
1564 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1565 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1567 new_classformaterror(c,
1568 "Illegal method modifiers: 0x%X",
1574 if (c->flags & ACC_INTERFACE) {
1575 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1577 new_classformaterror(c,
1578 "Illegal method modifiers: 0x%X",
1584 if (m->name == utf_init) {
1585 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1586 ACC_NATIVE | ACC_ABSTRACT)) {
1587 *exceptionptr = new_classformaterror(c,
1588 "Instance initialization method has invalid flags set");
1596 m->basicblockcount = 0;
1597 m->basicblocks = NULL;
1598 m->basicblockindex = NULL;
1599 m->instructioncount = 0;
1600 m->instructions = NULL;
1603 m->exceptiontable = NULL;
1604 m->stubroutine = NULL;
1606 m->entrypoint = NULL;
1607 m->methodUsed = NOTUSED;
1610 m->subRedefsUsed = 0;
1614 if (!check_classbuffer_size(cb, 2))
1617 attrnum = suck_u2(cb);
1618 for (i = 0; i < attrnum; i++) {
1621 if (!check_classbuffer_size(cb, 2))
1624 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1627 if (aname == utf_Code) {
1628 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1630 new_classformaterror(c,
1631 "Code attribute in native or abstract methods");
1638 new_classformaterror(c, "Multiple Code attributes");
1643 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1647 m->maxstack = suck_u2(cb);
1648 m->maxlocals = suck_u2(cb);
1650 if (m->maxlocals < argcount) {
1652 new_classformaterror(c, "Arguments can't fit into locals");
1657 if (!check_classbuffer_size(cb, 4))
1660 m->jcodelength = suck_u4(cb);
1662 if (m->jcodelength == 0) {
1664 new_classformaterror(c, "Code of a method has length 0");
1669 if (m->jcodelength > 65535) {
1671 new_classformaterror(c,
1672 "Code of a method longer than 65535 bytes");
1677 if (!check_classbuffer_size(cb, m->jcodelength))
1680 m->jcode = MNEW(u1, m->jcodelength);
1681 suck_nbytes(m->jcode, cb, m->jcodelength);
1683 if (!check_classbuffer_size(cb, 2))
1686 m->exceptiontablelength = suck_u2(cb);
1687 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1690 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1692 #if defined(STATISTICS)
1694 count_vmcode_len += m->jcodelength + 18;
1695 count_extable_len +=
1696 m->exceptiontablelength * sizeof(exceptiontable);
1700 for (j = 0; j < m->exceptiontablelength; j++) {
1702 m->exceptiontable[j].startpc = suck_u2(cb);
1703 m->exceptiontable[j].endpc = suck_u2(cb);
1704 m->exceptiontable[j].handlerpc = suck_u2(cb);
1708 m->exceptiontable[j].catchtype.any = NULL;
1711 /* the classref is created later */
1712 if (!(m->exceptiontable[j].catchtype.any =
1713 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1718 if (!check_classbuffer_size(cb, 2))
1721 codeattrnum = suck_u2(cb);
1723 for (; codeattrnum > 0; codeattrnum--) {
1726 if (!check_classbuffer_size(cb, 2))
1729 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1732 if (caname == utf_LineNumberTable) {
1735 if (!check_classbuffer_size(cb, 4 + 2))
1739 m->linenumbercount = suck_u2(cb);
1741 if (!check_classbuffer_size(cb,
1742 (2 + 2) * m->linenumbercount))
1745 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1747 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1748 m->linenumbers[lncid].start_pc = suck_u2(cb);
1749 m->linenumbers[lncid].line_number = suck_u2(cb);
1753 if (!skipattributes(cb, codeattrnum))
1759 if (!skipattributebody(cb))
1764 } else if (aname == utf_Exceptions) {
1767 if (m->thrownexceptions) {
1769 new_classformaterror(c, "Multiple Exceptions attributes");
1773 if (!check_classbuffer_size(cb, 4 + 2))
1776 suck_u4(cb); /* length */
1777 m->thrownexceptionscount = suck_u2(cb);
1779 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1782 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1784 for (j = 0; j < m->thrownexceptionscount; j++) {
1785 /* the classref is created later */
1786 if (!((m->thrownexceptions)[j].any =
1787 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1792 if (!skipattributebody(cb))
1797 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1798 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1803 /* everything was ok */
1809 /* load_attribute **************************************************************
1811 Read attributes from classfile.
1813 *******************************************************************************/
1815 static bool load_attributes(classbuffer *cb, u4 num)
1823 for (i = 0; i < num; i++) {
1824 /* retrieve attribute name */
1825 if (!check_classbuffer_size(cb, 2))
1828 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1831 if (aname == utf_InnerClasses) {
1832 /* innerclasses attribute */
1833 if (c->innerclass) {
1835 new_classformaterror(c, "Multiple InnerClasses attributes");
1839 if (!check_classbuffer_size(cb, 4 + 2))
1842 /* skip attribute length */
1845 /* number of records */
1846 c->innerclasscount = suck_u2(cb);
1848 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1851 /* allocate memory for innerclass structure */
1852 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1854 for (j = 0; j < c->innerclasscount; j++) {
1855 /* The innerclass structure contains a class with an encoded
1856 name, its defining scope, its simple name and a bitmask of
1857 the access flags. If an inner class is not a member, its
1858 outer_class is NULL, if a class is anonymous, its name is
1861 innerclassinfo *info = c->innerclass + j;
1863 info->inner_class.ref =
1864 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1865 info->outer_class.ref =
1866 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1868 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1869 info->flags = suck_u2(cb);
1872 } else if (aname == utf_SourceFile) {
1873 if (!check_classbuffer_size(cb, 4 + 2))
1876 if (suck_u4(cb) != 2) {
1878 new_classformaterror(c, "Wrong size for VALUE attribute");
1882 if (c->sourcefile) {
1884 new_classformaterror(c, "Multiple SourceFile attributes");
1888 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1892 /* unknown attribute */
1893 if (!skipattributebody(cb))
1902 /* load_class_from_sysloader ***************************************************
1904 Load the class with the given name using the system class loader
1907 name.............the classname
1910 the loaded class, or
1911 NULL if an exception has been thrown
1913 *******************************************************************************/
1915 classinfo *load_class_from_sysloader(utf *name)
1918 java_objectheader *cl;
1921 #ifdef LOADER_VERBOSE
1922 char logtext[MAXLOGTEXT];
1923 LOADER_INDENT(logtext);
1924 sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
1925 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
1929 LOADER_ASSERT(class_java_lang_Object);
1930 LOADER_ASSERT(class_java_lang_ClassLoader);
1931 LOADER_ASSERT(class_java_lang_ClassLoader->linked);
1933 m = class_resolveclassmethod(class_java_lang_ClassLoader,
1934 utf_getSystemClassLoader,
1935 utf_void__java_lang_ClassLoader,
1936 class_java_lang_Object,
1942 cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1947 r = load_class_from_classloader(name, cl);
1953 /* load_class_from_classloader *************************************************
1955 Load the class with the given name using the given user-defined class loader.
1958 name.............the classname
1959 cl...............user-defined class loader
1962 the loaded class, or
1963 NULL if an exception has been thrown
1965 *******************************************************************************/
1967 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1971 #ifdef LOADER_VERBOSE
1972 char logtext[MAXLOGTEXT];
1973 LOADER_INDENT(logtext);
1974 strcat(logtext,"load_class_from_classloader(");
1975 utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
1976 if (!cl) strcat(logtext,"<bootstrap>");
1977 else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
1978 else strcat(logtext,"<unknown class>");
1979 strcat(logtext,")");
1983 LOADER_ASSERT(name);
1985 /* lookup if this class has already been loaded */
1987 r = classcache_lookup(cl, name);
1989 #ifdef LOADER_VERBOSE
1991 dolog(" cached -> %p",(void*)r);
1997 /* if other class loader than bootstrap, call it */
2005 namelen = name->blength;
2007 /* handle array classes */
2008 if (text[0] == '[') {
2014 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2015 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2016 *exceptionptr = new_noclassdeffounderror(name);
2020 u = utf_new(text + 2, namelen - 3);
2022 if (!(comp = load_class_from_classloader(u, cl)))
2025 /* create the array class */
2026 return class_array_of(comp, false);
2029 /* load the component class */
2031 u = utf_new(text + 1, namelen - 1);
2033 if (!(comp = load_class_from_classloader(u, cl)))
2036 /* create the array class */
2037 return class_array_of(comp, false);
2040 /* primitive array classes are loaded by the bootstrap loader */
2041 return load_class_bootstrap(name);
2045 LOADER_ASSERT(class_java_lang_Object);
2047 lc = class_resolveclassmethod(cl->vftbl->class,
2049 utf_java_lang_String__java_lang_Class,
2050 class_java_lang_Object,
2054 return false; /* exception */
2057 r = (classinfo *) asm_calljavafunction(lc,
2059 javastring_new_slash_to_dot(name),
2064 /* Store this class in the loaded class cache. If another
2065 class with the same (initloader,name) pair has been
2066 stored earlier it will be returned by classcache_store
2067 In this case classcache_store may not free the class
2068 because it has already been exposed to Java code which
2069 may have kept references to that class. */
2071 classinfo *c = classcache_store(cl,r,false);
2074 /* exception, free the loaded class */
2082 /* loadClass has thrown an exception */
2083 /* we must convert ClassNotFoundException into NoClassDefFoundException */
2084 /* XXX maybe we should have a flag that avoids this conversion */
2085 /* for calling load_class_from_classloader from Class.forName */
2086 /* Currently we do a double conversion in these cases */
2087 classnotfoundexception_to_noclassdeffounderror();
2090 /* SUN compatible -verbose:class output */
2092 if (opt_verboseclass && (r != NULL) && (r->classloader == cl)) {
2094 utf_display_classname(name);
2102 r = load_class_bootstrap(name);
2109 /* load_class_bootstrap ********************************************************
2111 Load the class with the given name using the bootstrap class loader.
2114 name.............the classname
2117 loaded classinfo, or
2118 NULL if an exception has been thrown
2121 load_class_bootstrap is synchronized. It can be treated as an
2124 *******************************************************************************/
2126 classinfo *load_class_bootstrap(utf *name)
2131 #ifdef LOADER_VERBOSE
2132 char logtext[MAXLOGTEXT];
2137 LOADER_ASSERT(name);
2140 /* lookup if this class has already been loaded */
2142 if ((r = classcache_lookup(NULL, name)))
2145 #ifdef LOADER_VERBOSE
2146 LOADER_INDENT(logtext);
2147 strcat(logtext,"load_class_bootstrap(");
2148 utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
2152 /* create the classinfo */
2154 c = class_create_classinfo(name);
2156 /* handle array classes */
2158 if (name->text[0] == '[') {
2159 c = load_newly_created_array(c, NULL);
2161 goto return_exception;
2162 LOADER_ASSERT(c->loaded);
2167 #if defined(STATISTICS)
2170 if (getcompilingtime)
2171 compilingtime_stop();
2174 loadingtime_start();
2177 /* load classdata, throw exception on error */
2179 if ((cb = suck_start(c)) == NULL) {
2180 /* this normally means, the classpath was not set properly */
2182 if (name == utf_java_lang_Object)
2183 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2184 "java/lang/Object");
2187 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2189 goto return_exception;
2192 /* load the class from the buffer */
2194 r = load_class_from_classbuffer(cb);
2197 /* the class could not be loaded, free the classinfo struct */
2202 /* Store this class in the loaded class cache this step also
2203 checks the loading constraints. If the class has been loaded
2204 before, the earlier loaded class is returned. */
2206 classinfo *res = classcache_store(NULL, c, true);
2216 /* SUN compatible -verbose:class output */
2218 if (opt_verboseclass && r) {
2220 utf_display_classname(name);
2221 printf(" from %s]\n", cb->path);
2228 #if defined(STATISTICS)
2234 if (getcompilingtime)
2235 compilingtime_start();
2239 goto return_exception;
2253 /* load_class_from_classbuffer *************************************************
2255 Loads everything interesting about a class from the class file. The
2256 'classinfo' structure must have been allocated previously.
2258 The super class and the interfaces implemented by this class need
2259 not be loaded. The link is set later by the function 'class_link'.
2261 The loaded class is removed from the list 'unloadedclasses' and
2262 added to the list 'unlinkedclasses'.
2265 This function is NOT synchronized!
2267 *******************************************************************************/
2269 classinfo *load_class_from_classbuffer(classbuffer *cb)
2277 descriptor_pool *descpool;
2278 #if defined(STATISTICS)
2282 #ifdef LOADER_VERBOSE
2283 char logtext[MAXLOGTEXT];
2286 /* get the classbuffer's class */
2290 /* maybe the class is already loaded */
2295 #ifdef LOADER_VERBOSE
2296 LOADER_INDENT(logtext);
2297 strcat(logtext,"load_class_from_classbuffer(");
2298 utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
2303 #if defined(STATISTICS)
2305 count_class_loads++;
2308 /* output for debugging purposes */
2311 log_message_class("Loading class: ", c);
2313 /* mark start of dump memory area */
2315 dumpsize = dump_size();
2317 /* class is somewhat loaded */
2321 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2322 goto return_exception;
2324 /* check signature */
2326 if (suck_u4(cb) != MAGIC) {
2327 *exceptionptr = new_classformaterror(c, "Bad magic number");
2329 goto return_exception;
2337 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2339 new_unsupportedclassversionerror(c,
2340 "Unsupported major.minor version %d.%d",
2343 goto return_exception;
2346 /* create a new descriptor pool */
2348 descpool = descriptor_pool_new(c);
2350 /* load the constant pool */
2352 if (!load_constantpool(cb, descpool))
2353 goto return_exception;
2356 c->erroneous_state = 0;
2357 c->initializing_thread = 0;
2359 c->classUsed = NOTUSED; /* not used initially CO-RT */
2364 if (!check_classbuffer_size(cb, 2))
2365 goto return_exception;
2367 c->flags = suck_u2(cb);
2369 /* check ACC flags consistency */
2371 if (c->flags & ACC_INTERFACE) {
2372 if (!(c->flags & ACC_ABSTRACT)) {
2373 /* We work around this because interfaces in JDK 1.1 are
2374 * not declared abstract. */
2376 c->flags |= ACC_ABSTRACT;
2379 if (c->flags & ACC_FINAL) {
2381 new_classformaterror(c,
2382 "Illegal class modifiers: 0x%X", c->flags);
2384 goto return_exception;
2387 if (c->flags & ACC_SUPER) {
2388 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2392 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2394 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2396 goto return_exception;
2399 if (!check_classbuffer_size(cb, 2 + 2))
2400 goto return_exception;
2405 if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2406 goto return_exception;
2408 if (c->name == utf_not_named_yet) {
2409 /* we finally have a name for this class */
2411 class_set_packagename(c);
2413 } else if (name != c->name) {
2417 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
2418 utf_strlen(name) + strlen(")") + strlen("0");
2420 msg = MNEW(char, msglen);
2422 utf_sprint(msg, c->name);
2423 strcat(msg, " (wrong name: ");
2424 utf_strcat(msg, name);
2428 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2430 MFREE(msg, char, msglen);
2432 goto return_exception;
2435 /* retrieve superclass */
2437 c->super.any = NULL;
2438 if ((i = suck_u2(cb))) {
2439 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
2440 goto return_exception;
2442 /* java.lang.Object may not have a super class. */
2444 if (c->name == utf_java_lang_Object) {
2446 new_exception_message(string_java_lang_ClassFormatError,
2447 "java.lang.Object with superclass");
2449 goto return_exception;
2452 /* Interfaces must have java.lang.Object as super class. */
2454 if ((c->flags & ACC_INTERFACE) &&
2455 supername != utf_java_lang_Object) {
2457 new_exception_message(string_java_lang_ClassFormatError,
2458 "Interfaces must have java.lang.Object as superclass");
2460 goto return_exception;
2466 /* This is only allowed for java.lang.Object. */
2468 if (c->name != utf_java_lang_Object) {
2469 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2471 goto return_exception;
2475 /* retrieve interfaces */
2477 if (!check_classbuffer_size(cb, 2))
2478 goto return_exception;
2480 c->interfacescount = suck_u2(cb);
2482 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2483 goto return_exception;
2485 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2486 for (i = 0; i < c->interfacescount; i++) {
2487 /* the classrefs are created later */
2488 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2489 goto return_exception;
2493 if (!check_classbuffer_size(cb, 2))
2494 goto return_exception;
2496 c->fieldscount = suck_u2(cb);
2497 c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
2498 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2499 for (i = 0; i < c->fieldscount; i++) {
2500 if (!load_field(cb, &(c->fields[i]),descpool))
2501 goto return_exception;
2505 if (!check_classbuffer_size(cb, 2))
2506 goto return_exception;
2508 c->methodscount = suck_u2(cb);
2509 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2510 c->methods = MNEW(methodinfo, c->methodscount);
2511 for (i = 0; i < c->methodscount; i++) {
2512 if (!load_method(cb, &(c->methods[i]),descpool))
2513 goto return_exception;
2516 /* create the class reference table */
2519 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2521 /* allocate space for the parsed descriptors */
2523 descriptor_pool_alloc_parsed_descriptors(descpool);
2525 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2527 #if defined(STATISTICS)
2529 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2530 count_classref_len += classrefsize;
2531 count_parsed_desc_len += descsize;
2535 /* put the classrefs in the constant pool */
2536 for (i = 0; i < c->cpcount; i++) {
2537 if (c->cptags[i] == CONSTANT_Class) {
2538 utf *name = (utf *) c->cpinfos[i];
2539 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2543 /* set the super class reference */
2546 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2548 goto return_exception;
2551 /* set the super interfaces references */
2553 for (i = 0; i < c->interfacescount; i++) {
2554 c->interfaces[i].ref =
2555 descriptor_pool_lookup_classref(descpool,
2556 (utf *) c->interfaces[i].any);
2557 if (!c->interfaces[i].ref)
2558 goto return_exception;
2561 /* parse field descriptors */
2563 for (i = 0; i < c->fieldscount; i++) {
2564 c->fields[i].parseddesc =
2565 descriptor_pool_parse_field_descriptor(descpool,
2566 c->fields[i].descriptor);
2567 if (!c->fields[i].parseddesc)
2568 goto return_exception;
2571 /* parse method descriptors */
2573 for (i = 0; i < c->methodscount; i++) {
2574 methodinfo *m = &c->methods[i];
2576 descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2577 m->flags, class_get_self_classref(m->class));
2579 goto return_exception;
2581 for (j = 0; j < m->exceptiontablelength; j++) {
2582 if (!m->exceptiontable[j].catchtype.any)
2584 if ((m->exceptiontable[j].catchtype.ref =
2585 descriptor_pool_lookup_classref(descpool,
2586 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2587 goto return_exception;
2590 for (j = 0; j < m->thrownexceptionscount; j++) {
2591 if (!m->thrownexceptions[j].any)
2593 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2594 (utf *) m->thrownexceptions[j].any)) == NULL)
2595 goto return_exception;
2599 /* parse the loaded descriptors */
2601 for (i = 0; i < c->cpcount; i++) {
2602 constant_FMIref *fmi;
2605 switch (c->cptags[i]) {
2606 case CONSTANT_Fieldref:
2607 fmi = (constant_FMIref *) c->cpinfos[i];
2608 fmi->parseddesc.fd =
2609 descriptor_pool_parse_field_descriptor(descpool,
2611 if (!fmi->parseddesc.fd)
2612 goto return_exception;
2613 index = (int) (size_t) fmi->classref;
2615 (constant_classref *) class_getconstant(c, index,
2618 goto return_exception;
2620 case CONSTANT_Methodref:
2621 case CONSTANT_InterfaceMethodref:
2622 fmi = (constant_FMIref *) c->cpinfos[i];
2623 index = (int) (size_t) fmi->classref;
2625 (constant_classref *) class_getconstant(c, index,
2628 goto return_exception;
2629 fmi->parseddesc.md =
2630 descriptor_pool_parse_method_descriptor(descpool,
2634 if (!fmi->parseddesc.md)
2635 goto return_exception;
2640 /* Check if all fields and methods can be uniquely
2641 * identified by (name,descriptor). */
2644 /* We use a hash table here to avoid making the
2645 * average case quadratic in # of methods, fields.
2647 static int shift = 0;
2649 u2 *next; /* for chaining colliding hash entries */
2655 /* Allocate hashtable */
2656 len = c->methodscount;
2657 if (len < c->fieldscount) len = c->fieldscount;
2659 hashtab = MNEW(u2,(hashlen + len));
2660 next = hashtab + hashlen;
2662 /* Determine bitshift (to get good hash values) */
2672 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2674 for (i = 0; i < c->fieldscount; ++i) {
2675 fieldinfo *fi = c->fields + i;
2677 /* It's ok if we lose bits here */
2678 index = ((((size_t) fi->name) +
2679 ((size_t) fi->descriptor)) >> shift) % hashlen;
2681 if ((old = hashtab[index])) {
2685 if (c->fields[old].name == fi->name &&
2686 c->fields[old].descriptor == fi->descriptor) {
2688 new_classformaterror(c,
2689 "Repetitive field name/signature");
2691 goto return_exception;
2693 } while ((old = next[old]));
2695 hashtab[index] = i + 1;
2699 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2701 for (i = 0; i < c->methodscount; ++i) {
2702 methodinfo *mi = c->methods + i;
2704 /* It's ok if we lose bits here */
2705 index = ((((size_t) mi->name) +
2706 ((size_t) mi->descriptor)) >> shift) % hashlen;
2710 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2711 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2715 if ((old = hashtab[index])) {
2719 if (c->methods[old].name == mi->name &&
2720 c->methods[old].descriptor == mi->descriptor) {
2722 new_classformaterror(c,
2723 "Repetitive method name/signature");
2725 goto return_exception;
2727 } while ((old = next[old]));
2729 hashtab[index] = i + 1;
2732 MFREE(hashtab, u2, (hashlen + len));
2735 #if defined(STATISTICS)
2737 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2738 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2739 count_class_infos += sizeof(methodinfo) * c->methodscount;
2743 /* load attribute structures */
2745 if (!check_classbuffer_size(cb, 2))
2746 goto return_exception;
2748 if (!load_attributes(cb, suck_u2(cb)))
2749 goto return_exception;
2752 /* Pre java 1.5 version don't check this. This implementation is like
2753 java 1.5 do it: for class file version 45.3 we don't check it, older
2754 versions are checked.
2756 if ((ma == 45 && mi > 3) || ma > 45) {
2757 /* check if all data has been read */
2758 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2760 if (classdata_left > 0) {
2762 new_classformaterror(c, "Extra bytes at the end of class file");
2763 goto return_exception;
2768 /* release dump area */
2770 dump_release(dumpsize);
2773 log_message_class("Loading done class: ", c);
2779 /* release dump area */
2781 dump_release(dumpsize);
2783 /* an exception has been thrown */
2790 /* load_newly_created_array ****************************************************
2792 Load a newly created array class.
2795 c....................the array class C has been loaded
2796 other classinfo......the array class was found in the class cache,
2798 NULL.................an exception has been thrown
2801 This is an internal function. Do not use it unless you know exactly
2804 Use one of the load_class_... functions for general array class loading.
2806 *******************************************************************************/
2808 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2810 classinfo *comp = NULL;
2812 methoddesc *clonedesc;
2813 constant_classref *classrefs;
2818 #ifdef LOADER_VERBOSE
2819 char logtext[MAXLOGTEXT];
2820 LOADER_INDENT(logtext);
2821 strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
2822 sprintf(logtext+strlen(logtext),") loader=%p",loader);
2826 text = c->name->text;
2827 namelen = c->name->blength;
2829 /* Check array class name */
2831 if (namelen < 2 || text[0] != '[') {
2832 *exceptionptr = new_noclassdeffounderror(c->name);
2836 /* Check the element type */
2840 /* c is an array of arrays. We have to create the component class. */
2842 u = utf_new_intern(text + 1, namelen - 1);
2844 if (!(comp = load_class_from_classloader(u, loader))) {
2849 LOADER_ASSERT(comp->loaded);
2854 /* the array's flags are that of the component class */
2855 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2856 c->classloader = comp->classloader;
2860 /* c is an array of objects. */
2862 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2863 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2864 *exceptionptr = new_noclassdeffounderror(c->name);
2868 u = utf_new_intern(text + 2, namelen - 3);
2871 if (!(comp = load_class_from_classloader(u, loader))) {
2876 LOADER_ASSERT(comp->loaded);
2881 /* the array's flags are that of the component class */
2882 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2883 c->classloader = comp->classloader;
2887 /* c is an array of a primitive type */
2889 /* check for cases like `[II' */
2891 *exceptionptr = new_noclassdeffounderror(c->name);
2895 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2896 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2897 c->classloader = NULL;
2900 LOADER_ASSERT(class_java_lang_Object);
2901 LOADER_ASSERT(class_java_lang_Cloneable);
2902 LOADER_ASSERT(class_java_io_Serializable);
2904 /* setup the array class */
2906 c->super.cls = class_java_lang_Object;
2908 c->interfacescount = 2;
2909 c->interfaces = MNEW(classref_or_classinfo, 2);
2914 tc = class_java_lang_Cloneable;
2915 LOADER_ASSERT(tc->loaded);
2916 list_addfirst(&unlinkedclasses, tc);
2917 c->interfaces[0].cls = tc;
2919 tc = class_java_io_Serializable;
2920 LOADER_ASSERT(tc->loaded);
2921 list_addfirst(&unlinkedclasses, tc);
2922 c->interfaces[1].cls = tc;
2925 c->interfaces[0].cls = class_java_lang_Cloneable;
2926 c->interfaces[1].cls = class_java_io_Serializable;
2929 c->methodscount = 1;
2930 c->methods = MNEW(methodinfo, c->methodscount);
2932 classrefs = MNEW(constant_classref, 2);
2933 CLASSREF_INIT(classrefs[0], c, c->name);
2934 CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2936 /* create descriptor for clone method */
2937 /* we need one paramslot which is reserved for the 'this' parameter */
2938 clonedesc = NEW(methoddesc);
2939 clonedesc->returntype.type = TYPE_ADDRESS;
2940 clonedesc->returntype.classref = classrefs + 1;
2941 clonedesc->returntype.arraydim = 0;
2942 /* initialize params to "empty", add real params below in
2943 descriptor_params_from_paramtypes */
2944 clonedesc->paramcount = 0;
2945 clonedesc->paramslots = 0;
2946 clonedesc->paramtypes[0].classref = classrefs + 0;
2948 /* create methodinfo */
2951 MSET(clone, 0, methodinfo, 1);
2953 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2954 initObjectLock(&clone->header);
2957 /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter
2959 clone->flags = ACC_PUBLIC | ACC_NATIVE;
2960 clone->name = utf_clone;
2961 clone->descriptor = utf_void__java_lang_Object;
2962 clone->parseddesc = clonedesc;
2964 clone->monoPoly = MONO;
2966 /* parse the descriptor to get the register allocation */
2968 if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2972 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2974 /* XXX: field: length? */
2976 /* array classes are not loaded from class files */
2979 c->parseddescs = (u1 *) clonedesc;
2980 c->parseddescsize = sizeof(methodinfo);
2981 c->classrefs = classrefs;
2982 c->classrefcount = 1;
2984 /* insert class into the loaded class cache */
2985 /* XXX free classinfo if NULL returned? */
2987 return classcache_store(loader,c,true);
2991 /* loader_close ****************************************************************
2993 Frees all resources.
2995 *******************************************************************************/
2997 void loader_close(void)
3004 * These are local overrides for various environment variables in Emacs.
3005 * Please do not remove this and leave it at the end of the file, where
3006 * Emacs will automagically detect them.
3007 * ---------------------------------------------------------------------
3010 * indent-tabs-mode: t