1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
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
28 Changes: Andreas Krall
33 $Id: loader.c 1112 2004-05-31 15:47:20Z jowenn $
50 #include "toolbox/memory.h"
51 #include "toolbox/logging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "nat/java_lang_Throwable.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
79 /* utf-symbols for pointer comparison of frequently used strings */
81 static utf *utf_innerclasses; /* InnerClasses */
82 static utf *utf_constantvalue; /* ConstantValue */
83 static utf *utf_code; /* Code */
84 static utf *utf_exceptions; /* Exceptions */
85 static utf *utf_linenumbertable; /* LineNumberTable */
86 static utf *utf_sourcefile; /* SourceFile */
87 static utf *utf_finalize; /* finalize */
88 static utf *utf_fidesc; /* ()V changed */
89 static utf *utf_init; /* <init> */
90 static utf *utf_clinit; /* <clinit> */
91 static utf *utf_initsystemclass; /* initializeSystemClass */
92 static utf *utf_systemclass; /* java/lang/System */
93 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
94 static utf *utf_vmclass; /* java/lang/VMClassLoader */
95 static utf *utf_initialize;
96 static utf *utf_initializedesc;
97 static utf *utf_java_lang_Object; /* java/lang/Object */
99 utf *utf_fillInStackTrace_name;
100 utf *utf_fillInStackTrace_desc;
110 /* important system classes ***************************************************/
112 classinfo *class_java_lang_Object;
113 classinfo *class_java_lang_String;
114 classinfo *class_java_lang_Cloneable;
115 classinfo *class_java_io_Serializable;
117 /* Pseudo classes for the typechecker */
118 classinfo *pseudo_class_Arraystub = NULL;
119 classinfo *pseudo_class_Null = NULL;
120 classinfo *pseudo_class_New = NULL;
121 vftbl *pseudo_class_Arraystub_vftbl = NULL;
123 utf *array_packagename = NULL;
126 /********************************************************************
127 list of classpath entries (either filesystem directories or
129 ********************************************************************/
130 static classpath_info *classpath_entries=0;
133 /******************************************************************************
135 structure for primitive classes: contains the class for wrapping the
136 primitive type, the primitive class, the name of the class for wrapping,
137 the one character type signature and the name of the primitive class
139 ******************************************************************************/
141 /* CAUTION: Don't change the order of the types. This table is indexed
142 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
144 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
145 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
146 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
147 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
148 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
149 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
150 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
151 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
152 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
153 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
157 /* instances of important system classes **************************************/
159 java_objectheader *proto_java_lang_NullPointerException;
162 /************* functions for reading classdata *********************************
164 getting classdata in blocks of variable size
165 (8,16,32,64-bit integer or float)
167 *******************************************************************************/
169 static char *classpath = ""; /* searchpath for classfiles */
172 /* assert that at least <len> bytes are left to read */
173 /* <len> is limited to the range of non-negative s4 values */
175 #define ASSERT_LEFT(cb, len) \
177 if (((s4) (len)) < 0 || \
178 (((cb)->data + (cb)->size) - (cb)->pos - 1) < (len)) { \
179 char message[MAXLOGTEXT]; \
180 utf_sprint_classname(message, (cb)->class->name); \
181 sprintf(message + strlen(message), " (Truncated class file)"); \
183 new_exception_message(string_java_lang_ClassFormatError, \
185 throw_exception_exit(); \
190 /* transfer block of classfile data into a buffer */
192 #define suck_nbytes(buffer, cb, len) \
194 ASSERT_LEFT((cb), (len)); \
195 memcpy((buffer), (cb)->pos + 1, (len)); \
196 (cb)->pos += (len); \
200 /* skip block of classfile data */
202 #define skip_nbytes(cb, len) \
204 ASSERT_LEFT((cb), (len)); \
205 (cb)->pos += (len); \
209 inline u1 suck_u1(classbuffer *cb)
216 inline u2 suck_u2(classbuffer *cb)
220 return ((u2) a << 8) + (u2) b;
224 inline u4 suck_u4(classbuffer *cb)
230 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
233 #define suck_s8(a) (s8) suck_u8((a))
234 #define suck_s2(a) (s2) suck_u2((a))
235 #define suck_s4(a) (s4) suck_u4((a))
236 #define suck_s1(a) (s1) suck_u1((a))
239 /* get u8 from classfile data */
240 static u8 suck_u8(classbuffer *cb)
246 return (hi << 32) + lo;
249 v.high = suck_u4(cb);
256 /* get float from classfile data */
257 static float suck_float(classbuffer *cb)
265 for (i = 0; i < 4; i++)
266 buffer[3 - i] = suck_u1(cb);
268 memcpy((u1*) (&f), buffer, 4);
270 suck_nbytes((u1*) (&f), cb, 4);
273 if (sizeof(float) != 4) {
275 new_exception_message(string_java_lang_InternalError,
276 "Incompatible float-format");
278 /* XXX should we exit in such a case? */
279 throw_exception_exit();
286 /* get double from classfile data */
287 static double suck_double(classbuffer *cb)
295 for (i = 0; i < 8; i++)
296 buffer[7 - i] = suck_u1(cb);
298 memcpy((u1*) (&d), buffer, 8);
300 suck_nbytes((u1*) (&d), cb, 8);
303 if (sizeof(double) != 8) {
305 new_exception_message(string_java_lang_InternalError,
306 "Incompatible double-format");
308 /* XXX should we exit in such a case? */
309 throw_exception_exit();
316 /************************** function suck_init *********************************
318 called once at startup, sets the searchpath for the classfiles
320 *******************************************************************************/
322 void suck_init(char *cpath)
329 union classpath_info *tmp;
330 union classpath_info *insertAfter=0;
337 if (classpath_entries)
338 panic("suck_init should be called only once");
340 for (start = classpath; (*start) != '\0';) {
341 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
345 filenamelen = end - start;
348 if (strncasecmp(end - 3, "zip", 3) == 0 ||
349 strncasecmp(end - 3, "jar", 3) == 0) {
354 if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
355 panic("path length >= MAXFILENAME in suck_init");
358 filename = MNEW(char*, CLASSPATH_MAXFILENAME);
360 strncpy(filename, start, filenamelen);
361 filename[filenamelen + 1] = '\0';
366 unzFile uf = unzOpen(filename);
369 tmp = (union classpath_info *) NEW(classpath_info);
370 tmp->archive.type = CLASSPATH_ARCHIVE;
371 tmp->archive.uf = uf;
372 tmp->archive.next = 0;
376 panic("Zip/JAR not supported");
380 tmp = (union classpath_info *) NEW(classpath_info);
381 tmp->filepath.type = CLASSPATH_PATH;
382 tmp->filepath.next = 0;
384 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
385 filename[filenamelen] = '/';
386 filename[filenamelen + 1] = '\0';
390 tmp->filepath.filename = filename;
391 tmp->filepath.pathlen = filenamelen;
397 insertAfter->filepath.next = tmp;
400 classpath_entries = tmp;
412 MFREE(filename, char*, CLASSPATH_MAXFILENAME);
417 void create_all_classes()
421 for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
422 #if defined(USE_ZLIB)
423 unz_file_info file_info;
424 if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
428 s = (unz_s *) cpi->archive.uf;
429 ce = s->cacao_dir_list;
432 (void) class_new(ce->name);
438 #if defined(USE_ZLIB)
445 /************************** function suck_start ********************************
447 returns true if classbuffer is already loaded or a file for the
448 specified class has succussfully been read in. All directories of
449 the searchpath are used to find the classfile (<classname>.class).
450 Returns false if no classfile is found and writes an error message.
452 *******************************************************************************/
454 classbuffer *suck_start(classinfo *c)
456 classpath_info *currPos;
459 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
466 utf_ptr = c->name->text;
468 while (utf_ptr < utf_end(c->name)) {
469 if (filenamelen >= CLASSPATH_MAXFILENAME) {
471 new_exception_message(string_java_lang_InternalError,
472 "Filename too long");
474 /* XXX should we exit in such a case? */
475 throw_exception_exit();
479 if ((ch <= ' ' || ch > 'z') && (ch != '/')) /* invalid character */
481 filename[filenamelen++] = ch;
484 strcpy(filename + filenamelen, ".class");
487 for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
489 if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
490 if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
491 unz_file_info file_info;
492 /*log_text("Class found in zip file");*/
493 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
494 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
495 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
496 cb = NEW(classbuffer);
498 cb->size = file_info.uncompressed_size;
499 cb->data = MNEW(u1, cb->size);
500 cb->pos = cb->data - 1;
501 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
502 if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
503 unzCloseCurrentFile(currPos->archive.uf);
507 MFREE(cb->data, u1, cb->size);
508 FREE(cb, classbuffer);
509 log_text("Error while unzipping");
511 } else log_text("Error while opening file in archive");
512 } else log_text("Error while retrieving fileinfo");
514 unzCloseCurrentFile(currPos->archive.uf);
518 if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
519 strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
520 classfile = fopen(currPos->filepath.filename, "r");
521 if (classfile) { /* file exists */
523 /* determine size of classfile */
525 /* dolog("File: %s",filename); */
526 err = stat(currPos->filepath.filename, &buffer);
528 if (!err) { /* read classfile data */
529 cb = NEW(classbuffer);
531 cb->size = buffer.st_size;
532 cb->data = MNEW(u1, cb->size);
533 cb->pos = cb->data - 1;
534 fread(cb->data, 1, cb->size, classfile);
546 dolog("Warning: Can not open class file '%s'", filename);
553 /************************** function suck_stop *********************************
555 frees memory for buffer with classfile data.
556 Caution: this function may only be called if buffer has been allocated
557 by suck_start with reading a file
559 *******************************************************************************/
561 void suck_stop(classbuffer *cb)
565 MFREE(cb->data, u1, cb->size);
566 FREE(cb, classbuffer);
570 /******************************************************************************/
571 /******************* Some support functions ***********************************/
572 /******************************************************************************/
574 void fprintflags (FILE *fp, u2 f)
576 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
577 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
578 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
579 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
580 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
581 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
582 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
583 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
584 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
585 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
586 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
590 /********** internal function: printflags (only for debugging) ***************/
592 void printflags(u2 f)
594 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
595 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
596 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
597 if ( f & ACC_STATIC ) printf (" STATIC");
598 if ( f & ACC_FINAL ) printf (" FINAL");
599 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
600 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
601 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
602 if ( f & ACC_NATIVE ) printf (" NATIVE");
603 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
604 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
608 /************************* Function: skipattribute *****************************
610 skips a (1) 'attribute' structure in the class file
612 *******************************************************************************/
614 static void skipattribute(classbuffer *cb)
619 skip_nbytes(cb, len);
623 /********************** Function: skipattributebody ****************************
625 skips an attribute after the 16 bit reference to attribute_name has already
628 *******************************************************************************/
630 static void skipattributebody(classbuffer *cb)
634 skip_nbytes(cb, len);
638 /************************* Function: skipattributes ****************************
640 skips num attribute structures
642 *******************************************************************************/
644 static void skipattributes(classbuffer *cb, u4 num)
647 for (i = 0; i < num; i++)
652 /******************** function: innerclass_getconstant ************************
654 like class_getconstant, but if cptags is ZERO null is returned
656 *******************************************************************************/
658 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
660 /* invalid position in constantpool */
661 if (pos >= c->cpcount)
662 panic("Attempt to access constant outside range");
664 /* constantpool entry of type 0 */
668 /* check type of constantpool entry */
669 if (c->cptags[pos] != ctype) {
670 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
671 (int) ctype, (int) c->cptags[pos] );
674 return c->cpinfos[pos];
678 /************************ function: attribute_load ****************************
680 read attributes from classfile
682 *******************************************************************************/
684 static void attribute_load(classbuffer *cb, classinfo *c, u4 num)
688 for (i = 0; i < num; i++) {
689 /* retrieve attribute name */
690 utf *aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
692 if (aname == utf_innerclasses) {
693 /* innerclasses attribute */
695 if (c->innerclass != NULL)
696 panic("Class has more than one InnerClasses attribute");
698 /* skip attribute length */
700 /* number of records */
701 c->innerclasscount = suck_u2(cb);
702 /* allocate memory for innerclass structure */
703 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
705 for (j = 0; j < c->innerclasscount; j++) {
706 /* The innerclass structure contains a class with an encoded name,
707 its defining scope, its simple name and a bitmask of the access flags.
708 If an inner class is not a member, its outer_class is NULL,
709 if a class is anonymous, its name is NULL. */
711 innerclassinfo *info = c->innerclass + j;
713 info->inner_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
714 info->outer_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
715 info->name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
716 info->flags = suck_u2(cb); /* access_flags bitmask */
718 } else if (aname==utf_sourcefile) {
720 /*log_text("source file attribute found");*/
721 c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
723 /* unknown attribute */
724 skipattributebody(cb);
730 /******************* function: checkfielddescriptor ****************************
732 checks whether a field-descriptor is valid and aborts otherwise
733 all referenced classes are inserted into the list of unloaded classes
735 *******************************************************************************/
737 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
739 class_from_descriptor(utf_ptr,end_pos,NULL,
741 | CLASSLOAD_NULLPRIMITIVE
743 | CLASSLOAD_CHECKEND);
745 /* XXX use the following if -noverify */
747 char *tstart; /* pointer to start of classname */
749 char *start = utf_ptr;
751 switch (*utf_ptr++) {
765 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
766 panic ("Ill formed descriptor");
770 panic ("Ill formed descriptor");
773 /* exceeding characters */
774 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
779 /******************* function checkmethoddescriptor ****************************
781 checks whether a method-descriptor is valid and aborts otherwise.
782 All referenced classes are inserted into the list of unloaded classes.
784 The number of arguments is returned. A long or double argument is counted
787 *******************************************************************************/
789 static int checkmethoddescriptor (utf *d)
791 char *utf_ptr = d->text; /* current position in utf text */
792 char *end_pos = utf_end(d); /* points behind utf string */
793 int argcount = 0; /* number of arguments */
795 /* method descriptor must start with parenthesis */
796 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
798 /* check arguments */
799 while (utf_ptr != end_pos && *utf_ptr != ')') {
800 /* We cannot count the this argument here because
801 * we don't know if the method is static. */
802 if (*utf_ptr == 'J' || *utf_ptr == 'D')
806 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
808 | CLASSLOAD_NULLPRIMITIVE
812 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
813 utf_ptr++; /* skip ')' */
815 class_from_descriptor(utf_ptr,end_pos,NULL,
817 | CLASSLOAD_NULLPRIMITIVE
818 | CLASSLOAD_CHECKEND);
821 panic("Invalid method descriptor: too many arguments");
825 /* XXX use the following if -noverify */
827 /* check arguments */
828 while ((c = *utf_ptr++) != ')') {
845 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
846 panic ("Ill formed method descriptor");
850 panic ("Ill formed methodtype-descriptor");
854 /* check returntype */
856 /* returntype void */
857 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
860 /* treat as field-descriptor */
861 checkfielddescriptor (utf_ptr,end_pos);
866 /***************** Function: print_arraydescriptor ****************************
868 Debugging helper for displaying an arraydescriptor
870 *******************************************************************************/
872 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
875 fprintf(file, "<NULL>");
880 if (desc->componentvftbl) {
881 if (desc->componentvftbl->class)
882 utf_fprint(file, desc->componentvftbl->class->name);
884 fprintf(file, "<no classinfo>");
890 if (desc->elementvftbl) {
891 if (desc->elementvftbl->class)
892 utf_fprint(file, desc->elementvftbl->class->name);
894 fprintf(file, "<no classinfo>");
898 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
899 desc->dataoffset, desc->componentsize);
903 /******************************************************************************/
904 /************************** Functions for fields ****************************/
905 /******************************************************************************/
908 /************************ Function: field_load *********************************
910 Load everything about a class field from the class file and fill a
911 'fieldinfo' structure. For static fields, space in the data segment is
914 *******************************************************************************/
916 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
918 static fieldinfo *field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
922 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
924 f->flags = suck_u2(cb); /* ACC flags */
925 f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* name of field */
926 f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* JavaVM descriptor */
930 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
931 panic("Field with invalid name");
933 /* check flag consistency */
934 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
935 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
936 panic("Field has invalid access flags");
937 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
938 panic("Field is declared final and volatile");
939 if ((c->flags & ACC_INTERFACE) != 0) {
940 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
941 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
942 panic("Interface field is not declared static final public");
943 if ((f->flags & ACC_TRANSIENT) != 0)
944 panic("Interface field declared transient");
947 /* check descriptor */
948 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
951 f->type = jtype = desc_to_type(f->descriptor); /* data type */
952 f->offset = 0; /* offset from start of object */
957 case TYPE_INT: f->value.i = 0; break;
958 case TYPE_FLOAT: f->value.f = 0.0; break;
959 case TYPE_DOUBLE: f->value.d = 0.0; break;
960 case TYPE_ADDRESS: f->value.a = NULL; break;
963 f->value.l = 0; break;
965 f->value.l.low = 0; f->value.l.high = 0; break;
969 /* read attributes */
970 attrnum = suck_u2(cb);
971 for (i = 0; i < attrnum; i++) {
974 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
976 if (aname != utf_constantvalue) {
977 /* unknown attribute */
978 skipattributebody(cb);
981 /* constant value attribute */
983 if (pindex != field_load_NOVALUE)
984 panic("Field has more than one ConstantValue attribute");
986 /* check attribute length */
987 if (suck_u4(cb) != 2)
988 panic("ConstantValue attribute has invalid length");
990 /* index of value in constantpool */
991 pindex = suck_u2(cb);
993 /* initialize field with value from constantpool */
996 constant_integer *ci =
997 class_getconstant(c, pindex, CONSTANT_Integer);
998 f->value.i = ci->value;
1004 class_getconstant(c, pindex, CONSTANT_Long);
1005 f->value.l = cl->value;
1010 constant_float *cf =
1011 class_getconstant(c, pindex, CONSTANT_Float);
1012 f->value.f = cf->value;
1017 constant_double *cd =
1018 class_getconstant(c, pindex, CONSTANT_Double);
1019 f->value.d = cd->value;
1023 case TYPE_ADDRESS: {
1024 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1025 /* create javastring from compressed utf8-string */
1026 f->value.a = literalstring_new(u);
1031 log_text ("Invalid Constant - Type");
1036 /* just return fieldinfo* to signal everything was ok */
1042 /********************** function: field_free **********************************/
1044 static void field_free(fieldinfo *f)
1050 /**************** Function: field_display (debugging only) ********************/
1052 void field_display(fieldinfo *f)
1055 printflags(f->flags);
1057 utf_display(f->name);
1059 utf_display(f->descriptor);
1060 printf(" offset: %ld\n", (long int) (f->offset));
1064 /******************************************************************************/
1065 /************************* Functions for methods ******************************/
1066 /******************************************************************************/
1069 /*********************** Function: method_load *********************************
1071 Loads a method from the class file and fills an existing 'methodinfo'
1072 structure. For native methods, the function pointer field is set to the
1073 real function pointer, for JavaVM methods a pointer to the compiler is used
1076 *******************************************************************************/
1078 static methodinfo *method_load(classbuffer *cb, classinfo *c, methodinfo *m)
1082 char msg[MAXLOGTEXT]; /* maybe we get an exception */
1086 count_all_methods++;
1089 m->thrownexceptionscount = 0;
1090 m->linenumbercount = 0;
1094 m->flags = suck_u2(cb);
1095 m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1098 if (!is_valid_name_utf(m->name))
1099 panic("Method with invalid name");
1100 if (m->name->text[0] == '<'
1101 && m->name != utf_init && m->name != utf_clinit)
1102 panic("Method with invalid special name");
1105 m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1106 argcount = checkmethoddescriptor(m->descriptor);
1107 if (!(m->flags & ACC_STATIC))
1108 argcount++; /* count the 'this' argument */
1112 panic("Too many arguments in signature");
1114 /* check flag consistency */
1115 if (m->name != utf_clinit) {
1116 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1117 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1118 panic("Method has invalid access flags");
1120 if ((m->flags & ACC_ABSTRACT) != 0) {
1121 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1122 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1123 utf_sprint(msg, c->name);
1124 sprintf(msg + strlen(msg), " (Illegal method modifiers: 0x%x)", m->flags);
1127 new_exception_message(string_java_lang_ClassFormatError,
1134 if ((c->flags & ACC_INTERFACE) != 0) {
1135 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1136 != (ACC_ABSTRACT | ACC_PUBLIC))
1137 panic("Interface method is not declared abstract and public");
1140 if (m->name == utf_init) {
1141 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1142 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1143 panic("Instance initialization method has invalid flags set");
1149 m->exceptiontable = NULL;
1150 m->entrypoint = NULL;
1152 m->stubroutine = NULL;
1153 m->methodUsed = NOTUSED;
1156 m->subRedefsUsed = 0;
1160 if (!(m->flags & ACC_NATIVE)) {
1161 m->stubroutine = createcompilerstub(m);
1164 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1165 (m->flags & ACC_STATIC) != 0);
1167 m->stubroutine = createnativestub(f, m);
1172 attrnum = suck_u2(cb);
1173 for (i = 0; i < attrnum; i++) {
1176 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1178 if (aname != utf_code) {
1179 if (aname == utf_exceptions) {
1182 suck_u4(cb); /*length*/
1183 exceptionCount=suck_u2(cb);
1184 m->thrownexceptionscount=exceptionCount;
1185 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1186 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1187 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(cb),CONSTANT_Class);
1191 skipattributebody(cb);
1195 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1196 utf_sprint(msg, c->name);
1197 sprintf(msg + strlen(msg),
1198 " (Code attribute in native or abstract methods)");
1201 new_exception_message(string_java_lang_ClassFormatError,
1208 utf_sprint(msg, c->name);
1209 sprintf(msg + strlen(msg), " (Multiple Code attributes)");
1212 new_exception_message(string_java_lang_ClassFormatError,
1219 m->maxstack = suck_u2(cb);
1220 m->maxlocals = suck_u2(cb);
1221 if (m->maxlocals < argcount) {
1222 utf_sprint(msg, c->name);
1223 sprintf(msg + strlen(msg),
1224 " (Arguments can't fit into locals)");
1227 new_exception_message(string_java_lang_ClassFormatError,
1233 codelen = suck_u4(cb);
1236 panic("bytecode has zero length");
1238 if (codelen > 65535) {
1239 utf_sprint(msg, c->name);
1240 sprintf(msg + strlen(msg),
1241 " (Code of a method longer than 65535 bytes)");
1244 new_exception_message(string_java_lang_ClassFormatError,
1250 m->jcodelength = codelen;
1251 m->jcode = MNEW(u1, m->jcodelength);
1252 suck_nbytes(m->jcode, cb, m->jcodelength);
1254 m->exceptiontablelength = suck_u2(cb);
1256 MNEW(exceptiontable, m->exceptiontablelength);
1260 count_vmcode_len += m->jcodelength + 18;
1261 count_extable_len += 8 * m->exceptiontablelength;
1265 for (e = 0; e < m->exceptiontablelength; e++) {
1267 m->exceptiontable[e].startpc = suck_u2(cb);
1268 m->exceptiontable[e].endpc = suck_u2(cb);
1269 m->exceptiontable[e].handlerpc = suck_u2(cb);
1273 m->exceptiontable[e].catchtype = NULL;
1276 m->exceptiontable[e].catchtype =
1277 class_getconstant(c, idx, CONSTANT_Class);
1282 for (codeattrnum=suck_u2(cb);codeattrnum>0;codeattrnum--) {
1283 utf * caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1284 if (caname==utf_linenumbertable) {
1286 /*log_text("LineNumberTable found");*/
1288 m->linenumbercount=suck_u2(cb);
1289 /*printf("length:%d\n",m->linenumbercount);*/
1290 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1291 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1292 m->linenumbers[lncid].start_pc=suck_u2(cb);
1293 m->linenumbers[lncid].line_number=suck_u2(cb);
1296 skipattributes(cb, codeattrnum);
1298 } else skipattributebody(cb);
1305 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1306 utf_sprint(msg, c->name);
1307 sprintf(msg + strlen(msg), " (Missing Code attribute)");
1310 new_exception_message(string_java_lang_ClassFormatError, msg);
1315 /* just return methodinfo* to signal everything was ok */
1321 /********************* Function: method_free ***********************************
1323 frees all memory that was allocated for this method
1325 *******************************************************************************/
1327 static void method_free(methodinfo *m)
1330 MFREE(m->jcode, u1, m->jcodelength);
1332 if (m->exceptiontable)
1333 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1336 CFREE(m->mcode, m->mcodelength);
1338 if (m->stubroutine) {
1339 if (m->flags & ACC_NATIVE) {
1340 removenativestub(m->stubroutine);
1343 removecompilerstub(m->stubroutine);
1349 /************** Function: method_display (debugging only) **************/
1351 void method_display(methodinfo *m)
1354 printflags(m->flags);
1356 utf_display(m->name);
1358 utf_display(m->descriptor);
1362 /************** Function: method_display_flags_last (debugging only) **************/
1364 void method_display_flags_last(methodinfo *m)
1367 utf_display(m->name);
1369 utf_display(m->descriptor);
1371 printflags(m->flags);
1376 /******************** Function: method_canoverwrite ****************************
1378 Check if m and old are identical with respect to type and name. This means
1379 that old can be overwritten with m.
1381 *******************************************************************************/
1383 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1385 if (m->name != old->name) return false;
1386 if (m->descriptor != old->descriptor) return false;
1387 if (m->flags & ACC_STATIC) return false;
1392 /******************************************************************************/
1393 /************************ Functions for class *********************************/
1394 /******************************************************************************/
1397 /******************** function:: class_getconstant *****************************
1399 retrieves the value at position 'pos' of the constantpool of a class
1400 if the type of the value is other than 'ctype' the system is stopped
1402 *******************************************************************************/
1404 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1406 /* invalid position in constantpool */
1407 /* (pos == 0 is caught by type comparison) */
1408 if (pos >= c->cpcount)
1409 panic("Attempt to access constant outside range");
1411 /* check type of constantpool entry */
1413 if (c->cptags[pos] != ctype) {
1414 class_showconstantpool(c);
1415 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1416 (int) ctype, (int) c->cptags[pos]);
1419 return c->cpinfos[pos];
1423 /********************* Function: class_constanttype ****************************
1425 Determines the type of a class entry in the ConstantPool
1427 *******************************************************************************/
1429 u4 class_constanttype(classinfo *c, u4 pos)
1431 if (pos >= c->cpcount)
1432 panic("Attempt to access constant outside range");
1434 return c->cptags[pos];
1438 /******************** function: class_loadcpool ********************************
1440 loads the constantpool of a class,
1441 the entries are transformed into a simpler format
1442 by resolving references
1443 (a detailed overview of the compact structures can be found in global.h)
1445 *******************************************************************************/
1447 static void class_loadcpool(classbuffer *cb, classinfo *c)
1450 /* The following structures are used to save information which cannot be
1451 processed during the first pass. After the complete constantpool has
1452 been traversed the references can be resolved.
1453 (only in specific order) */
1455 /* CONSTANT_Class_info entries */
1456 typedef struct forward_class {
1457 struct forward_class *next;
1462 /* CONSTANT_String */
1463 typedef struct forward_string {
1464 struct forward_string *next;
1469 /* CONSTANT_NameAndType */
1470 typedef struct forward_nameandtype {
1471 struct forward_nameandtype *next;
1475 } forward_nameandtype;
1477 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1478 typedef struct forward_fieldmethint {
1479 struct forward_fieldmethint *next;
1483 u2 nameandtype_index;
1484 } forward_fieldmethint;
1488 long int dumpsize = dump_size ();
1490 forward_class *forward_classes = NULL;
1491 forward_string *forward_strings = NULL;
1492 forward_nameandtype *forward_nameandtypes = NULL;
1493 forward_fieldmethint *forward_fieldmethints = NULL;
1495 /* number of entries in the constant_pool table plus one */
1496 u4 cpcount = c->cpcount = suck_u2(cb);
1498 /* allocate memory */
1499 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1500 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1503 panic("Invalid constant_pool_count (0)");
1506 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1509 /* initialize constantpool */
1510 for (idx = 0; idx < cpcount; idx++) {
1511 cptags[idx] = CONSTANT_UNUSED;
1512 cpinfos[idx] = NULL;
1516 /******* first pass *******/
1517 /* entries which cannot be resolved now are written into
1518 temporary structures and traversed again later */
1521 while (idx < cpcount) {
1522 /* get constant type */
1526 case CONSTANT_Class: {
1527 forward_class *nfc = DNEW(forward_class);
1529 nfc->next = forward_classes;
1530 forward_classes = nfc;
1532 nfc->thisindex = idx;
1533 /* reference to CONSTANT_NameAndType */
1534 nfc->name_index = suck_u2(cb);
1540 case CONSTANT_Fieldref:
1541 case CONSTANT_Methodref:
1542 case CONSTANT_InterfaceMethodref: {
1543 forward_fieldmethint *nff = DNEW(forward_fieldmethint);
1545 nff->next = forward_fieldmethints;
1546 forward_fieldmethints = nff;
1548 nff->thisindex = idx;
1551 /* class or interface type that contains the declaration of the
1553 nff->class_index = suck_u2(cb);
1554 /* name and descriptor of the field or method */
1555 nff->nameandtype_index = suck_u2(cb);
1561 case CONSTANT_String: {
1562 forward_string *nfs = DNEW(forward_string);
1564 nfs->next = forward_strings;
1565 forward_strings = nfs;
1567 nfs->thisindex = idx;
1568 /* reference to CONSTANT_Utf8_info with string characters */
1569 nfs->string_index = suck_u2(cb);
1575 case CONSTANT_NameAndType: {
1576 forward_nameandtype *nfn = DNEW(forward_nameandtype);
1578 nfn->next = forward_nameandtypes;
1579 forward_nameandtypes = nfn;
1581 nfn->thisindex = idx;
1582 /* reference to CONSTANT_Utf8_info containing simple name */
1583 nfn->name_index = suck_u2(cb);
1584 /* reference to CONSTANT_Utf8_info containing field or method
1586 nfn->sig_index = suck_u2(cb);
1592 case CONSTANT_Integer: {
1593 constant_integer *ci = NEW(constant_integer);
1596 count_const_pool_len += sizeof(constant_integer);
1599 ci->value = suck_s4(cb);
1600 cptags[idx] = CONSTANT_Integer;
1607 case CONSTANT_Float: {
1608 constant_float *cf = NEW(constant_float);
1611 count_const_pool_len += sizeof(constant_float);
1614 cf->value = suck_float(cb);
1615 cptags[idx] = CONSTANT_Float;
1622 case CONSTANT_Long: {
1623 constant_long *cl = NEW(constant_long);
1626 count_const_pool_len += sizeof(constant_long);
1629 cl->value = suck_s8(cb);
1630 cptags[idx] = CONSTANT_Long;
1634 panic("Long constant exceeds constant pool");
1638 case CONSTANT_Double: {
1639 constant_double *cd = NEW(constant_double);
1642 count_const_pool_len += sizeof(constant_double);
1645 cd->value = suck_double(cb);
1646 cptags[idx] = CONSTANT_Double;
1650 panic("Double constant exceeds constant pool");
1654 case CONSTANT_Utf8: {
1655 /* number of bytes in the bytes array (not string-length) */
1656 u4 length = suck_u2(cb);
1657 cptags[idx] = CONSTANT_Utf8;
1658 /* validate the string */
1659 ASSERT_LEFT(cb, length);
1661 !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) {
1662 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1663 panic("Invalid UTF-8 string");
1665 /* insert utf-string into the utf-symboltable */
1666 cpinfos[idx] = utf_new_int(cb->pos + 1, length);
1668 /* skip bytes of the string */
1669 skip_nbytes(cb, length);
1675 error("Unkown constant type: %d",(int) t);
1680 /* resolve entries in temporary structures */
1682 while (forward_classes) {
1684 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1686 if (opt_verify && !is_valid_name_utf(name))
1687 panic("Class reference with invalid name");
1689 cptags[forward_classes->thisindex] = CONSTANT_Class;
1690 /* retrieve class from class-table */
1691 cpinfos[forward_classes->thisindex] = class_new(name);
1693 forward_classes = forward_classes->next;
1696 while (forward_strings) {
1698 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1700 /* resolve utf-string */
1701 cptags[forward_strings->thisindex] = CONSTANT_String;
1702 cpinfos[forward_strings->thisindex] = text;
1704 forward_strings = forward_strings->next;
1707 while (forward_nameandtypes) {
1708 constant_nameandtype *cn = NEW(constant_nameandtype);
1711 count_const_pool_len += sizeof(constant_nameandtype);
1714 /* resolve simple name and descriptor */
1715 cn->name = class_getconstant(c,
1716 forward_nameandtypes->name_index,
1719 cn->descriptor = class_getconstant(c,
1720 forward_nameandtypes->sig_index,
1725 if (!is_valid_name_utf(cn->name))
1726 panic("NameAndType with invalid name");
1727 /* disallow referencing <clinit> among others */
1728 if (cn->name->text[0] == '<' && cn->name != utf_init)
1729 panic("NameAndType with invalid special name");
1732 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1733 cpinfos[forward_nameandtypes->thisindex] = cn;
1735 forward_nameandtypes = forward_nameandtypes->next;
1738 while (forward_fieldmethints) {
1739 constant_nameandtype *nat;
1740 constant_FMIref *fmi = NEW(constant_FMIref);
1743 count_const_pool_len += sizeof(constant_FMIref);
1745 /* resolve simple name and descriptor */
1746 nat = class_getconstant(c,
1747 forward_fieldmethints->nameandtype_index,
1748 CONSTANT_NameAndType);
1750 fmi->class = class_getconstant(c,
1751 forward_fieldmethints->class_index,
1753 fmi->name = nat->name;
1754 fmi->descriptor = nat->descriptor;
1756 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1757 cpinfos[forward_fieldmethints->thisindex] = fmi;
1759 switch (forward_fieldmethints->tag) {
1760 case CONSTANT_Fieldref: /* check validity of descriptor */
1761 checkfielddescriptor(fmi->descriptor->text,
1762 utf_end(fmi->descriptor));
1764 case CONSTANT_InterfaceMethodref:
1765 case CONSTANT_Methodref: /* check validity of descriptor */
1766 checkmethoddescriptor(fmi->descriptor);
1770 forward_fieldmethints = forward_fieldmethints->next;
1773 dump_release(dumpsize);
1777 /********************** Function: class_load ***********************************
1779 Loads everything interesting about a class from the class file. The
1780 'classinfo' structure must have been allocated previously.
1782 The super class and the interfaces implemented by this class need not be
1783 loaded. The link is set later by the function 'class_link'.
1785 The loaded class is removed from the list 'unloadedclasses' and added to
1786 the list 'unlinkedclasses'.
1788 *******************************************************************************/
1790 classinfo *class_load_intern(classbuffer *cb);
1792 classinfo *class_load(classinfo *c)
1799 #if defined(USE_THREADS)
1800 #if defined(NATIVE_THREADS)
1808 /* maybe the class is already loaded */
1810 #if defined(USE_THREADS)
1811 #if defined(NATIVE_THREADS)
1824 starttime = getcputime();
1826 /* load classdata, throw exception on error */
1828 if ((cb = suck_start(c)) == NULL) {
1829 /* this means, the classpath was not set properly */
1830 if (c->name == utf_java_lang_Object)
1831 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1832 "java/lang/Object");
1835 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1837 /* log_text("Leaving class_load with NoClassDefFoundError");*/
1838 #if defined(USE_THREADS)
1839 #if defined(NATIVE_THREADS)
1850 /* call the internal function */
1851 r = class_load_intern(cb);
1853 /* if return value is NULL, we had a problem and the class is not loaded */
1861 if (getloadingtime) {
1862 stoptime = getcputime();
1863 loadingtime += (stoptime - starttime);
1866 #if defined(USE_THREADS)
1867 #if defined(NATIVE_THREADS)
1879 classinfo *class_load_intern(classbuffer *cb)
1885 char msg[MAXLOGTEXT]; /* maybe we get an exception */
1887 /* get the classbuffer's class */
1890 /* maybe the class is already loaded */
1895 count_class_loads++;
1898 /* output for debugging purposes */
1900 log_message_class("Loading class: ", c);
1902 /* class is somewhat loaded */
1905 /* check signature */
1906 if (suck_u4(cb) != MAGIC) {
1907 utf_sprint_classname(msg, c->name);
1908 sprintf(msg + strlen(msg), " (Bad magic number)");
1911 new_exception_message(string_java_lang_ClassFormatError, msg);
1920 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION + 1 || mi != 0)) {
1921 utf_sprint_classname(msg, c->name);
1922 sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
1926 new_exception_message(string_java_lang_ClassFormatError,
1932 class_loadcpool(cb, c);
1934 c->erroneous_state = 0;
1935 c->initializing_thread = 0;
1937 c->classUsed = NOTUSED; /* not used initially CO-RT */
1941 c->flags = suck_u2(cb);
1942 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1944 /* check ACC flags consistency */
1945 if (c->flags & ACC_INTERFACE) {
1946 if (!(c->flags & ACC_ABSTRACT)) {
1947 /* We work around this because interfaces in JDK 1.1 are
1948 * not declared abstract. */
1950 c->flags |= ACC_ABSTRACT;
1951 /* panic("Interface class not declared abstract"); */
1954 if (c->flags & ACC_FINAL) {
1955 utf_sprint(msg, c->name);
1956 sprintf(msg + strlen(msg),
1957 " (Illegal class modifiers: 0x%x)", c->flags);
1960 new_exception_message(string_java_lang_ClassFormatError, msg);
1965 if (c->flags & ACC_SUPER) {
1966 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1970 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1971 utf_sprint(msg, c->name);
1972 sprintf(msg + strlen(msg),
1973 " (Illegal class modifiers: 0x%x)", c->flags);
1976 new_exception_message(string_java_lang_ClassFormatError, msg);
1983 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1984 utf_sprint(msg, c->name);
1985 sprintf(msg + strlen(msg), " (wrong name: ");
1986 utf_sprint(msg + strlen(msg),
1987 ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
1988 sprintf(msg + strlen(msg), ")");
1991 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1996 /* retrieve superclass */
1997 if ((i = suck_u2(cb))) {
1998 c->super = class_getconstant(c, i, CONSTANT_Class);
2000 /* java.lang.Object may not have a super class. */
2001 if (c->name == utf_java_lang_Object) {
2003 new_exception_message(string_java_lang_ClassFormatError,
2004 "java.lang.Object with superclass");
2009 /* Interfaces must have java.lang.Object as super class. */
2010 if ((c->flags & ACC_INTERFACE) &&
2011 c->super->name != utf_java_lang_Object) {
2013 new_exception_message(string_java_lang_ClassFormatError,
2014 "Interfaces must have java.lang.Object as superclass");
2022 /* This is only allowed for java.lang.Object. */
2023 if (c->name != utf_java_lang_Object) {
2024 utf_sprint(msg, c->name);
2025 sprintf(msg + strlen(msg), " (Bad superclass index)");
2028 new_exception_message(string_java_lang_ClassFormatError, msg);
2035 /* retrieve interfaces */
2036 c->interfacescount = suck_u2(cb);
2037 c->interfaces = MNEW(classinfo*, c->interfacescount);
2038 for (i = 0; i < c->interfacescount; i++) {
2040 class_getconstant(c, suck_u2(cb), CONSTANT_Class);
2044 c->fieldscount = suck_u2(cb);
2045 c->fields = GCNEW(fieldinfo, c->fieldscount);
2046 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2047 for (i = 0; i < c->fieldscount; i++) {
2048 if (!field_load(cb, c, &(c->fields[i])))
2053 c->methodscount = suck_u2(cb);
2054 c->methods = GCNEW(methodinfo, c->methodscount);
2055 /* c->methods = MNEW(methodinfo, c->methodscount); */
2056 for (i = 0; i < c->methodscount; i++) {
2057 if (!method_load(cb, c, &(c->methods[i])))
2061 /* Check if all fields and methods can be uniquely
2062 * identified by (name,descriptor). */
2064 /* We use a hash table here to avoid making the
2065 * average case quadratic in # of methods, fields.
2067 static int shift = 0;
2069 u2 *next; /* for chaining colliding hash entries */
2075 /* Allocate hashtable */
2076 len = c->methodscount;
2077 if (len < c->fieldscount) len = c->fieldscount;
2079 hashtab = MNEW(u2,(hashlen + len));
2080 next = hashtab + hashlen;
2082 /* Determine bitshift (to get good hash values) */
2092 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2093 for (i = 0; i < c->fieldscount; ++i) {
2094 fieldinfo *fi = c->fields + i;
2095 /* It's ok if we lose bits here */
2096 index = ((((size_t) fi->name) +
2097 ((size_t) fi->descriptor)) >> shift) % hashlen;
2098 if ((old = hashtab[index])) {
2102 if (c->fields[old].name == fi->name &&
2103 c->fields[old].descriptor == fi->descriptor) {
2104 utf_sprint(msg, c->name);
2105 sprintf(msg + strlen(msg), " (Repetitive field name/signature)");
2108 new_exception_message(string_java_lang_ClassFormatError,
2113 } while ((old = next[old]));
2115 hashtab[index] = i + 1;
2119 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2120 for (i = 0; i < c->methodscount; ++i) {
2121 methodinfo *mi = c->methods + i;
2122 /* It's ok if we lose bits here */
2123 index = ((((size_t) mi->name) +
2124 ((size_t) mi->descriptor)) >> shift) % hashlen;
2125 if ((old = hashtab[index])) {
2129 if (c->methods[old].name == mi->name &&
2130 c->methods[old].descriptor == mi->descriptor) {
2131 utf_sprint(msg, c->name);
2132 sprintf(msg + strlen(msg), " (Repetitive method name/signature)");
2135 new_exception_message(string_java_lang_ClassFormatError,
2140 } while ((old = next[old]));
2142 hashtab[index] = i + 1;
2145 MFREE(hashtab, u2, (hashlen + len));
2150 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2151 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2152 count_class_infos += sizeof(methodinfo) * c->methodscount;
2156 /* load variable-length attribute structures */
2157 attribute_load(cb, c, suck_u2(cb));
2160 /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
2162 /* check if all data has been read */
2163 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2165 if (classdata_left > 0) {
2167 dolog("There are %d extra bytes at end of classfile", classdata_left);
2168 /* The JVM spec disallows extra bytes. */
2169 panic("Extra bytes at end of classfile");
2174 log_message_class("Loading done class: ", c);
2181 /************** internal Function: class_highestinterface **********************
2183 Used by the function class_link to determine the amount of memory needed
2184 for the interface table.
2186 *******************************************************************************/
2188 static s4 class_highestinterface(classinfo *c)
2193 if (!(c->flags & ACC_INTERFACE)) {
2194 char logtext[MAXLOGTEXT];
2195 sprintf(logtext, "Interface-methods count requested for non-interface: ");
2196 utf_sprint(logtext + strlen(logtext), c->name);
2197 error("%s",logtext);
2201 for (i = 0; i < c->interfacescount; i++) {
2202 s4 h2 = class_highestinterface(c->interfaces[i]);
2210 /* class_addinterface **********************************************************
2212 Is needed by class_link for adding a VTBL to a class. All interfaces
2213 implemented by ic are added as well.
2215 *******************************************************************************/
2217 static void class_addinterface(classinfo *c, classinfo *ic)
2221 vftbl *vftbl = c->vftbl;
2223 if (i >= vftbl->interfacetablelength)
2224 panic ("Inernal error: interfacetable overflow");
2226 if (vftbl->interfacetable[-i])
2229 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
2230 vftbl->interfacevftbllength[i] = 1;
2231 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2232 vftbl->interfacetable[-i][0] = NULL;
2235 vftbl->interfacevftbllength[i] = ic->methodscount;
2236 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2240 count_vftbl_len += sizeof(methodptr) *
2241 (ic->methodscount + (ic->methodscount == 0));
2244 for (j = 0; j < ic->methodscount; j++) {
2247 for (m = 0; m < sc->methodscount; m++) {
2248 methodinfo *mi = &(sc->methods[m]);
2249 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2250 vftbl->interfacetable[-i][j] =
2251 vftbl->table[mi->vftblindex];
2262 for (j = 0; j < ic->interfacescount; j++)
2263 class_addinterface(c, ic->interfaces[j]);
2267 /******************* Function: class_new_array *********************************
2269 This function is called by class_new to setup an array class.
2271 *******************************************************************************/
2273 void class_new_array(classinfo *c)
2275 classinfo *comp = NULL;
2279 /* Check array class name */
2280 namelen = c->name->blength;
2281 if (namelen < 2 || c->name->text[0] != '[')
2282 panic("Invalid array class name");
2284 /* Check the component type */
2285 switch (c->name->text[1]) {
2287 /* c is an array of arrays. We have to create the component class. */
2288 comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
2292 /* c is an array of objects. */
2293 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2294 panic("Invalid array class name");
2295 comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
2299 /* Setup the array class */
2300 c->super = class_java_lang_Object;
2301 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2303 c->interfacescount = 2;
2304 c->interfaces = MNEW(classinfo*, 2);
2305 c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
2306 c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
2308 c->methodscount = 1;
2309 c->methods = MNEW(methodinfo, c->methodscount);
2312 memset(clone, 0, sizeof(methodinfo));
2313 clone->flags = ACC_PUBLIC;
2314 clone->name = utf_new_char("clone");
2315 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2317 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2318 clone->monoPoly = MONO;
2320 /* XXX: field: length? */
2322 /* array classes are not loaded from class files */
2327 /****************** Function: class_link_array *********************************
2329 This function is called by class_link to create the
2330 arraydescriptor for an array class.
2332 This function returns NULL if the array cannot be linked because
2333 the component type has not been linked yet.
2335 *******************************************************************************/
2337 static arraydescriptor *class_link_array(classinfo *c)
2339 classinfo *comp = NULL;
2340 s4 namelen = c->name->blength;
2341 arraydescriptor *desc;
2344 /* Check the component type */
2345 switch (c->name->text[1]) {
2347 /* c is an array of arrays. */
2348 /* comp = class_get(utf_new_int(c->name->text + 1, namelen - 1)); */
2349 comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
2351 panic("Could not find component array class.");
2355 /* c is an array of objects. */
2356 /* comp = class_get(utf_new_int(c->name->text + 2, namelen - 3)); */
2357 comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
2359 panic("Could not find component class.");
2363 /* If the component type has not been linked, link it now */
2364 if (comp && !comp->linked) {
2370 /* Allocate the arraydescriptor */
2371 desc = NEW(arraydescriptor);
2374 /* c is an array of references */
2375 desc->arraytype = ARRAYTYPE_OBJECT;
2376 desc->componentsize = sizeof(void*);
2377 desc->dataoffset = OFFSET(java_objectarray, data);
2379 compvftbl = comp->vftbl;
2381 panic("Component class has no vftbl");
2382 desc->componentvftbl = compvftbl;
2384 if (compvftbl->arraydesc) {
2385 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2386 if (compvftbl->arraydesc->dimension >= 255)
2387 panic("Creating array of dimension >255");
2388 desc->dimension = compvftbl->arraydesc->dimension + 1;
2389 desc->elementtype = compvftbl->arraydesc->elementtype;
2392 desc->elementvftbl = compvftbl;
2393 desc->dimension = 1;
2394 desc->elementtype = ARRAYTYPE_OBJECT;
2398 /* c is an array of a primitive type */
2399 switch (c->name->text[1]) {
2401 desc->arraytype = ARRAYTYPE_BOOLEAN;
2402 desc->dataoffset = OFFSET(java_booleanarray,data);
2403 desc->componentsize = sizeof(u1);
2407 desc->arraytype = ARRAYTYPE_BYTE;
2408 desc->dataoffset = OFFSET(java_bytearray,data);
2409 desc->componentsize = sizeof(u1);
2413 desc->arraytype = ARRAYTYPE_CHAR;
2414 desc->dataoffset = OFFSET(java_chararray,data);
2415 desc->componentsize = sizeof(u2);
2419 desc->arraytype = ARRAYTYPE_DOUBLE;
2420 desc->dataoffset = OFFSET(java_doublearray,data);
2421 desc->componentsize = sizeof(double);
2425 desc->arraytype = ARRAYTYPE_FLOAT;
2426 desc->dataoffset = OFFSET(java_floatarray,data);
2427 desc->componentsize = sizeof(float);
2431 desc->arraytype = ARRAYTYPE_INT;
2432 desc->dataoffset = OFFSET(java_intarray,data);
2433 desc->componentsize = sizeof(s4);
2437 desc->arraytype = ARRAYTYPE_LONG;
2438 desc->dataoffset = OFFSET(java_longarray,data);
2439 desc->componentsize = sizeof(s8);
2443 desc->arraytype = ARRAYTYPE_SHORT;
2444 desc->dataoffset = OFFSET(java_shortarray,data);
2445 desc->componentsize = sizeof(s2);
2449 panic("Invalid array class name");
2452 desc->componentvftbl = NULL;
2453 desc->elementvftbl = NULL;
2454 desc->dimension = 1;
2455 desc->elementtype = desc->arraytype;
2462 /********************** Function: class_link ***********************************
2464 Tries to link a class. The function calculates the length in bytes that
2465 an instance of this class requires as well as the VTBL for methods and
2468 *******************************************************************************/
2470 static classinfo *class_link_intern(classinfo *c);
2472 classinfo *class_link(classinfo *c)
2478 #if defined(USE_THREADS)
2479 #if defined(NATIVE_THREADS)
2487 /* maybe the class is already linked */
2489 #if defined(USE_THREADS)
2490 #if defined(NATIVE_THREADS)
2503 starttime = getcputime();
2505 /* call the internal function */
2506 r = class_link_intern(c);
2508 /* if return value is NULL, we had a problem and the class is not linked */
2513 if (getloadingtime) {
2514 stoptime = getcputime();
2515 loadingtime += (stoptime - starttime);
2518 #if defined(USE_THREADS)
2519 #if defined(NATIVE_THREADS)
2526 if (c->linked) return c; else return 0;
2530 static classinfo *class_link_intern(classinfo *c)
2532 s4 supervftbllength; /* vftbllegnth of super class */
2533 s4 vftbllength; /* vftbllength of current class */
2534 s4 interfacetablelength; /* interface table length */
2535 classinfo *super = c->super; /* super class */
2536 classinfo *ic, *c2; /* intermediate class variables */
2537 vftbl *v; /* vftbl of current class */
2538 s4 i; /* interface/method/field counter */
2539 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2541 /* maybe the class is already linked */
2546 log_message_class("Linking class: ", c);
2548 /* ok, this class is somewhat linked */
2551 /* check interfaces */
2553 for (i = 0; i < c->interfacescount; i++) {
2554 ic = c->interfaces[i];
2556 /* detect circularity */
2559 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2571 if (!(ic->flags & ACC_INTERFACE)) {
2572 dolog("Specified interface is not declared as interface:");
2576 panic("Specified interface is not declared as interface");
2580 /* check super class */
2582 if (super == NULL) { /* class java.lang.Object */
2584 c->classUsed = USED; /* Object class is always used CO-RT*/
2586 c->instancesize = sizeof(java_objectheader);
2588 vftbllength = supervftbllength = 0;
2590 c->finalizer = NULL;
2593 /* detect circularity */
2596 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2608 if (super->flags & ACC_INTERFACE)
2609 panic("Interface specified as super class");
2611 /* handle array classes */
2612 /* The component class must have been linked already. */
2613 if (c->name->text[0] == '[') {
2614 if ((arraydesc = class_link_array(c)) == NULL) {
2615 panic("class_link: class_link_array");
2619 /* Don't allow extending final classes */
2620 if (super->flags & ACC_FINAL)
2621 panic("Trying to extend final class");
2623 if (c->flags & ACC_INTERFACE)
2624 c->index = interfaceindex++;
2626 c->index = super->index + 1;
2628 c->instancesize = super->instancesize;
2630 vftbllength = supervftbllength = super->vftbl->vftbllength;
2632 c->finalizer = super->finalizer;
2635 /* compute vftbl length */
2637 for (i = 0; i < c->methodscount; i++) {
2638 methodinfo *m = &(c->methods[i]);
2640 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2641 classinfo *sc = super;
2644 for (j = 0; j < sc->methodscount; j++) {
2645 if (method_canoverwrite(m, &(sc->methods[j]))) {
2646 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2647 goto notfoundvftblindex;
2649 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2652 log_utf(sc->methods[j].name);
2653 log_utf(sc->methods[j].descriptor);
2654 panic("Trying to overwrite final method");
2656 m->vftblindex = sc->methods[j].vftblindex;
2657 goto foundvftblindex;
2663 m->vftblindex = (vftbllength++);
2672 sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2675 /* compute interfacetable length */
2677 interfacetablelength = 0;
2680 for (i = 0; i < c2->interfacescount; i++) {
2681 s4 h = class_highestinterface(c2->interfaces[i]) + 1;
2682 if (h > interfacetablelength)
2683 interfacetablelength = h;
2688 /* allocate virtual function table */
2690 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2691 (vftbllength - 1) + sizeof(methodptr*) *
2692 (interfacetablelength - (interfacetablelength > 0)));
2693 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2694 (interfacetablelength > 1));
2695 c->header.vftbl = c->vftbl = v;
2696 /* utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
2698 v->vftbllength = vftbllength;
2699 v->interfacetablelength = interfacetablelength;
2700 v->arraydesc = arraydesc;
2702 /* store interface index in vftbl */
2703 if (c->flags & ACC_INTERFACE)
2704 v->baseval = -(c->index);
2706 /* copy virtual function table of super class */
2708 for (i = 0; i < supervftbllength; i++)
2709 v->table[i] = super->vftbl->table[i];
2711 /* add method stubs into virtual function table */
2713 for (i = 0; i < c->methodscount; i++) {
2714 methodinfo *m = &(c->methods[i]);
2715 if (!(m->flags & ACC_STATIC)) {
2716 v->table[m->vftblindex] = m->stubroutine;
2720 /* compute instance size and offset of each field */
2722 for (i = 0; i < c->fieldscount; i++) {
2724 fieldinfo *f = &(c->fields[i]);
2726 if (!(f->flags & ACC_STATIC)) {
2727 dsize = desc_typesize(f->descriptor);
2728 c->instancesize = ALIGN(c->instancesize, dsize);
2729 f->offset = c->instancesize;
2730 c->instancesize += dsize;
2734 /* initialize interfacetable and interfacevftbllength */
2736 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2740 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2743 for (i = 0; i < interfacetablelength; i++) {
2744 v->interfacevftbllength[i] = 0;
2745 v->interfacetable[-i] = NULL;
2748 /* add interfaces */
2750 for (c2 = c; c2 != NULL; c2 = c2->super)
2751 for (i = 0; i < c2->interfacescount; i++) {
2752 class_addinterface(c, c2->interfaces[i]);
2755 /* add finalizer method (not for java.lang.Object) */
2757 if (super != NULL) {
2759 static utf *finame = NULL;
2760 static utf *fidesc = NULL;
2763 finame = utf_finalize;
2765 fidesc = utf_fidesc;
2767 fi = class_findmethod(c, finame, fidesc);
2769 if (!(fi->flags & ACC_STATIC)) {
2777 loader_compute_subclasses(c);
2780 log_message_class("Linking done class: ", c);
2782 /* just return c to show that we didn't had a problem */
2788 /******************* Function: class_freepool **********************************
2790 Frees all resources used by this classes Constant Pool.
2792 *******************************************************************************/
2794 static void class_freecpool(classinfo *c)
2800 for (idx=0; idx < c->cpcount; idx++) {
2801 tag = c->cptags[idx];
2802 info = c->cpinfos[idx];
2806 case CONSTANT_Fieldref:
2807 case CONSTANT_Methodref:
2808 case CONSTANT_InterfaceMethodref:
2809 FREE(info, constant_FMIref);
2811 case CONSTANT_Integer:
2812 FREE(info, constant_integer);
2814 case CONSTANT_Float:
2815 FREE(info, constant_float);
2818 FREE(info, constant_long);
2820 case CONSTANT_Double:
2821 FREE(info, constant_double);
2823 case CONSTANT_NameAndType:
2824 FREE(info, constant_nameandtype);
2830 MFREE(c->cptags, u1, c->cpcount);
2831 MFREE(c->cpinfos, voidptr, c->cpcount);
2835 /*********************** Function: class_free **********************************
2837 Frees all resources used by the class.
2839 *******************************************************************************/
2841 static void class_free(classinfo *c)
2848 MFREE(c->interfaces, classinfo*, c->interfacescount);
2850 for (i = 0; i < c->fieldscount; i++)
2851 field_free(&(c->fields[i]));
2853 for (i = 0; i < c->methodscount; i++)
2854 method_free(&(c->methods[i]));
2855 MFREE(c->methods, methodinfo, c->methodscount);
2857 if ((v = c->vftbl) != NULL) {
2859 mem_free(v->arraydesc,sizeof(arraydescriptor));
2861 for (i = 0; i < v->interfacetablelength; i++) {
2862 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2864 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2866 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2867 sizeof(methodptr*) * (v->interfacetablelength -
2868 (v->interfacetablelength > 0));
2869 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2870 (v->interfacetablelength > 1));
2874 if (c->innerclasscount)
2875 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2877 /* if (c->classvftbl)
2878 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2884 /************************* Function: class_findfield ***************************
2886 Searches a 'classinfo' structure for a field having the given name and
2889 *******************************************************************************/
2891 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2895 for (i = 0; i < c->fieldscount; i++) {
2896 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2897 return &(c->fields[i]);
2900 panic("Can not find field given in CONSTANT_Fieldref");
2902 /* keep compiler happy */
2907 /****************** Function: class_resolvefield_int ***************************
2909 This is an internally used helper function. Do not use this directly.
2911 Tries to resolve a field having the given name and type.
2912 If the field cannot be resolved, NULL is returned.
2914 *******************************************************************************/
2916 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2921 /* search for field in class c */
2922 for (i = 0; i < c->fieldscount; i++) {
2923 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2924 return &(c->fields[i]);
2928 /* try superinterfaces recursively */
2929 for (i = 0; i < c->interfacescount; ++i) {
2930 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2935 /* try superclass */
2937 return class_resolvefield_int(c->super, name, desc);
2944 /********************* Function: class_resolvefield ***************************
2946 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2948 If the field cannot be resolved the return value is NULL. If EXCEPT is
2949 true *exceptionptr is set, too.
2951 *******************************************************************************/
2953 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2954 classinfo *referer, bool except)
2958 /* XXX resolve class c */
2959 /* XXX check access from REFERER to C */
2961 fi = class_resolvefield_int(c, name, desc);
2966 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2972 /* XXX check access rights */
2978 /************************* Function: class_findmethod **************************
2980 Searches a 'classinfo' structure for a method having the given name and
2981 type and returns the index in the class info structure.
2982 If type is NULL, it is ignored.
2984 *******************************************************************************/
2986 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2990 for (i = 0; i < c->methodscount; i++) {
2992 /* utf_display_classname(c->name);printf("."); */
2993 /* utf_display(c->methods[i].name);printf("."); */
2994 /* utf_display(c->methods[i].descriptor); */
2997 if ((c->methods[i].name == name) && ((desc == NULL) ||
2998 (c->methods[i].descriptor == desc))) {
3007 /************************* Function: class_findmethod **************************
3009 Searches a 'classinfo' structure for a method having the given name and
3011 If type is NULL, it is ignored.
3013 *******************************************************************************/
3015 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3017 s4 idx = class_findmethodIndex(c, name, desc);
3022 return &(c->methods[idx]);
3026 /*********************** Function: class_fetchmethod **************************
3028 like class_findmethod, but aborts with an error if the method is not found
3030 *******************************************************************************/
3032 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3036 mi = class_findmethod(c, name, desc);
3039 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3040 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3041 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3042 panic("Method not found");
3049 /*********************** Function: class_findmethod_w**************************
3051 like class_findmethod, but logs a warning if the method is not found
3053 *******************************************************************************/
3055 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
3058 mi = class_findmethod(c, name, desc);
3061 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3062 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3063 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3065 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
3066 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
3067 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
3068 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
3069 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
3070 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
3071 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
3072 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
3073 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
3074 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
3075 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
3078 log_plain(" : WARNING: Method not found");log_nl( );
3085 /************************* Function: class_findmethod_approx ******************
3087 like class_findmethod but ignores the return value when comparing the
3090 *******************************************************************************/
3092 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3096 for (i = 0; i < c->methodscount; i++) {
3097 if (c->methods[i].name == name) {
3098 utf *meth_descr = c->methods[i].descriptor;
3102 return &(c->methods[i]);
3104 if (desc->blength <= meth_descr->blength) {
3105 /* current position in utf text */
3106 char *desc_utf_ptr = desc->text;
3107 char *meth_utf_ptr = meth_descr->text;
3108 /* points behind utf strings */
3109 char *desc_end = utf_end(desc);
3110 char *meth_end = utf_end(meth_descr);
3113 /* compare argument types */
3114 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3116 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3117 break; /* no match */
3120 return &(c->methods[i]); /* all parameter types equal */
3130 /***************** Function: class_resolvemethod_approx ***********************
3132 Searches a class and every super class for a method (without paying
3133 attention to the return value)
3135 *******************************************************************************/
3137 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3140 /* search for method (ignore returntype) */
3141 methodinfo *m = class_findmethod_approx(c, name, desc);
3144 /* search superclass */
3152 /************************* Function: class_resolvemethod ***********************
3154 Searches a class and every super class for a method.
3156 *******************************************************************************/
3158 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3160 /*log_text("Trying to resolve a method");
3161 utf_display(c->name);
3163 utf_display(desc);*/
3166 /*log_text("Looking in:");
3167 utf_display(c->name);*/
3168 methodinfo *m = class_findmethod(c, name, desc);
3170 /* search superclass */
3173 /*log_text("method not found:");*/
3179 /****************** Function: class_resolveinterfacemethod_int ****************
3181 Internally used helper function. Do not use this directly.
3183 *******************************************************************************/
3186 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
3191 mi = class_findmethod(c,name,desc);
3195 /* try the superinterfaces */
3196 for (i=0; i<c->interfacescount; ++i) {
3197 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3205 /******************** Function: class_resolveinterfacemethod ******************
3207 Resolves a reference from REFERER to a method with NAME and DESC in
3210 If the method cannot be resolved the return value is NULL. If EXCEPT is
3211 true *exceptionptr is set, too.
3213 *******************************************************************************/
3215 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3216 classinfo *referer, bool except)
3220 /* XXX resolve class c */
3221 /* XXX check access from REFERER to C */
3223 if (!(c->flags & ACC_INTERFACE)) {
3226 new_exception(string_java_lang_IncompatibleClassChangeError);
3231 mi = class_resolveinterfacemethod_int(c, name, desc);
3236 /* try class java.lang.Object */
3237 mi = class_findmethod(class_java_lang_Object, name, desc);
3244 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3250 /********************* Function: class_resolveclassmethod *********************
3252 Resolves a reference from REFERER to a method with NAME and DESC in
3255 If the method cannot be resolved the return value is NULL. If EXCEPT is
3256 true *exceptionptr is set, too.
3258 *******************************************************************************/
3260 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3261 classinfo *referer, bool except)
3266 char msg[MAXLOGTEXT];
3268 /* XXX resolve class c */
3269 /* XXX check access from REFERER to C */
3271 /* if (c->flags & ACC_INTERFACE) { */
3273 /* *exceptionptr = */
3274 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3278 /* try class c and its superclasses */
3281 mi = class_findmethod(cls, name, desc);
3284 } while ((cls = cls->super) != NULL); /* try the superclass */
3286 /* try the superinterfaces */
3287 for (i = 0; i < c->interfacescount; ++i) {
3288 mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
3294 utf_sprint(msg, c->name);
3295 sprintf(msg + strlen(msg), ".");
3296 utf_sprint(msg + strlen(msg), name);
3297 utf_sprint(msg + strlen(msg), desc);
3300 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3306 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3308 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3313 /* XXX check access rights */
3319 /************************* Function: class_issubclass **************************
3321 Checks if sub is a descendant of super.
3323 *******************************************************************************/
3325 bool class_issubclass(classinfo *sub, classinfo *super)
3328 if (!sub) return false;
3329 if (sub == super) return true;
3335 /****************** Initialization function for classes ******************
3337 In Java, every class can have a static initialization function. This
3338 function has to be called BEFORE calling other methods or accessing static
3341 *******************************************************************************/
3343 classinfo *class_init(classinfo *c)
3347 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3351 if (!makeinitializations)
3357 /* class is somewhat initialized */
3358 c->initialized = true;
3368 #if defined(STATISTICS)
3370 count_class_inits++;
3373 /* initialize super class */
3375 if (!c->super->loaded)
3376 if (!class_load(c->super))
3379 if (!c->super->linked)
3380 if (!class_link(c->super))
3383 if (!c->super->initialized) {
3385 char logtext[MAXLOGTEXT];
3386 sprintf(logtext, "Initialize super class ");
3387 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3388 sprintf(logtext + strlen(logtext), " from ");
3389 utf_sprint_classname(logtext + strlen(logtext), c->name);
3393 if (!class_init(c->super))
3398 /* initialize interface classes */
3399 for (i = 0; i < c->interfacescount; i++) {
3400 if (!c->interfaces[i]->loaded)
3401 if (!class_load(c->interfaces[i]))
3404 if (!c->interfaces[i]->linked)
3405 if (!class_link(c->interfaces[i]))
3408 if (!c->interfaces[i]->initialized) {
3410 char logtext[MAXLOGTEXT];
3411 sprintf(logtext, "Initialize interface class ");
3412 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3413 sprintf(logtext + strlen(logtext), " from ");
3414 utf_sprint_classname(logtext + strlen(logtext), c->name);
3418 if (!class_init(c->interfaces[i]))
3423 m = class_findmethod(c, utf_clinit, utf_fidesc);
3427 char logtext[MAXLOGTEXT];
3428 sprintf(logtext, "Class ");
3429 utf_sprint_classname(logtext + strlen(logtext), c->name);
3430 sprintf(logtext + strlen(logtext), " has no static class initializer");
3437 if (!(m->flags & ACC_STATIC))
3438 panic("Class initializer is not static!");
3441 log_message_class("Starting static class initializer for class: ", c);
3443 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3448 /* now call the initializer */
3449 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3451 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3452 assert(blockInts == 0);
3456 /* we have an exception */
3457 if (*exceptionptr) {
3458 java_objectheader *xptr;
3459 java_objectheader *cause;
3461 /* class is NOT initialized */
3462 c->initialized = false;
3465 cause = *exceptionptr;
3467 /* clear exception, because we are calling jit code again */
3468 *exceptionptr = NULL;
3470 /* wrap the exception */
3472 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3473 (java_lang_Throwable *) cause);
3475 if (*exceptionptr) {
3479 /* set new exception */
3480 *exceptionptr = xptr;
3486 log_message_class("Finished static class initializer for class: ", c);
3492 /********* Function: find_class_method_constant *********/
3494 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3499 for (i=0; i<c->cpcount; i++) {
3501 e = c -> cpinfos [i];
3504 switch (c -> cptags [i]) {
3505 case CONSTANT_Methodref:
3507 constant_FMIref *fmi = e;
3508 if ( (fmi->class->name == c1)
3509 && (fmi->name == m1)
3510 && (fmi->descriptor == d1)) {
3517 case CONSTANT_InterfaceMethodref:
3519 constant_FMIref *fmi = e;
3520 if ( (fmi->class->name == c1)
3521 && (fmi->name == m1)
3522 && (fmi->descriptor == d1)) {
3536 void class_showconstanti(classinfo *c, int ii)
3542 printf ("#%d: ", (int) i);
3544 switch (c->cptags [i]) {
3545 case CONSTANT_Class:
3546 printf("Classreference -> ");
3547 utf_display(((classinfo*)e)->name);
3550 case CONSTANT_Fieldref:
3551 printf("Fieldref -> "); goto displayFMIi;
3552 case CONSTANT_Methodref:
3553 printf("Methodref -> "); goto displayFMIi;
3554 case CONSTANT_InterfaceMethodref:
3555 printf("InterfaceMethod -> "); goto displayFMIi;
3558 constant_FMIref *fmi = e;
3559 utf_display(fmi->class->name);
3561 utf_display(fmi->name);
3563 utf_display(fmi->descriptor);
3567 case CONSTANT_String:
3568 printf("String -> ");
3571 case CONSTANT_Integer:
3572 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3574 case CONSTANT_Float:
3575 printf("Float -> %f", ((constant_float*)e)->value);
3577 case CONSTANT_Double:
3578 printf("Double -> %f", ((constant_double*)e)->value);
3582 u8 v = ((constant_long*)e)->value;
3584 printf("Long -> %ld", (long int) v);
3586 printf("Long -> HI: %ld, LO: %ld\n",
3587 (long int) v.high, (long int) v.low);
3591 case CONSTANT_NameAndType:
3593 constant_nameandtype *cnt = e;
3594 printf("NameAndType: ");
3595 utf_display(cnt->name);
3597 utf_display(cnt->descriptor);
3605 panic("Invalid type of ConstantPool-Entry");
3612 void class_showconstantpool (classinfo *c)
3617 printf ("---- dump of constant pool ----\n");
3619 for (i=0; i<c->cpcount; i++) {
3620 printf ("#%d: ", (int) i);
3622 e = c -> cpinfos [i];
3625 switch (c -> cptags [i]) {
3626 case CONSTANT_Class:
3627 printf ("Classreference -> ");
3628 utf_display ( ((classinfo*)e) -> name );
3631 case CONSTANT_Fieldref:
3632 printf ("Fieldref -> "); goto displayFMI;
3633 case CONSTANT_Methodref:
3634 printf ("Methodref -> "); goto displayFMI;
3635 case CONSTANT_InterfaceMethodref:
3636 printf ("InterfaceMethod -> "); goto displayFMI;
3639 constant_FMIref *fmi = e;
3640 utf_display ( fmi->class->name );
3642 utf_display ( fmi->name);
3644 utf_display ( fmi->descriptor );
3648 case CONSTANT_String:
3649 printf ("String -> ");
3652 case CONSTANT_Integer:
3653 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3655 case CONSTANT_Float:
3656 printf ("Float -> %f", ((constant_float*)e) -> value);
3658 case CONSTANT_Double:
3659 printf ("Double -> %f", ((constant_double*)e) -> value);
3663 u8 v = ((constant_long*)e) -> value;
3665 printf ("Long -> %ld", (long int) v);
3667 printf ("Long -> HI: %ld, LO: %ld\n",
3668 (long int) v.high, (long int) v.low);
3672 case CONSTANT_NameAndType:
3674 constant_nameandtype *cnt = e;
3675 printf ("NameAndType: ");
3676 utf_display (cnt->name);
3678 utf_display (cnt->descriptor);
3682 printf ("Utf8 -> ");
3686 panic ("Invalid type of ConstantPool-Entry");
3696 /********** Function: class_showmethods (debugging only) *************/
3698 void class_showmethods (classinfo *c)
3702 printf ("--------- Fields and Methods ----------------\n");
3703 printf ("Flags: "); printflags (c->flags); printf ("\n");
3705 printf ("This: "); utf_display (c->name); printf ("\n");
3707 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3709 printf ("Index: %d\n", c->index);
3711 printf ("interfaces:\n");
3712 for (i=0; i < c-> interfacescount; i++) {
3714 utf_display (c -> interfaces[i] -> name);
3715 printf (" (%d)\n", c->interfaces[i] -> index);
3718 printf ("fields:\n");
3719 for (i=0; i < c -> fieldscount; i++) {
3720 field_display (&(c -> fields[i]));
3723 printf ("methods:\n");
3724 for (i=0; i < c -> methodscount; i++) {
3725 methodinfo *m = &(c->methods[i]);
3726 if ( !(m->flags & ACC_STATIC))
3727 printf ("vftblindex: %d ", m->vftblindex);
3729 method_display ( m );
3733 printf ("Virtual function table:\n");
3734 for (i=0; i<c->vftbl->vftbllength; i++) {
3735 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3741 /******************************************************************************/
3742 /******************* General functions for the class loader *******************/
3743 /******************************************************************************/
3745 /**************** function: create_primitive_classes ***************************
3747 create classes representing primitive types
3749 *******************************************************************************/
3751 void create_primitive_classes()
3755 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
3756 /* create primitive class */
3757 classinfo *c = class_new_int(utf_new_char(primitivetype_table[i].name));
3758 c->classUsed = NOTUSED; /* not used initially CO-RT */
3761 /* prevent loader from loading primitive class */
3765 primitivetype_table[i].class_primitive = c;
3767 /* create class for wrapping the primitive type */
3768 c = class_new_int(utf_new_char(primitivetype_table[i].wrapname));
3769 primitivetype_table[i].class_wrap = c;
3770 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
3771 primitivetype_table[i].class_wrap->impldBy = NULL;
3773 /* create the primitive array class */
3774 if (primitivetype_table[i].arrayname) {
3775 c = class_new_int(utf_new_char(primitivetype_table[i].arrayname));
3776 primitivetype_table[i].arrayclass = c;
3780 primitivetype_table[i].arrayvftbl = c->vftbl;
3786 /**************** function: class_primitive_from_sig ***************************
3788 return the primitive class indicated by the given signature character
3790 If the descriptor does not indicate a valid primitive type the
3791 return value is NULL.
3793 ********************************************************************************/
3795 classinfo *class_primitive_from_sig(char sig)
3798 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3799 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3800 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3801 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3802 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3803 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3804 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3805 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3806 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3811 /****************** function: class_from_descriptor ****************************
3813 return the class indicated by the given descriptor
3815 utf_ptr....first character of descriptor
3816 end_ptr....first character after the end of the string
3817 next.......if non-NULL, *next is set to the first character after
3818 the descriptor. (Undefined if an error occurs.)
3820 mode.......a combination (binary or) of the following flags:
3822 (Flags marked with * are the default settings.)
3824 What to do if a reference type descriptor is parsed successfully:
3826 CLASSLOAD_SKIP...skip it and return something != NULL
3827 * CLASSLOAD_NEW....get classinfo * via class_new
3828 CLASSLOAD_LOAD...get classinfo * via loader_load
3830 How to handle primitive types:
3832 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3833 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3835 How to handle "V" descriptors:
3837 * CLASSLOAD_VOID.....handle it like other primitive types
3838 CLASSLOAD_NOVOID...treat it as an error
3840 How to deal with extra characters after the end of the
3843 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3844 CLASSLOAD_CHECKEND.....treat them as an error
3846 How to deal with errors:
3848 * CLASSLOAD_PANIC....abort execution with an error message
3849 CLASSLOAD_NOPANIC..return NULL on error
3851 ********************************************************************************/
3853 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3854 char **next, int mode)
3856 char *start = utf_ptr;
3860 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3862 if (mode & CLASSLOAD_CHECKEND)
3863 error |= (utf_ptr != end_ptr);
3866 if (next) *next = utf_ptr;
3870 if (mode & CLASSLOAD_NOVOID)
3881 return (mode & CLASSLOAD_NULLPRIMITIVE)
3883 : class_primitive_from_sig(*start);
3890 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3891 name = utf_new(start, utf_ptr - start);
3892 return (mode & CLASSLOAD_LOAD)
3893 ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
3897 /* An error occurred */
3898 if (mode & CLASSLOAD_NOPANIC)
3901 log_plain("Invalid descriptor at beginning of '");
3902 log_plain_utf(utf_new(start, end_ptr - start));
3906 panic("Invalid descriptor");
3908 /* keep compiler happy */
3913 /******************* function: type_from_descriptor ****************************
3915 return the basic type indicated by the given descriptor
3917 This function parses a descriptor and returns its basic type as
3918 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3920 cls...if non-NULL the referenced variable is set to the classinfo *
3921 returned by class_from_descriptor.
3923 For documentation of the arguments utf_ptr, end_ptr, next and mode
3924 see class_from_descriptor. The only difference is that
3925 type_from_descriptor always uses CLASSLOAD_PANIC.
3927 ********************************************************************************/
3929 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3930 char **next, int mode)
3933 if (!cls) cls = &mycls;
3934 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3951 return TYPE_ADDRESS;
3955 /*************** function: create_pseudo_classes *******************************
3957 create pseudo classes used by the typechecker
3959 ********************************************************************************/
3961 static void create_pseudo_classes()
3963 /* pseudo class for Arraystubs (extends java.lang.Object) */
3965 pseudo_class_Arraystub = class_new_int(utf_new_char("$ARRAYSTUB$"));
3966 pseudo_class_Arraystub->loaded = true;
3967 pseudo_class_Arraystub->super = class_java_lang_Object;
3968 pseudo_class_Arraystub->interfacescount = 2;
3969 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3970 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3971 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3973 class_link(pseudo_class_Arraystub);
3975 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3977 /* pseudo class representing the null type */
3979 pseudo_class_Null = class_new_int(utf_new_char("$NULL$"));
3980 pseudo_class_Null->loaded = true;
3981 pseudo_class_Null->super = class_java_lang_Object;
3982 class_link(pseudo_class_Null);
3984 /* pseudo class representing new uninitialized objects */
3986 pseudo_class_New = class_new_int(utf_new_char("$NEW$"));
3987 pseudo_class_New->loaded = true;
3988 pseudo_class_New->linked = true;
3989 pseudo_class_New->super = class_java_lang_Object;
3990 /* class_link(pseudo_class_New); */
3994 /********************** Function: loader_init **********************************
3996 Initializes all lists and loads all classes required for the system or the
3999 *******************************************************************************/
4001 void loader_init(u1 *stackbottom)
4005 /* create utf-symbols for pointer comparison of frequently used strings */
4006 utf_innerclasses = utf_new_char("InnerClasses");
4007 utf_constantvalue = utf_new_char("ConstantValue");
4008 utf_code = utf_new_char("Code");
4009 utf_exceptions = utf_new_char("Exceptions");
4010 utf_linenumbertable = utf_new_char("LineNumberTable");
4011 utf_sourcefile = utf_new_char("SourceFile");
4012 utf_finalize = utf_new_char("finalize");
4013 utf_fidesc = utf_new_char("()V");
4014 utf_init = utf_new_char("<init>");
4015 utf_clinit = utf_new_char("<clinit>");
4016 utf_initsystemclass = utf_new_char("initializeSystemClass");
4017 utf_systemclass = utf_new_char("java/lang/System");
4018 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
4019 utf_initialize = utf_new_char("initialize");
4020 utf_initializedesc = utf_new_char("(I)V");
4021 utf_vmclass = utf_new_char("java/lang/VMClass");
4022 utf_java_lang_Object= utf_new_char("java/lang/Object");
4023 array_packagename = utf_new_char("<the array package>");
4024 utf_fillInStackTrace_name = utf_new_char("fillInStackTrace");
4025 utf_fillInStackTrace_desc = utf_new_char("()Ljava/lang/Throwable;");
4027 /* create some important classes */
4028 /* These classes have to be created now because the classinfo
4029 * pointers are used in the loading code.
4031 class_java_lang_Object =
4032 class_new_int(utf_java_lang_Object);
4033 class_load(class_java_lang_Object);
4034 class_link(class_java_lang_Object);
4036 class_java_lang_String =
4037 class_new_int(utf_new_char("java/lang/String"));
4038 class_load(class_java_lang_String);
4039 class_link(class_java_lang_String);
4041 class_java_lang_Cloneable =
4042 class_new_int(utf_new_char("java/lang/Cloneable"));
4043 class_load(class_java_lang_Cloneable);
4044 class_link(class_java_lang_Cloneable);
4046 class_java_io_Serializable =
4047 class_new_int(utf_new_char("java/io/Serializable"));
4048 class_load(class_java_io_Serializable);
4049 class_link(class_java_io_Serializable);
4051 /* create classes representing primitive types */
4052 create_primitive_classes();
4054 /* create classes used by the typechecker */
4055 create_pseudo_classes();
4057 /* correct vftbl-entries (retarded loading of class java/lang/String) */
4058 stringtable_update();
4060 #if defined(USE_THREADS)
4061 if (stackbottom != 0)
4067 static void loader_compute_class_values(classinfo *c)
4071 c->vftbl->baseval = ++classvalue;
4074 while (subs != NULL) {
4075 loader_compute_class_values(subs);
4076 subs = subs->nextsub;
4079 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4083 void loader_compute_subclasses(classinfo *c)
4085 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4089 if (!(c->flags & ACC_INTERFACE)) {
4094 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4095 c->nextsub = c->super->sub;
4101 /* this is the java.lang.Object special case */
4102 if (!class_java_lang_Object) {
4103 loader_compute_class_values(c);
4106 loader_compute_class_values(class_java_lang_Object);
4109 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4115 /******************** Function: loader_close ***********************************
4119 *******************************************************************************/
4125 /* while ((c = list_first(&unloadedclasses))) { */
4126 /* list_remove(&unloadedclasses, c); */
4127 /* class_free(c); */
4129 /* while ((c = list_first(&unlinkedclasses))) { */
4130 /* list_remove(&unlinkedclasses, c); */
4131 /* class_free(c); */
4133 /* while ((c = list_first(&linkedclasses))) { */
4134 /* list_remove(&linkedclasses, c); */
4135 /* class_free(c); */
4141 * These are local overrides for various environment variables in Emacs.
4142 * Please do not remove this and leave it at the end of the file, where
4143 * Emacs will automagically detect them.
4144 * ---------------------------------------------------------------------
4147 * indent-tabs-mode: t