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 1110 2004-05-28 21:45:51Z 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 */
108 /* important system classes ***************************************************/
110 classinfo *class_java_lang_Object;
111 classinfo *class_java_lang_String;
112 classinfo *class_java_lang_Cloneable;
113 classinfo *class_java_io_Serializable;
115 /* Pseudo classes for the typechecker */
116 classinfo *pseudo_class_Arraystub = NULL;
117 classinfo *pseudo_class_Null = NULL;
118 classinfo *pseudo_class_New = NULL;
119 vftbl *pseudo_class_Arraystub_vftbl = NULL;
121 utf *array_packagename = NULL;
124 /********************************************************************
125 list of classpath entries (either filesystem directories or
127 ********************************************************************/
128 static classpath_info *classpath_entries=0;
131 /******************************************************************************
133 structure for primitive classes: contains the class for wrapping the
134 primitive type, the primitive class, the name of the class for wrapping,
135 the one character type signature and the name of the primitive class
137 ******************************************************************************/
139 /* CAUTION: Don't change the order of the types. This table is indexed
140 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
142 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
143 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
144 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
145 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
146 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
147 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
148 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
149 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
150 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
151 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
155 /* instances of important system classes **************************************/
157 java_objectheader *proto_java_lang_NullPointerException;
160 /************* functions for reading classdata *********************************
162 getting classdata in blocks of variable size
163 (8,16,32,64-bit integer or float)
165 *******************************************************************************/
167 static char *classpath = ""; /* searchpath for classfiles */
170 /* assert that at least <len> bytes are left to read */
171 /* <len> is limited to the range of non-negative s4 values */
173 #define ASSERT_LEFT(cb, len) \
175 if (((s4) (len)) < 0 || \
176 (((cb)->data + (cb)->size) - (cb)->pos - 1) < (len)) { \
177 char message[MAXLOGTEXT]; \
178 utf_sprint_classname(message, (cb)->class->name); \
179 sprintf(message + strlen(message), " (Truncated class file)"); \
181 new_exception_message(string_java_lang_ClassFormatError, \
183 throw_exception_exit(); \
188 /* transfer block of classfile data into a buffer */
190 #define suck_nbytes(buffer, cb, len) \
192 ASSERT_LEFT((cb), (len)); \
193 memcpy((buffer), (cb)->pos + 1, (len)); \
194 (cb)->pos += (len); \
198 /* skip block of classfile data */
200 #define skip_nbytes(cb, len) \
202 ASSERT_LEFT((cb), (len)); \
203 (cb)->pos += (len); \
207 inline u1 suck_u1(classbuffer *cb)
214 inline u2 suck_u2(classbuffer *cb)
218 return ((u2) a << 8) + (u2) b;
222 inline u4 suck_u4(classbuffer *cb)
228 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
231 #define suck_s8(a) (s8) suck_u8((a))
232 #define suck_s2(a) (s2) suck_u2((a))
233 #define suck_s4(a) (s4) suck_u4((a))
234 #define suck_s1(a) (s1) suck_u1((a))
237 /* get u8 from classfile data */
238 static u8 suck_u8(classbuffer *cb)
244 return (hi << 32) + lo;
247 v.high = suck_u4(cb);
254 /* get float from classfile data */
255 static float suck_float(classbuffer *cb)
263 for (i = 0; i < 4; i++)
264 buffer[3 - i] = suck_u1(cb);
266 memcpy((u1*) (&f), buffer, 4);
268 suck_nbytes((u1*) (&f), cb, 4);
271 if (sizeof(float) != 4) {
273 new_exception_message(string_java_lang_InternalError,
274 "Incompatible float-format");
276 /* XXX should we exit in such a case? */
277 throw_exception_exit();
284 /* get double from classfile data */
285 static double suck_double(classbuffer *cb)
293 for (i = 0; i < 8; i++)
294 buffer[7 - i] = suck_u1(cb);
296 memcpy((u1*) (&d), buffer, 8);
298 suck_nbytes((u1*) (&d), cb, 8);
301 if (sizeof(double) != 8) {
303 new_exception_message(string_java_lang_InternalError,
304 "Incompatible double-format");
306 /* XXX should we exit in such a case? */
307 throw_exception_exit();
314 /************************** function suck_init *********************************
316 called once at startup, sets the searchpath for the classfiles
318 *******************************************************************************/
320 void suck_init(char *cpath)
327 union classpath_info *tmp;
328 union classpath_info *insertAfter=0;
335 if (classpath_entries)
336 panic("suck_init should be called only once");
338 for (start = classpath; (*start) != '\0';) {
339 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
343 filenamelen = end - start;
346 if (strncasecmp(end - 3, "zip", 3) == 0 ||
347 strncasecmp(end - 3, "jar", 3) == 0) {
352 if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
353 panic("path length >= MAXFILENAME in suck_init");
356 filename = MNEW(char*, CLASSPATH_MAXFILENAME);
358 strncpy(filename, start, filenamelen);
359 filename[filenamelen + 1] = '\0';
364 unzFile uf = unzOpen(filename);
367 tmp = (union classpath_info *) NEW(classpath_info);
368 tmp->archive.type = CLASSPATH_ARCHIVE;
369 tmp->archive.uf = uf;
370 tmp->archive.next = 0;
374 panic("Zip/JAR not supported");
378 tmp = (union classpath_info *) NEW(classpath_info);
379 tmp->filepath.type = CLASSPATH_PATH;
380 tmp->filepath.next = 0;
382 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
383 filename[filenamelen] = '/';
384 filename[filenamelen + 1] = '\0';
388 tmp->filepath.filename = filename;
389 tmp->filepath.pathlen = filenamelen;
395 insertAfter->filepath.next = tmp;
398 classpath_entries = tmp;
410 MFREE(filename, char*, CLASSPATH_MAXFILENAME);
415 void create_all_classes()
419 for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
420 #if defined(USE_ZLIB)
421 unz_file_info file_info;
422 if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
426 s = (unz_s *) cpi->archive.uf;
427 ce = s->cacao_dir_list;
430 (void) class_new(ce->name);
436 #if defined(USE_ZLIB)
443 /************************** function suck_start ********************************
445 returns true if classbuffer is already loaded or a file for the
446 specified class has succussfully been read in. All directories of
447 the searchpath are used to find the classfile (<classname>.class).
448 Returns false if no classfile is found and writes an error message.
450 *******************************************************************************/
452 classbuffer *suck_start(classinfo *c)
454 classpath_info *currPos;
457 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
464 utf_ptr = c->name->text;
466 while (utf_ptr < utf_end(c->name)) {
467 if (filenamelen >= CLASSPATH_MAXFILENAME) {
469 new_exception_message(string_java_lang_InternalError,
470 "Filename too long");
472 /* XXX should we exit in such a case? */
473 throw_exception_exit();
477 if ((ch <= ' ' || ch > 'z') && (ch != '/')) /* invalid character */
479 filename[filenamelen++] = ch;
482 strcpy(filename + filenamelen, ".class");
485 for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
487 if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
488 if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
489 unz_file_info file_info;
490 /*log_text("Class found in zip file");*/
491 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
492 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
493 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
494 cb = NEW(classbuffer);
496 cb->size = file_info.uncompressed_size;
497 cb->data = MNEW(u1, cb->size);
498 cb->pos = cb->data - 1;
499 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
500 if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
501 unzCloseCurrentFile(currPos->archive.uf);
505 MFREE(cb->data, u1, cb->size);
506 FREE(cb, classbuffer);
507 log_text("Error while unzipping");
509 } else log_text("Error while opening file in archive");
510 } else log_text("Error while retrieving fileinfo");
512 unzCloseCurrentFile(currPos->archive.uf);
516 if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
517 strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
518 classfile = fopen(currPos->filepath.filename, "r");
519 if (classfile) { /* file exists */
521 /* determine size of classfile */
523 /* dolog("File: %s",filename); */
524 err = stat(currPos->filepath.filename, &buffer);
526 if (!err) { /* read classfile data */
527 cb = NEW(classbuffer);
529 cb->size = buffer.st_size;
530 cb->data = MNEW(u1, cb->size);
531 cb->pos = cb->data - 1;
532 fread(cb->data, 1, cb->size, classfile);
544 dolog("Warning: Can not open class file '%s'", filename);
551 /************************** function suck_stop *********************************
553 frees memory for buffer with classfile data.
554 Caution: this function may only be called if buffer has been allocated
555 by suck_start with reading a file
557 *******************************************************************************/
559 void suck_stop(classbuffer *cb)
563 MFREE(cb->data, u1, cb->size);
564 FREE(cb, classbuffer);
568 /******************************************************************************/
569 /******************* Some support functions ***********************************/
570 /******************************************************************************/
572 void fprintflags (FILE *fp, u2 f)
574 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
575 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
576 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
577 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
578 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
579 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
580 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
581 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
582 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
583 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
584 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
588 /********** internal function: printflags (only for debugging) ***************/
590 void printflags(u2 f)
592 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
593 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
594 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
595 if ( f & ACC_STATIC ) printf (" STATIC");
596 if ( f & ACC_FINAL ) printf (" FINAL");
597 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
598 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
599 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
600 if ( f & ACC_NATIVE ) printf (" NATIVE");
601 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
602 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
606 /************************* Function: skipattribute *****************************
608 skips a (1) 'attribute' structure in the class file
610 *******************************************************************************/
612 static void skipattribute(classbuffer *cb)
617 skip_nbytes(cb, len);
621 /********************** Function: skipattributebody ****************************
623 skips an attribute after the 16 bit reference to attribute_name has already
626 *******************************************************************************/
628 static void skipattributebody(classbuffer *cb)
632 skip_nbytes(cb, len);
636 /************************* Function: skipattributes ****************************
638 skips num attribute structures
640 *******************************************************************************/
642 static void skipattributes(classbuffer *cb, u4 num)
645 for (i = 0; i < num; i++)
650 /******************** function: innerclass_getconstant ************************
652 like class_getconstant, but if cptags is ZERO null is returned
654 *******************************************************************************/
656 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
658 /* invalid position in constantpool */
659 if (pos >= c->cpcount)
660 panic("Attempt to access constant outside range");
662 /* constantpool entry of type 0 */
666 /* check type of constantpool entry */
667 if (c->cptags[pos] != ctype) {
668 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
669 (int) ctype, (int) c->cptags[pos] );
672 return c->cpinfos[pos];
676 /************************ function: attribute_load ****************************
678 read attributes from classfile
680 *******************************************************************************/
682 static void attribute_load(classbuffer *cb, classinfo *c, u4 num)
686 for (i = 0; i < num; i++) {
687 /* retrieve attribute name */
688 utf *aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
690 if (aname == utf_innerclasses) {
691 /* innerclasses attribute */
693 if (c->innerclass != NULL)
694 panic("Class has more than one InnerClasses attribute");
696 /* skip attribute length */
698 /* number of records */
699 c->innerclasscount = suck_u2(cb);
700 /* allocate memory for innerclass structure */
701 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
703 for (j = 0; j < c->innerclasscount; j++) {
704 /* The innerclass structure contains a class with an encoded name,
705 its defining scope, its simple name and a bitmask of the access flags.
706 If an inner class is not a member, its outer_class is NULL,
707 if a class is anonymous, its name is NULL. */
709 innerclassinfo *info = c->innerclass + j;
711 info->inner_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
712 info->outer_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
713 info->name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
714 info->flags = suck_u2(cb); /* access_flags bitmask */
716 } else if (aname==utf_sourcefile) {
718 /*log_text("source file attribute found");*/
719 c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
721 /* unknown attribute */
722 skipattributebody(cb);
728 /******************* function: checkfielddescriptor ****************************
730 checks whether a field-descriptor is valid and aborts otherwise
731 all referenced classes are inserted into the list of unloaded classes
733 *******************************************************************************/
735 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
737 class_from_descriptor(utf_ptr,end_pos,NULL,
739 | CLASSLOAD_NULLPRIMITIVE
741 | CLASSLOAD_CHECKEND);
743 /* XXX use the following if -noverify */
745 char *tstart; /* pointer to start of classname */
747 char *start = utf_ptr;
749 switch (*utf_ptr++) {
763 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
764 panic ("Ill formed descriptor");
768 panic ("Ill formed descriptor");
771 /* exceeding characters */
772 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
777 /******************* function checkmethoddescriptor ****************************
779 checks whether a method-descriptor is valid and aborts otherwise.
780 All referenced classes are inserted into the list of unloaded classes.
782 The number of arguments is returned. A long or double argument is counted
785 *******************************************************************************/
787 static int checkmethoddescriptor (utf *d)
789 char *utf_ptr = d->text; /* current position in utf text */
790 char *end_pos = utf_end(d); /* points behind utf string */
791 int argcount = 0; /* number of arguments */
793 /* method descriptor must start with parenthesis */
794 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
796 /* check arguments */
797 while (utf_ptr != end_pos && *utf_ptr != ')') {
798 /* We cannot count the this argument here because
799 * we don't know if the method is static. */
800 if (*utf_ptr == 'J' || *utf_ptr == 'D')
804 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
806 | CLASSLOAD_NULLPRIMITIVE
810 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
811 utf_ptr++; /* skip ')' */
813 class_from_descriptor(utf_ptr,end_pos,NULL,
815 | CLASSLOAD_NULLPRIMITIVE
816 | CLASSLOAD_CHECKEND);
819 panic("Invalid method descriptor: too many arguments");
823 /* XXX use the following if -noverify */
825 /* check arguments */
826 while ((c = *utf_ptr++) != ')') {
843 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
844 panic ("Ill formed method descriptor");
848 panic ("Ill formed methodtype-descriptor");
852 /* check returntype */
854 /* returntype void */
855 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
858 /* treat as field-descriptor */
859 checkfielddescriptor (utf_ptr,end_pos);
864 /***************** Function: print_arraydescriptor ****************************
866 Debugging helper for displaying an arraydescriptor
868 *******************************************************************************/
870 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
873 fprintf(file, "<NULL>");
878 if (desc->componentvftbl) {
879 if (desc->componentvftbl->class)
880 utf_fprint(file, desc->componentvftbl->class->name);
882 fprintf(file, "<no classinfo>");
888 if (desc->elementvftbl) {
889 if (desc->elementvftbl->class)
890 utf_fprint(file, desc->elementvftbl->class->name);
892 fprintf(file, "<no classinfo>");
896 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
897 desc->dataoffset, desc->componentsize);
901 /******************************************************************************/
902 /************************** Functions for fields ****************************/
903 /******************************************************************************/
906 /************************ Function: field_load *********************************
908 Load everything about a class field from the class file and fill a
909 'fieldinfo' structure. For static fields, space in the data segment is
912 *******************************************************************************/
914 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
916 static fieldinfo *field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
920 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
922 f->flags = suck_u2(cb); /* ACC flags */
923 f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* name of field */
924 f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* JavaVM descriptor */
928 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
929 panic("Field with invalid name");
931 /* check flag consistency */
932 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
933 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
934 panic("Field has invalid access flags");
935 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
936 panic("Field is declared final and volatile");
937 if ((c->flags & ACC_INTERFACE) != 0) {
938 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
939 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
940 panic("Interface field is not declared static final public");
941 if ((f->flags & ACC_TRANSIENT) != 0)
942 panic("Interface field declared transient");
945 /* check descriptor */
946 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
949 f->type = jtype = desc_to_type(f->descriptor); /* data type */
950 f->offset = 0; /* offset from start of object */
955 case TYPE_INT: f->value.i = 0; break;
956 case TYPE_FLOAT: f->value.f = 0.0; break;
957 case TYPE_DOUBLE: f->value.d = 0.0; break;
958 case TYPE_ADDRESS: f->value.a = NULL; break;
961 f->value.l = 0; break;
963 f->value.l.low = 0; f->value.l.high = 0; break;
967 /* read attributes */
968 attrnum = suck_u2(cb);
969 for (i = 0; i < attrnum; i++) {
972 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
974 if (aname != utf_constantvalue) {
975 /* unknown attribute */
976 skipattributebody(cb);
979 /* constant value attribute */
981 if (pindex != field_load_NOVALUE)
982 panic("Field has more than one ConstantValue attribute");
984 /* check attribute length */
985 if (suck_u4(cb) != 2)
986 panic("ConstantValue attribute has invalid length");
988 /* index of value in constantpool */
989 pindex = suck_u2(cb);
991 /* initialize field with value from constantpool */
994 constant_integer *ci =
995 class_getconstant(c, pindex, CONSTANT_Integer);
996 f->value.i = ci->value;
1002 class_getconstant(c, pindex, CONSTANT_Long);
1003 f->value.l = cl->value;
1008 constant_float *cf =
1009 class_getconstant(c, pindex, CONSTANT_Float);
1010 f->value.f = cf->value;
1015 constant_double *cd =
1016 class_getconstant(c, pindex, CONSTANT_Double);
1017 f->value.d = cd->value;
1021 case TYPE_ADDRESS: {
1022 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1023 /* create javastring from compressed utf8-string */
1024 f->value.a = literalstring_new(u);
1029 log_text ("Invalid Constant - Type");
1034 /* just return fieldinfo* to signal everything was ok */
1040 /********************** function: field_free **********************************/
1042 static void field_free(fieldinfo *f)
1048 /**************** Function: field_display (debugging only) ********************/
1050 void field_display(fieldinfo *f)
1053 printflags(f->flags);
1055 utf_display(f->name);
1057 utf_display(f->descriptor);
1058 printf(" offset: %ld\n", (long int) (f->offset));
1062 /******************************************************************************/
1063 /************************* Functions for methods ******************************/
1064 /******************************************************************************/
1067 /*********************** Function: method_load *********************************
1069 Loads a method from the class file and fills an existing 'methodinfo'
1070 structure. For native methods, the function pointer field is set to the
1071 real function pointer, for JavaVM methods a pointer to the compiler is used
1074 *******************************************************************************/
1076 static methodinfo *method_load(classbuffer *cb, classinfo *c, methodinfo *m)
1080 char msg[MAXLOGTEXT]; /* maybe we get an exception */
1084 count_all_methods++;
1087 m->thrownexceptionscount = 0;
1088 m->linenumbercount = 0;
1092 m->flags = suck_u2(cb);
1093 m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1096 if (!is_valid_name_utf(m->name))
1097 panic("Method with invalid name");
1098 if (m->name->text[0] == '<'
1099 && m->name != utf_init && m->name != utf_clinit)
1100 panic("Method with invalid special name");
1103 m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1104 argcount = checkmethoddescriptor(m->descriptor);
1105 if (!(m->flags & ACC_STATIC))
1106 argcount++; /* count the 'this' argument */
1110 panic("Too many arguments in signature");
1112 /* check flag consistency */
1113 if (m->name != utf_clinit) {
1114 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1115 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1116 panic("Method has invalid access flags");
1118 if ((m->flags & ACC_ABSTRACT) != 0) {
1119 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1120 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1121 utf_sprint(msg, c->name);
1122 sprintf(msg + strlen(msg), " (Illegal method modifiers: 0x%x)", m->flags);
1125 new_exception_message(string_java_lang_ClassFormatError,
1132 if ((c->flags & ACC_INTERFACE) != 0) {
1133 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1134 != (ACC_ABSTRACT | ACC_PUBLIC))
1135 panic("Interface method is not declared abstract and public");
1138 if (m->name == utf_init) {
1139 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1140 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1141 panic("Instance initialization method has invalid flags set");
1147 m->exceptiontable = NULL;
1148 m->entrypoint = NULL;
1150 m->stubroutine = NULL;
1151 m->methodUsed = NOTUSED;
1154 m->subRedefsUsed = 0;
1158 if (!(m->flags & ACC_NATIVE)) {
1159 m->stubroutine = createcompilerstub(m);
1162 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1163 (m->flags & ACC_STATIC) != 0);
1165 m->stubroutine = createnativestub(f, m);
1170 attrnum = suck_u2(cb);
1171 for (i = 0; i < attrnum; i++) {
1174 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1176 if (aname != utf_code) {
1177 if (aname == utf_exceptions) {
1180 suck_u4(cb); /*length*/
1181 exceptionCount=suck_u2(cb);
1182 m->thrownexceptionscount=exceptionCount;
1183 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1184 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1185 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(cb),CONSTANT_Class);
1189 skipattributebody(cb);
1193 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1194 utf_sprint(msg, c->name);
1195 sprintf(msg + strlen(msg),
1196 " (Code attribute in native or abstract methods)");
1199 new_exception_message(string_java_lang_ClassFormatError,
1206 utf_sprint(msg, c->name);
1207 sprintf(msg + strlen(msg), " (Multiple Code attributes)");
1210 new_exception_message(string_java_lang_ClassFormatError,
1217 m->maxstack = suck_u2(cb);
1218 m->maxlocals = suck_u2(cb);
1219 if (m->maxlocals < argcount) {
1220 utf_sprint(msg, c->name);
1221 sprintf(msg + strlen(msg),
1222 " (Arguments can't fit into locals)");
1225 new_exception_message(string_java_lang_ClassFormatError,
1231 codelen = suck_u4(cb);
1234 panic("bytecode has zero length");
1236 if (codelen > 65535) {
1237 utf_sprint(msg, c->name);
1238 sprintf(msg + strlen(msg),
1239 " (Code of a method longer than 65535 bytes)");
1242 new_exception_message(string_java_lang_ClassFormatError,
1248 m->jcodelength = codelen;
1249 m->jcode = MNEW(u1, m->jcodelength);
1250 suck_nbytes(m->jcode, cb, m->jcodelength);
1252 m->exceptiontablelength = suck_u2(cb);
1254 MNEW(exceptiontable, m->exceptiontablelength);
1258 count_vmcode_len += m->jcodelength + 18;
1259 count_extable_len += 8 * m->exceptiontablelength;
1263 for (e = 0; e < m->exceptiontablelength; e++) {
1265 m->exceptiontable[e].startpc = suck_u2(cb);
1266 m->exceptiontable[e].endpc = suck_u2(cb);
1267 m->exceptiontable[e].handlerpc = suck_u2(cb);
1271 m->exceptiontable[e].catchtype = NULL;
1274 m->exceptiontable[e].catchtype =
1275 class_getconstant(c, idx, CONSTANT_Class);
1280 for (codeattrnum=suck_u2(cb);codeattrnum>0;codeattrnum--) {
1281 utf * caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1282 if (caname==utf_linenumbertable) {
1284 /*log_text("LineNumberTable found");*/
1286 m->linenumbercount=suck_u2(cb);
1287 /*printf("length:%d\n",m->linenumbercount);*/
1288 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1289 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1290 m->linenumbers[lncid].start_pc=suck_u2(cb);
1291 m->linenumbers[lncid].line_number=suck_u2(cb);
1294 skipattributes(cb, codeattrnum);
1296 } else skipattributebody(cb);
1303 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1304 utf_sprint(msg, c->name);
1305 sprintf(msg + strlen(msg), " (Missing Code attribute)");
1308 new_exception_message(string_java_lang_ClassFormatError, msg);
1313 /* just return methodinfo* to signal everything was ok */
1319 /********************* Function: method_free ***********************************
1321 frees all memory that was allocated for this method
1323 *******************************************************************************/
1325 static void method_free(methodinfo *m)
1328 MFREE(m->jcode, u1, m->jcodelength);
1330 if (m->exceptiontable)
1331 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1334 CFREE(m->mcode, m->mcodelength);
1336 if (m->stubroutine) {
1337 if (m->flags & ACC_NATIVE) {
1338 removenativestub(m->stubroutine);
1341 removecompilerstub(m->stubroutine);
1347 /************** Function: method_display (debugging only) **************/
1349 void method_display(methodinfo *m)
1352 printflags(m->flags);
1354 utf_display(m->name);
1356 utf_display(m->descriptor);
1360 /************** Function: method_display_flags_last (debugging only) **************/
1362 void method_display_flags_last(methodinfo *m)
1365 utf_display(m->name);
1367 utf_display(m->descriptor);
1369 printflags(m->flags);
1374 /******************** Function: method_canoverwrite ****************************
1376 Check if m and old are identical with respect to type and name. This means
1377 that old can be overwritten with m.
1379 *******************************************************************************/
1381 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1383 if (m->name != old->name) return false;
1384 if (m->descriptor != old->descriptor) return false;
1385 if (m->flags & ACC_STATIC) return false;
1390 /******************************************************************************/
1391 /************************ Functions for class *********************************/
1392 /******************************************************************************/
1395 /******************** function:: class_getconstant *****************************
1397 retrieves the value at position 'pos' of the constantpool of a class
1398 if the type of the value is other than 'ctype' the system is stopped
1400 *******************************************************************************/
1402 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1404 /* invalid position in constantpool */
1405 /* (pos == 0 is caught by type comparison) */
1406 if (pos >= c->cpcount)
1407 panic("Attempt to access constant outside range");
1409 /* check type of constantpool entry */
1411 if (c->cptags[pos] != ctype) {
1412 class_showconstantpool(c);
1413 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1414 (int) ctype, (int) c->cptags[pos]);
1417 return c->cpinfos[pos];
1421 /********************* Function: class_constanttype ****************************
1423 Determines the type of a class entry in the ConstantPool
1425 *******************************************************************************/
1427 u4 class_constanttype(classinfo *c, u4 pos)
1429 if (pos >= c->cpcount)
1430 panic("Attempt to access constant outside range");
1432 return c->cptags[pos];
1436 /******************** function: class_loadcpool ********************************
1438 loads the constantpool of a class,
1439 the entries are transformed into a simpler format
1440 by resolving references
1441 (a detailed overview of the compact structures can be found in global.h)
1443 *******************************************************************************/
1445 static void class_loadcpool(classbuffer *cb, classinfo *c)
1448 /* The following structures are used to save information which cannot be
1449 processed during the first pass. After the complete constantpool has
1450 been traversed the references can be resolved.
1451 (only in specific order) */
1453 /* CONSTANT_Class_info entries */
1454 typedef struct forward_class {
1455 struct forward_class *next;
1460 /* CONSTANT_String */
1461 typedef struct forward_string {
1462 struct forward_string *next;
1467 /* CONSTANT_NameAndType */
1468 typedef struct forward_nameandtype {
1469 struct forward_nameandtype *next;
1473 } forward_nameandtype;
1475 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1476 typedef struct forward_fieldmethint {
1477 struct forward_fieldmethint *next;
1481 u2 nameandtype_index;
1482 } forward_fieldmethint;
1486 long int dumpsize = dump_size ();
1488 forward_class *forward_classes = NULL;
1489 forward_string *forward_strings = NULL;
1490 forward_nameandtype *forward_nameandtypes = NULL;
1491 forward_fieldmethint *forward_fieldmethints = NULL;
1493 /* number of entries in the constant_pool table plus one */
1494 u4 cpcount = c->cpcount = suck_u2(cb);
1496 /* allocate memory */
1497 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1498 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1501 panic("Invalid constant_pool_count (0)");
1504 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1507 /* initialize constantpool */
1508 for (idx = 0; idx < cpcount; idx++) {
1509 cptags[idx] = CONSTANT_UNUSED;
1510 cpinfos[idx] = NULL;
1514 /******* first pass *******/
1515 /* entries which cannot be resolved now are written into
1516 temporary structures and traversed again later */
1519 while (idx < cpcount) {
1520 /* get constant type */
1524 case CONSTANT_Class: {
1525 forward_class *nfc = DNEW(forward_class);
1527 nfc->next = forward_classes;
1528 forward_classes = nfc;
1530 nfc->thisindex = idx;
1531 /* reference to CONSTANT_NameAndType */
1532 nfc->name_index = suck_u2(cb);
1538 case CONSTANT_Fieldref:
1539 case CONSTANT_Methodref:
1540 case CONSTANT_InterfaceMethodref: {
1541 forward_fieldmethint *nff = DNEW(forward_fieldmethint);
1543 nff->next = forward_fieldmethints;
1544 forward_fieldmethints = nff;
1546 nff->thisindex = idx;
1549 /* class or interface type that contains the declaration of the
1551 nff->class_index = suck_u2(cb);
1552 /* name and descriptor of the field or method */
1553 nff->nameandtype_index = suck_u2(cb);
1559 case CONSTANT_String: {
1560 forward_string *nfs = DNEW(forward_string);
1562 nfs->next = forward_strings;
1563 forward_strings = nfs;
1565 nfs->thisindex = idx;
1566 /* reference to CONSTANT_Utf8_info with string characters */
1567 nfs->string_index = suck_u2(cb);
1573 case CONSTANT_NameAndType: {
1574 forward_nameandtype *nfn = DNEW(forward_nameandtype);
1576 nfn->next = forward_nameandtypes;
1577 forward_nameandtypes = nfn;
1579 nfn->thisindex = idx;
1580 /* reference to CONSTANT_Utf8_info containing simple name */
1581 nfn->name_index = suck_u2(cb);
1582 /* reference to CONSTANT_Utf8_info containing field or method
1584 nfn->sig_index = suck_u2(cb);
1590 case CONSTANT_Integer: {
1591 constant_integer *ci = NEW(constant_integer);
1594 count_const_pool_len += sizeof(constant_integer);
1597 ci->value = suck_s4(cb);
1598 cptags[idx] = CONSTANT_Integer;
1605 case CONSTANT_Float: {
1606 constant_float *cf = NEW(constant_float);
1609 count_const_pool_len += sizeof(constant_float);
1612 cf->value = suck_float(cb);
1613 cptags[idx] = CONSTANT_Float;
1620 case CONSTANT_Long: {
1621 constant_long *cl = NEW(constant_long);
1624 count_const_pool_len += sizeof(constant_long);
1627 cl->value = suck_s8(cb);
1628 cptags[idx] = CONSTANT_Long;
1632 panic("Long constant exceeds constant pool");
1636 case CONSTANT_Double: {
1637 constant_double *cd = NEW(constant_double);
1640 count_const_pool_len += sizeof(constant_double);
1643 cd->value = suck_double(cb);
1644 cptags[idx] = CONSTANT_Double;
1648 panic("Double constant exceeds constant pool");
1652 case CONSTANT_Utf8: {
1653 /* number of bytes in the bytes array (not string-length) */
1654 u4 length = suck_u2(cb);
1655 cptags[idx] = CONSTANT_Utf8;
1656 /* validate the string */
1657 ASSERT_LEFT(cb, length);
1659 !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) {
1660 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1661 panic("Invalid UTF-8 string");
1663 /* insert utf-string into the utf-symboltable */
1664 cpinfos[idx] = utf_new_int(cb->pos + 1, length);
1666 /* skip bytes of the string */
1667 skip_nbytes(cb, length);
1673 error("Unkown constant type: %d",(int) t);
1678 /* resolve entries in temporary structures */
1680 while (forward_classes) {
1682 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1684 if (opt_verify && !is_valid_name_utf(name))
1685 panic("Class reference with invalid name");
1687 cptags[forward_classes->thisindex] = CONSTANT_Class;
1688 /* retrieve class from class-table */
1689 cpinfos[forward_classes->thisindex] = class_new(name);
1691 forward_classes = forward_classes->next;
1694 while (forward_strings) {
1696 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1698 /* resolve utf-string */
1699 cptags[forward_strings->thisindex] = CONSTANT_String;
1700 cpinfos[forward_strings->thisindex] = text;
1702 forward_strings = forward_strings->next;
1705 while (forward_nameandtypes) {
1706 constant_nameandtype *cn = NEW(constant_nameandtype);
1709 count_const_pool_len += sizeof(constant_nameandtype);
1712 /* resolve simple name and descriptor */
1713 cn->name = class_getconstant(c,
1714 forward_nameandtypes->name_index,
1717 cn->descriptor = class_getconstant(c,
1718 forward_nameandtypes->sig_index,
1723 if (!is_valid_name_utf(cn->name))
1724 panic("NameAndType with invalid name");
1725 /* disallow referencing <clinit> among others */
1726 if (cn->name->text[0] == '<' && cn->name != utf_init)
1727 panic("NameAndType with invalid special name");
1730 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1731 cpinfos[forward_nameandtypes->thisindex] = cn;
1733 forward_nameandtypes = forward_nameandtypes->next;
1736 while (forward_fieldmethints) {
1737 constant_nameandtype *nat;
1738 constant_FMIref *fmi = NEW(constant_FMIref);
1741 count_const_pool_len += sizeof(constant_FMIref);
1743 /* resolve simple name and descriptor */
1744 nat = class_getconstant(c,
1745 forward_fieldmethints->nameandtype_index,
1746 CONSTANT_NameAndType);
1748 fmi->class = class_getconstant(c,
1749 forward_fieldmethints->class_index,
1751 fmi->name = nat->name;
1752 fmi->descriptor = nat->descriptor;
1754 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1755 cpinfos[forward_fieldmethints->thisindex] = fmi;
1757 switch (forward_fieldmethints->tag) {
1758 case CONSTANT_Fieldref: /* check validity of descriptor */
1759 checkfielddescriptor(fmi->descriptor->text,
1760 utf_end(fmi->descriptor));
1762 case CONSTANT_InterfaceMethodref:
1763 case CONSTANT_Methodref: /* check validity of descriptor */
1764 checkmethoddescriptor(fmi->descriptor);
1768 forward_fieldmethints = forward_fieldmethints->next;
1771 dump_release(dumpsize);
1775 /********************** Function: class_load ***********************************
1777 Loads everything interesting about a class from the class file. The
1778 'classinfo' structure must have been allocated previously.
1780 The super class and the interfaces implemented by this class need not be
1781 loaded. The link is set later by the function 'class_link'.
1783 The loaded class is removed from the list 'unloadedclasses' and added to
1784 the list 'unlinkedclasses'.
1786 *******************************************************************************/
1788 classinfo *class_load_intern(classbuffer *cb);
1790 classinfo *class_load(classinfo *c)
1797 #if defined(USE_THREADS)
1798 #if defined(NATIVE_THREADS)
1806 /* maybe the class is already loaded */
1808 #if defined(USE_THREADS)
1809 #if defined(NATIVE_THREADS)
1822 starttime = getcputime();
1824 /* load classdata, throw exception on error */
1826 if ((cb = suck_start(c)) == NULL) {
1827 /* this means, the classpath was not set properly */
1828 if (c->name == utf_java_lang_Object)
1829 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1830 "java/lang/Object");
1833 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1836 #if defined(USE_THREADS)
1837 #if defined(NATIVE_THREADS)
1848 /* call the internal function */
1849 r = class_load_intern(cb);
1851 /* if return value is NULL, we had a problem and the class is not loaded */
1859 if (getloadingtime) {
1860 stoptime = getcputime();
1861 loadingtime += (stoptime - starttime);
1864 #if defined(USE_THREADS)
1865 #if defined(NATIVE_THREADS)
1877 classinfo *class_load_intern(classbuffer *cb)
1883 char msg[MAXLOGTEXT]; /* maybe we get an exception */
1885 /* get the classbuffer's class */
1888 /* maybe the class is already loaded */
1893 count_class_loads++;
1896 /* output for debugging purposes */
1898 log_message_class("Loading class: ", c);
1900 /* class is somewhat loaded */
1903 /* check signature */
1904 if (suck_u4(cb) != MAGIC) {
1905 utf_sprint_classname(msg, c->name);
1906 sprintf(msg + strlen(msg), " (Bad magic number)");
1909 new_exception_message(string_java_lang_ClassFormatError, msg);
1918 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION + 1 || mi != 0)) {
1919 utf_sprint_classname(msg, c->name);
1920 sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
1924 new_exception_message(string_java_lang_ClassFormatError,
1930 class_loadcpool(cb, c);
1932 c->erroneous_state = 0;
1933 c->initializing_thread = 0;
1935 c->classUsed = NOTUSED; /* not used initially CO-RT */
1939 c->flags = suck_u2(cb);
1940 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1942 /* check ACC flags consistency */
1943 if (c->flags & ACC_INTERFACE) {
1944 if (!(c->flags & ACC_ABSTRACT)) {
1945 /* We work around this because interfaces in JDK 1.1 are
1946 * not declared abstract. */
1948 c->flags |= ACC_ABSTRACT;
1949 /* panic("Interface class not declared abstract"); */
1952 if (c->flags & ACC_FINAL) {
1953 utf_sprint(msg, c->name);
1954 sprintf(msg + strlen(msg),
1955 " (Illegal class modifiers: 0x%x)", c->flags);
1958 new_exception_message(string_java_lang_ClassFormatError, msg);
1963 if (c->flags & ACC_SUPER) {
1964 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1968 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1969 utf_sprint(msg, c->name);
1970 sprintf(msg + strlen(msg),
1971 " (Illegal class modifiers: 0x%x)", c->flags);
1974 new_exception_message(string_java_lang_ClassFormatError, msg);
1981 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1982 utf_sprint(msg, c->name);
1983 sprintf(msg + strlen(msg), " (wrong name: ");
1984 utf_sprint(msg + strlen(msg),
1985 ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
1986 sprintf(msg + strlen(msg), ")");
1989 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1994 /* retrieve superclass */
1995 if ((i = suck_u2(cb))) {
1996 c->super = class_getconstant(c, i, CONSTANT_Class);
1998 /* java.lang.Object may not have a super class. */
1999 if (c->name == utf_java_lang_Object) {
2001 new_exception_message(string_java_lang_ClassFormatError,
2002 "java.lang.Object with superclass");
2007 /* Interfaces must have java.lang.Object as super class. */
2008 if ((c->flags & ACC_INTERFACE) &&
2009 c->super->name != utf_java_lang_Object) {
2011 new_exception_message(string_java_lang_ClassFormatError,
2012 "Interfaces must have java.lang.Object as superclass");
2020 /* This is only allowed for java.lang.Object. */
2021 if (c->name != utf_java_lang_Object) {
2022 utf_sprint(msg, c->name);
2023 sprintf(msg + strlen(msg), " (Bad superclass index)");
2026 new_exception_message(string_java_lang_ClassFormatError, msg);
2033 /* retrieve interfaces */
2034 c->interfacescount = suck_u2(cb);
2035 c->interfaces = MNEW(classinfo*, c->interfacescount);
2036 for (i = 0; i < c->interfacescount; i++) {
2038 class_getconstant(c, suck_u2(cb), CONSTANT_Class);
2042 c->fieldscount = suck_u2(cb);
2043 c->fields = GCNEW(fieldinfo, c->fieldscount);
2044 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2045 for (i = 0; i < c->fieldscount; i++) {
2046 if (!field_load(cb, c, &(c->fields[i])))
2051 c->methodscount = suck_u2(cb);
2052 c->methods = GCNEW(methodinfo, c->methodscount);
2053 /* c->methods = MNEW(methodinfo, c->methodscount); */
2054 for (i = 0; i < c->methodscount; i++) {
2055 if (!method_load(cb, c, &(c->methods[i])))
2059 /* Check if all fields and methods can be uniquely
2060 * identified by (name,descriptor). */
2062 /* We use a hash table here to avoid making the
2063 * average case quadratic in # of methods, fields.
2065 static int shift = 0;
2067 u2 *next; /* for chaining colliding hash entries */
2073 /* Allocate hashtable */
2074 len = c->methodscount;
2075 if (len < c->fieldscount) len = c->fieldscount;
2077 hashtab = MNEW(u2,(hashlen + len));
2078 next = hashtab + hashlen;
2080 /* Determine bitshift (to get good hash values) */
2090 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2091 for (i = 0; i < c->fieldscount; ++i) {
2092 fieldinfo *fi = c->fields + i;
2093 /* It's ok if we lose bits here */
2094 index = ((((size_t) fi->name) +
2095 ((size_t) fi->descriptor)) >> shift) % hashlen;
2096 if ((old = hashtab[index])) {
2100 if (c->fields[old].name == fi->name &&
2101 c->fields[old].descriptor == fi->descriptor) {
2102 utf_sprint(msg, c->name);
2103 sprintf(msg + strlen(msg), " (Repetitive field name/signature)");
2106 new_exception_message(string_java_lang_ClassFormatError,
2111 } while ((old = next[old]));
2113 hashtab[index] = i + 1;
2117 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2118 for (i = 0; i < c->methodscount; ++i) {
2119 methodinfo *mi = c->methods + i;
2120 /* It's ok if we lose bits here */
2121 index = ((((size_t) mi->name) +
2122 ((size_t) mi->descriptor)) >> shift) % hashlen;
2123 if ((old = hashtab[index])) {
2127 if (c->methods[old].name == mi->name &&
2128 c->methods[old].descriptor == mi->descriptor) {
2129 utf_sprint(msg, c->name);
2130 sprintf(msg + strlen(msg), " (Repetitive method name/signature)");
2133 new_exception_message(string_java_lang_ClassFormatError,
2138 } while ((old = next[old]));
2140 hashtab[index] = i + 1;
2143 MFREE(hashtab, u2, (hashlen + len));
2148 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2149 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2150 count_class_infos += sizeof(methodinfo) * c->methodscount;
2154 /* load variable-length attribute structures */
2155 attribute_load(cb, c, suck_u2(cb));
2158 /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
2160 /* check if all data has been read */
2161 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2163 if (classdata_left > 0) {
2165 dolog("There are %d extra bytes at end of classfile", classdata_left);
2166 /* The JVM spec disallows extra bytes. */
2167 panic("Extra bytes at end of classfile");
2172 log_message_class("Loading done class: ", c);
2179 /************** internal Function: class_highestinterface **********************
2181 Used by the function class_link to determine the amount of memory needed
2182 for the interface table.
2184 *******************************************************************************/
2186 static s4 class_highestinterface(classinfo *c)
2191 if (!(c->flags & ACC_INTERFACE)) {
2192 char logtext[MAXLOGTEXT];
2193 sprintf(logtext, "Interface-methods count requested for non-interface: ");
2194 utf_sprint(logtext + strlen(logtext), c->name);
2195 error("%s",logtext);
2199 for (i = 0; i < c->interfacescount; i++) {
2200 s4 h2 = class_highestinterface(c->interfaces[i]);
2208 /* class_addinterface **********************************************************
2210 Is needed by class_link for adding a VTBL to a class. All interfaces
2211 implemented by ic are added as well.
2213 *******************************************************************************/
2215 static void class_addinterface(classinfo *c, classinfo *ic)
2219 vftbl *vftbl = c->vftbl;
2221 if (i >= vftbl->interfacetablelength)
2222 panic ("Inernal error: interfacetable overflow");
2224 if (vftbl->interfacetable[-i])
2227 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
2228 vftbl->interfacevftbllength[i] = 1;
2229 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2230 vftbl->interfacetable[-i][0] = NULL;
2233 vftbl->interfacevftbllength[i] = ic->methodscount;
2234 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2238 count_vftbl_len += sizeof(methodptr) *
2239 (ic->methodscount + (ic->methodscount == 0));
2242 for (j = 0; j < ic->methodscount; j++) {
2245 for (m = 0; m < sc->methodscount; m++) {
2246 methodinfo *mi = &(sc->methods[m]);
2247 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2248 vftbl->interfacetable[-i][j] =
2249 vftbl->table[mi->vftblindex];
2260 for (j = 0; j < ic->interfacescount; j++)
2261 class_addinterface(c, ic->interfaces[j]);
2265 /******************* Function: class_new_array *********************************
2267 This function is called by class_new to setup an array class.
2269 *******************************************************************************/
2271 void class_new_array(classinfo *c)
2273 classinfo *comp = NULL;
2277 /* Check array class name */
2278 namelen = c->name->blength;
2279 if (namelen < 2 || c->name->text[0] != '[')
2280 panic("Invalid array class name");
2282 /* Check the component type */
2283 switch (c->name->text[1]) {
2285 /* c is an array of arrays. We have to create the component class. */
2286 comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
2290 /* c is an array of objects. */
2291 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2292 panic("Invalid array class name");
2293 comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
2297 /* Setup the array class */
2298 c->super = class_java_lang_Object;
2299 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2301 c->interfacescount = 2;
2302 c->interfaces = MNEW(classinfo*, 2);
2303 c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
2304 c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
2306 c->methodscount = 1;
2307 c->methods = MNEW(methodinfo, c->methodscount);
2310 memset(clone, 0, sizeof(methodinfo));
2311 clone->flags = ACC_PUBLIC;
2312 clone->name = utf_new_char("clone");
2313 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2315 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2316 clone->monoPoly = MONO;
2318 /* XXX: field: length? */
2320 /* array classes are not loaded from class files */
2325 /****************** Function: class_link_array *********************************
2327 This function is called by class_link to create the
2328 arraydescriptor for an array class.
2330 This function returns NULL if the array cannot be linked because
2331 the component type has not been linked yet.
2333 *******************************************************************************/
2335 static arraydescriptor *class_link_array(classinfo *c)
2337 classinfo *comp = NULL;
2338 s4 namelen = c->name->blength;
2339 arraydescriptor *desc;
2342 /* Check the component type */
2343 switch (c->name->text[1]) {
2345 /* c is an array of arrays. */
2346 /* comp = class_get(utf_new_int(c->name->text + 1, namelen - 1)); */
2347 comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
2349 panic("Could not find component array class.");
2353 /* c is an array of objects. */
2354 /* comp = class_get(utf_new_int(c->name->text + 2, namelen - 3)); */
2355 comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
2357 panic("Could not find component class.");
2361 /* If the component type has not been linked, link it now */
2362 if (comp && !comp->linked) {
2368 /* Allocate the arraydescriptor */
2369 desc = NEW(arraydescriptor);
2372 /* c is an array of references */
2373 desc->arraytype = ARRAYTYPE_OBJECT;
2374 desc->componentsize = sizeof(void*);
2375 desc->dataoffset = OFFSET(java_objectarray, data);
2377 compvftbl = comp->vftbl;
2379 panic("Component class has no vftbl");
2380 desc->componentvftbl = compvftbl;
2382 if (compvftbl->arraydesc) {
2383 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2384 if (compvftbl->arraydesc->dimension >= 255)
2385 panic("Creating array of dimension >255");
2386 desc->dimension = compvftbl->arraydesc->dimension + 1;
2387 desc->elementtype = compvftbl->arraydesc->elementtype;
2390 desc->elementvftbl = compvftbl;
2391 desc->dimension = 1;
2392 desc->elementtype = ARRAYTYPE_OBJECT;
2396 /* c is an array of a primitive type */
2397 switch (c->name->text[1]) {
2399 desc->arraytype = ARRAYTYPE_BOOLEAN;
2400 desc->dataoffset = OFFSET(java_booleanarray,data);
2401 desc->componentsize = sizeof(u1);
2405 desc->arraytype = ARRAYTYPE_BYTE;
2406 desc->dataoffset = OFFSET(java_bytearray,data);
2407 desc->componentsize = sizeof(u1);
2411 desc->arraytype = ARRAYTYPE_CHAR;
2412 desc->dataoffset = OFFSET(java_chararray,data);
2413 desc->componentsize = sizeof(u2);
2417 desc->arraytype = ARRAYTYPE_DOUBLE;
2418 desc->dataoffset = OFFSET(java_doublearray,data);
2419 desc->componentsize = sizeof(double);
2423 desc->arraytype = ARRAYTYPE_FLOAT;
2424 desc->dataoffset = OFFSET(java_floatarray,data);
2425 desc->componentsize = sizeof(float);
2429 desc->arraytype = ARRAYTYPE_INT;
2430 desc->dataoffset = OFFSET(java_intarray,data);
2431 desc->componentsize = sizeof(s4);
2435 desc->arraytype = ARRAYTYPE_LONG;
2436 desc->dataoffset = OFFSET(java_longarray,data);
2437 desc->componentsize = sizeof(s8);
2441 desc->arraytype = ARRAYTYPE_SHORT;
2442 desc->dataoffset = OFFSET(java_shortarray,data);
2443 desc->componentsize = sizeof(s2);
2447 panic("Invalid array class name");
2450 desc->componentvftbl = NULL;
2451 desc->elementvftbl = NULL;
2452 desc->dimension = 1;
2453 desc->elementtype = desc->arraytype;
2460 /********************** Function: class_link ***********************************
2462 Tries to link a class. The function calculates the length in bytes that
2463 an instance of this class requires as well as the VTBL for methods and
2466 *******************************************************************************/
2468 static classinfo *class_link_intern(classinfo *c);
2470 classinfo *class_link(classinfo *c)
2476 #if defined(USE_THREADS)
2477 #if defined(NATIVE_THREADS)
2485 /* maybe the class is already linked */
2487 #if defined(USE_THREADS)
2488 #if defined(NATIVE_THREADS)
2501 starttime = getcputime();
2503 /* call the internal function */
2504 r = class_link_intern(c);
2506 /* if return value is NULL, we had a problem and the class is not linked */
2511 if (getloadingtime) {
2512 stoptime = getcputime();
2513 loadingtime += (stoptime - starttime);
2516 #if defined(USE_THREADS)
2517 #if defined(NATIVE_THREADS)
2524 if (c->linked) return c; else return 0;
2528 static classinfo *class_link_intern(classinfo *c)
2530 s4 supervftbllength; /* vftbllegnth of super class */
2531 s4 vftbllength; /* vftbllength of current class */
2532 s4 interfacetablelength; /* interface table length */
2533 classinfo *super = c->super; /* super class */
2534 classinfo *ic, *c2; /* intermediate class variables */
2535 vftbl *v; /* vftbl of current class */
2536 s4 i; /* interface/method/field counter */
2537 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2539 /* maybe the class is already linked */
2544 log_message_class("Linking class: ", c);
2546 /* ok, this class is somewhat linked */
2549 /* check interfaces */
2551 for (i = 0; i < c->interfacescount; i++) {
2552 ic = c->interfaces[i];
2554 /* detect circularity */
2557 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2569 if (!(ic->flags & ACC_INTERFACE)) {
2570 dolog("Specified interface is not declared as interface:");
2574 panic("Specified interface is not declared as interface");
2578 /* check super class */
2580 if (super == NULL) { /* class java.lang.Object */
2582 c->classUsed = USED; /* Object class is always used CO-RT*/
2584 c->instancesize = sizeof(java_objectheader);
2586 vftbllength = supervftbllength = 0;
2588 c->finalizer = NULL;
2591 /* detect circularity */
2594 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2606 if (super->flags & ACC_INTERFACE)
2607 panic("Interface specified as super class");
2609 /* handle array classes */
2610 /* The component class must have been linked already. */
2611 if (c->name->text[0] == '[') {
2612 if ((arraydesc = class_link_array(c)) == NULL) {
2613 panic("class_link: class_link_array");
2617 /* Don't allow extending final classes */
2618 if (super->flags & ACC_FINAL)
2619 panic("Trying to extend final class");
2621 if (c->flags & ACC_INTERFACE)
2622 c->index = interfaceindex++;
2624 c->index = super->index + 1;
2626 c->instancesize = super->instancesize;
2628 vftbllength = supervftbllength = super->vftbl->vftbllength;
2630 c->finalizer = super->finalizer;
2633 /* compute vftbl length */
2635 for (i = 0; i < c->methodscount; i++) {
2636 methodinfo *m = &(c->methods[i]);
2638 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2639 classinfo *sc = super;
2642 for (j = 0; j < sc->methodscount; j++) {
2643 if (method_canoverwrite(m, &(sc->methods[j]))) {
2644 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2645 goto notfoundvftblindex;
2647 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2650 log_utf(sc->methods[j].name);
2651 log_utf(sc->methods[j].descriptor);
2652 panic("Trying to overwrite final method");
2654 m->vftblindex = sc->methods[j].vftblindex;
2655 goto foundvftblindex;
2661 m->vftblindex = (vftbllength++);
2670 sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2673 /* compute interfacetable length */
2675 interfacetablelength = 0;
2678 for (i = 0; i < c2->interfacescount; i++) {
2679 s4 h = class_highestinterface(c2->interfaces[i]) + 1;
2680 if (h > interfacetablelength)
2681 interfacetablelength = h;
2686 /* allocate virtual function table */
2688 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2689 (vftbllength - 1) + sizeof(methodptr*) *
2690 (interfacetablelength - (interfacetablelength > 0)));
2691 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2692 (interfacetablelength > 1));
2693 c->header.vftbl = c->vftbl = v;
2694 /* utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
2696 v->vftbllength = vftbllength;
2697 v->interfacetablelength = interfacetablelength;
2698 v->arraydesc = arraydesc;
2700 /* store interface index in vftbl */
2701 if (c->flags & ACC_INTERFACE)
2702 v->baseval = -(c->index);
2704 /* copy virtual function table of super class */
2706 for (i = 0; i < supervftbllength; i++)
2707 v->table[i] = super->vftbl->table[i];
2709 /* add method stubs into virtual function table */
2711 for (i = 0; i < c->methodscount; i++) {
2712 methodinfo *m = &(c->methods[i]);
2713 if (!(m->flags & ACC_STATIC)) {
2714 v->table[m->vftblindex] = m->stubroutine;
2718 /* compute instance size and offset of each field */
2720 for (i = 0; i < c->fieldscount; i++) {
2722 fieldinfo *f = &(c->fields[i]);
2724 if (!(f->flags & ACC_STATIC)) {
2725 dsize = desc_typesize(f->descriptor);
2726 c->instancesize = ALIGN(c->instancesize, dsize);
2727 f->offset = c->instancesize;
2728 c->instancesize += dsize;
2732 /* initialize interfacetable and interfacevftbllength */
2734 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2738 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2741 for (i = 0; i < interfacetablelength; i++) {
2742 v->interfacevftbllength[i] = 0;
2743 v->interfacetable[-i] = NULL;
2746 /* add interfaces */
2748 for (c2 = c; c2 != NULL; c2 = c2->super)
2749 for (i = 0; i < c2->interfacescount; i++) {
2750 class_addinterface(c, c2->interfaces[i]);
2753 /* add finalizer method (not for java.lang.Object) */
2755 if (super != NULL) {
2757 static utf *finame = NULL;
2758 static utf *fidesc = NULL;
2761 finame = utf_finalize;
2763 fidesc = utf_fidesc;
2765 fi = class_findmethod(c, finame, fidesc);
2767 if (!(fi->flags & ACC_STATIC)) {
2775 loader_compute_subclasses(c);
2778 log_message_class("Linking done class: ", c);
2780 /* just return c to show that we didn't had a problem */
2786 /******************* Function: class_freepool **********************************
2788 Frees all resources used by this classes Constant Pool.
2790 *******************************************************************************/
2792 static void class_freecpool(classinfo *c)
2798 for (idx=0; idx < c->cpcount; idx++) {
2799 tag = c->cptags[idx];
2800 info = c->cpinfos[idx];
2804 case CONSTANT_Fieldref:
2805 case CONSTANT_Methodref:
2806 case CONSTANT_InterfaceMethodref:
2807 FREE(info, constant_FMIref);
2809 case CONSTANT_Integer:
2810 FREE(info, constant_integer);
2812 case CONSTANT_Float:
2813 FREE(info, constant_float);
2816 FREE(info, constant_long);
2818 case CONSTANT_Double:
2819 FREE(info, constant_double);
2821 case CONSTANT_NameAndType:
2822 FREE(info, constant_nameandtype);
2828 MFREE(c->cptags, u1, c->cpcount);
2829 MFREE(c->cpinfos, voidptr, c->cpcount);
2833 /*********************** Function: class_free **********************************
2835 Frees all resources used by the class.
2837 *******************************************************************************/
2839 static void class_free(classinfo *c)
2846 MFREE(c->interfaces, classinfo*, c->interfacescount);
2848 for (i = 0; i < c->fieldscount; i++)
2849 field_free(&(c->fields[i]));
2851 for (i = 0; i < c->methodscount; i++)
2852 method_free(&(c->methods[i]));
2853 MFREE(c->methods, methodinfo, c->methodscount);
2855 if ((v = c->vftbl) != NULL) {
2857 mem_free(v->arraydesc,sizeof(arraydescriptor));
2859 for (i = 0; i < v->interfacetablelength; i++) {
2860 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2862 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2864 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2865 sizeof(methodptr*) * (v->interfacetablelength -
2866 (v->interfacetablelength > 0));
2867 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2868 (v->interfacetablelength > 1));
2872 if (c->innerclasscount)
2873 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2875 /* if (c->classvftbl)
2876 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2882 /************************* Function: class_findfield ***************************
2884 Searches a 'classinfo' structure for a field having the given name and
2887 *******************************************************************************/
2889 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2893 for (i = 0; i < c->fieldscount; i++) {
2894 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2895 return &(c->fields[i]);
2898 panic("Can not find field given in CONSTANT_Fieldref");
2900 /* keep compiler happy */
2905 /****************** Function: class_resolvefield_int ***************************
2907 This is an internally used helper function. Do not use this directly.
2909 Tries to resolve a field having the given name and type.
2910 If the field cannot be resolved, NULL is returned.
2912 *******************************************************************************/
2914 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2919 /* search for field in class c */
2920 for (i = 0; i < c->fieldscount; i++) {
2921 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2922 return &(c->fields[i]);
2926 /* try superinterfaces recursively */
2927 for (i = 0; i < c->interfacescount; ++i) {
2928 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2933 /* try superclass */
2935 return class_resolvefield_int(c->super, name, desc);
2942 /********************* Function: class_resolvefield ***************************
2944 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2946 If the field cannot be resolved the return value is NULL. If EXCEPT is
2947 true *exceptionptr is set, too.
2949 *******************************************************************************/
2951 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2952 classinfo *referer, bool except)
2956 /* XXX resolve class c */
2957 /* XXX check access from REFERER to C */
2959 fi = class_resolvefield_int(c, name, desc);
2964 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2970 /* XXX check access rights */
2976 /************************* Function: class_findmethod **************************
2978 Searches a 'classinfo' structure for a method having the given name and
2979 type and returns the index in the class info structure.
2980 If type is NULL, it is ignored.
2982 *******************************************************************************/
2984 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2988 for (i = 0; i < c->methodscount; i++) {
2990 /* utf_display_classname(c->name);printf("."); */
2991 /* utf_display(c->methods[i].name);printf("."); */
2992 /* utf_display(c->methods[i].descriptor); */
2995 if ((c->methods[i].name == name) && ((desc == NULL) ||
2996 (c->methods[i].descriptor == desc))) {
3005 /************************* Function: class_findmethod **************************
3007 Searches a 'classinfo' structure for a method having the given name and
3009 If type is NULL, it is ignored.
3011 *******************************************************************************/
3013 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3015 s4 idx = class_findmethodIndex(c, name, desc);
3020 return &(c->methods[idx]);
3024 /*********************** Function: class_fetchmethod **************************
3026 like class_findmethod, but aborts with an error if the method is not found
3028 *******************************************************************************/
3030 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3034 mi = class_findmethod(c, name, desc);
3037 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3038 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3039 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3040 panic("Method not found");
3047 /*********************** Function: class_findmethod_w**************************
3049 like class_findmethod, but logs a warning if the method is not found
3051 *******************************************************************************/
3053 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
3056 mi = class_findmethod(c, name, desc);
3059 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3060 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3061 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3063 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
3064 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
3065 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
3066 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
3067 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
3068 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
3069 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
3070 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
3071 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
3072 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
3073 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
3076 log_plain(" : WARNING: Method not found");log_nl( );
3083 /************************* Function: class_findmethod_approx ******************
3085 like class_findmethod but ignores the return value when comparing the
3088 *******************************************************************************/
3090 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3094 for (i = 0; i < c->methodscount; i++) {
3095 if (c->methods[i].name == name) {
3096 utf *meth_descr = c->methods[i].descriptor;
3100 return &(c->methods[i]);
3102 if (desc->blength <= meth_descr->blength) {
3103 /* current position in utf text */
3104 char *desc_utf_ptr = desc->text;
3105 char *meth_utf_ptr = meth_descr->text;
3106 /* points behind utf strings */
3107 char *desc_end = utf_end(desc);
3108 char *meth_end = utf_end(meth_descr);
3111 /* compare argument types */
3112 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3114 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3115 break; /* no match */
3118 return &(c->methods[i]); /* all parameter types equal */
3128 /***************** Function: class_resolvemethod_approx ***********************
3130 Searches a class and every super class for a method (without paying
3131 attention to the return value)
3133 *******************************************************************************/
3135 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3138 /* search for method (ignore returntype) */
3139 methodinfo *m = class_findmethod_approx(c, name, desc);
3142 /* search superclass */
3150 /************************* Function: class_resolvemethod ***********************
3152 Searches a class and every super class for a method.
3154 *******************************************************************************/
3156 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3159 methodinfo *m = class_findmethod(c, name, desc);
3161 /* search superclass */
3169 /****************** Function: class_resolveinterfacemethod_int ****************
3171 Internally used helper function. Do not use this directly.
3173 *******************************************************************************/
3176 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
3181 mi = class_findmethod(c,name,desc);
3185 /* try the superinterfaces */
3186 for (i=0; i<c->interfacescount; ++i) {
3187 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3195 /******************** Function: class_resolveinterfacemethod ******************
3197 Resolves a reference from REFERER to a method with NAME and DESC in
3200 If the method cannot be resolved the return value is NULL. If EXCEPT is
3201 true *exceptionptr is set, too.
3203 *******************************************************************************/
3205 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3206 classinfo *referer, bool except)
3210 /* XXX resolve class c */
3211 /* XXX check access from REFERER to C */
3213 if (!(c->flags & ACC_INTERFACE)) {
3216 new_exception(string_java_lang_IncompatibleClassChangeError);
3221 mi = class_resolveinterfacemethod_int(c, name, desc);
3226 /* try class java.lang.Object */
3227 mi = class_findmethod(class_java_lang_Object, name, desc);
3234 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3240 /********************* Function: class_resolveclassmethod *********************
3242 Resolves a reference from REFERER to a method with NAME and DESC in
3245 If the method cannot be resolved the return value is NULL. If EXCEPT is
3246 true *exceptionptr is set, too.
3248 *******************************************************************************/
3250 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3251 classinfo *referer, bool except)
3256 char msg[MAXLOGTEXT];
3258 /* XXX resolve class c */
3259 /* XXX check access from REFERER to C */
3261 /* if (c->flags & ACC_INTERFACE) { */
3263 /* *exceptionptr = */
3264 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3268 /* try class c and its superclasses */
3271 mi = class_findmethod(cls, name, desc);
3274 } while ((cls = cls->super) != NULL); /* try the superclass */
3276 /* try the superinterfaces */
3277 for (i = 0; i < c->interfacescount; ++i) {
3278 mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
3284 utf_sprint(msg, c->name);
3285 sprintf(msg + strlen(msg), ".");
3286 utf_sprint(msg + strlen(msg), name);
3287 utf_sprint(msg + strlen(msg), desc);
3290 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3296 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3298 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3303 /* XXX check access rights */
3309 /************************* Function: class_issubclass **************************
3311 Checks if sub is a descendant of super.
3313 *******************************************************************************/
3315 bool class_issubclass(classinfo *sub, classinfo *super)
3318 if (!sub) return false;
3319 if (sub == super) return true;
3325 /****************** Initialization function for classes ******************
3327 In Java, every class can have a static initialization function. This
3328 function has to be called BEFORE calling other methods or accessing static
3331 *******************************************************************************/
3333 classinfo *class_init(classinfo *c)
3337 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3341 if (!makeinitializations)
3347 /* class is somewhat initialized */
3348 c->initialized = true;
3358 #if defined(STATISTICS)
3360 count_class_inits++;
3363 /* initialize super class */
3365 if (!c->super->loaded)
3366 if (!class_load(c->super))
3369 if (!c->super->linked)
3370 if (!class_link(c->super))
3373 if (!c->super->initialized) {
3375 char logtext[MAXLOGTEXT];
3376 sprintf(logtext, "Initialize super class ");
3377 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3378 sprintf(logtext + strlen(logtext), " from ");
3379 utf_sprint_classname(logtext + strlen(logtext), c->name);
3383 if (!class_init(c->super))
3388 /* initialize interface classes */
3389 for (i = 0; i < c->interfacescount; i++) {
3390 if (!c->interfaces[i]->loaded)
3391 if (!class_load(c->interfaces[i]))
3394 if (!c->interfaces[i]->linked)
3395 if (!class_link(c->interfaces[i]))
3398 if (!c->interfaces[i]->initialized) {
3400 char logtext[MAXLOGTEXT];
3401 sprintf(logtext, "Initialize interface class ");
3402 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3403 sprintf(logtext + strlen(logtext), " from ");
3404 utf_sprint_classname(logtext + strlen(logtext), c->name);
3408 if (!class_init(c->interfaces[i]))
3413 m = class_findmethod(c, utf_clinit, utf_fidesc);
3417 char logtext[MAXLOGTEXT];
3418 sprintf(logtext, "Class ");
3419 utf_sprint_classname(logtext + strlen(logtext), c->name);
3420 sprintf(logtext + strlen(logtext), " has no static class initializer");
3427 if (!(m->flags & ACC_STATIC))
3428 panic("Class initializer is not static!");
3431 log_message_class("Starting static class initializer for class: ", c);
3433 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3438 /* now call the initializer */
3439 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3441 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3442 assert(blockInts == 0);
3446 /* we have an exception */
3447 if (*exceptionptr) {
3448 java_objectheader *xptr;
3449 java_objectheader *cause;
3451 /* class is NOT initialized */
3452 c->initialized = false;
3455 cause = *exceptionptr;
3457 /* clear exception, because we are calling jit code again */
3458 *exceptionptr = NULL;
3460 /* wrap the exception */
3462 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3463 (java_lang_Throwable *) cause);
3465 if (*exceptionptr) {
3469 /* set new exception */
3470 *exceptionptr = xptr;
3476 log_message_class("Finished static class initializer for class: ", c);
3482 /********* Function: find_class_method_constant *********/
3484 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3489 for (i=0; i<c->cpcount; i++) {
3491 e = c -> cpinfos [i];
3494 switch (c -> cptags [i]) {
3495 case CONSTANT_Methodref:
3497 constant_FMIref *fmi = e;
3498 if ( (fmi->class->name == c1)
3499 && (fmi->name == m1)
3500 && (fmi->descriptor == d1)) {
3507 case CONSTANT_InterfaceMethodref:
3509 constant_FMIref *fmi = e;
3510 if ( (fmi->class->name == c1)
3511 && (fmi->name == m1)
3512 && (fmi->descriptor == d1)) {
3526 void class_showconstanti(classinfo *c, int ii)
3532 printf ("#%d: ", (int) i);
3534 switch (c->cptags [i]) {
3535 case CONSTANT_Class:
3536 printf("Classreference -> ");
3537 utf_display(((classinfo*)e)->name);
3540 case CONSTANT_Fieldref:
3541 printf("Fieldref -> "); goto displayFMIi;
3542 case CONSTANT_Methodref:
3543 printf("Methodref -> "); goto displayFMIi;
3544 case CONSTANT_InterfaceMethodref:
3545 printf("InterfaceMethod -> "); goto displayFMIi;
3548 constant_FMIref *fmi = e;
3549 utf_display(fmi->class->name);
3551 utf_display(fmi->name);
3553 utf_display(fmi->descriptor);
3557 case CONSTANT_String:
3558 printf("String -> ");
3561 case CONSTANT_Integer:
3562 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3564 case CONSTANT_Float:
3565 printf("Float -> %f", ((constant_float*)e)->value);
3567 case CONSTANT_Double:
3568 printf("Double -> %f", ((constant_double*)e)->value);
3572 u8 v = ((constant_long*)e)->value;
3574 printf("Long -> %ld", (long int) v);
3576 printf("Long -> HI: %ld, LO: %ld\n",
3577 (long int) v.high, (long int) v.low);
3581 case CONSTANT_NameAndType:
3583 constant_nameandtype *cnt = e;
3584 printf("NameAndType: ");
3585 utf_display(cnt->name);
3587 utf_display(cnt->descriptor);
3595 panic("Invalid type of ConstantPool-Entry");
3602 void class_showconstantpool (classinfo *c)
3607 printf ("---- dump of constant pool ----\n");
3609 for (i=0; i<c->cpcount; i++) {
3610 printf ("#%d: ", (int) i);
3612 e = c -> cpinfos [i];
3615 switch (c -> cptags [i]) {
3616 case CONSTANT_Class:
3617 printf ("Classreference -> ");
3618 utf_display ( ((classinfo*)e) -> name );
3621 case CONSTANT_Fieldref:
3622 printf ("Fieldref -> "); goto displayFMI;
3623 case CONSTANT_Methodref:
3624 printf ("Methodref -> "); goto displayFMI;
3625 case CONSTANT_InterfaceMethodref:
3626 printf ("InterfaceMethod -> "); goto displayFMI;
3629 constant_FMIref *fmi = e;
3630 utf_display ( fmi->class->name );
3632 utf_display ( fmi->name);
3634 utf_display ( fmi->descriptor );
3638 case CONSTANT_String:
3639 printf ("String -> ");
3642 case CONSTANT_Integer:
3643 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3645 case CONSTANT_Float:
3646 printf ("Float -> %f", ((constant_float*)e) -> value);
3648 case CONSTANT_Double:
3649 printf ("Double -> %f", ((constant_double*)e) -> value);
3653 u8 v = ((constant_long*)e) -> value;
3655 printf ("Long -> %ld", (long int) v);
3657 printf ("Long -> HI: %ld, LO: %ld\n",
3658 (long int) v.high, (long int) v.low);
3662 case CONSTANT_NameAndType:
3664 constant_nameandtype *cnt = e;
3665 printf ("NameAndType: ");
3666 utf_display (cnt->name);
3668 utf_display (cnt->descriptor);
3672 printf ("Utf8 -> ");
3676 panic ("Invalid type of ConstantPool-Entry");
3686 /********** Function: class_showmethods (debugging only) *************/
3688 void class_showmethods (classinfo *c)
3692 printf ("--------- Fields and Methods ----------------\n");
3693 printf ("Flags: "); printflags (c->flags); printf ("\n");
3695 printf ("This: "); utf_display (c->name); printf ("\n");
3697 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3699 printf ("Index: %d\n", c->index);
3701 printf ("interfaces:\n");
3702 for (i=0; i < c-> interfacescount; i++) {
3704 utf_display (c -> interfaces[i] -> name);
3705 printf (" (%d)\n", c->interfaces[i] -> index);
3708 printf ("fields:\n");
3709 for (i=0; i < c -> fieldscount; i++) {
3710 field_display (&(c -> fields[i]));
3713 printf ("methods:\n");
3714 for (i=0; i < c -> methodscount; i++) {
3715 methodinfo *m = &(c->methods[i]);
3716 if ( !(m->flags & ACC_STATIC))
3717 printf ("vftblindex: %d ", m->vftblindex);
3719 method_display ( m );
3723 printf ("Virtual function table:\n");
3724 for (i=0; i<c->vftbl->vftbllength; i++) {
3725 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3731 /******************************************************************************/
3732 /******************* General functions for the class loader *******************/
3733 /******************************************************************************/
3735 /**************** function: create_primitive_classes ***************************
3737 create classes representing primitive types
3739 *******************************************************************************/
3741 void create_primitive_classes()
3745 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
3746 /* create primitive class */
3747 classinfo *c = class_new_int(utf_new_char(primitivetype_table[i].name));
3748 c->classUsed = NOTUSED; /* not used initially CO-RT */
3751 /* prevent loader from loading primitive class */
3755 primitivetype_table[i].class_primitive = c;
3757 /* create class for wrapping the primitive type */
3758 c = class_new_int(utf_new_char(primitivetype_table[i].wrapname));
3759 primitivetype_table[i].class_wrap = c;
3760 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
3761 primitivetype_table[i].class_wrap->impldBy = NULL;
3763 /* create the primitive array class */
3764 if (primitivetype_table[i].arrayname) {
3765 c = class_new_int(utf_new_char(primitivetype_table[i].arrayname));
3766 primitivetype_table[i].arrayclass = c;
3770 primitivetype_table[i].arrayvftbl = c->vftbl;
3776 /**************** function: class_primitive_from_sig ***************************
3778 return the primitive class indicated by the given signature character
3780 If the descriptor does not indicate a valid primitive type the
3781 return value is NULL.
3783 ********************************************************************************/
3785 classinfo *class_primitive_from_sig(char sig)
3788 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3789 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3790 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3791 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3792 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3793 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3794 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3795 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3796 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3801 /****************** function: class_from_descriptor ****************************
3803 return the class indicated by the given descriptor
3805 utf_ptr....first character of descriptor
3806 end_ptr....first character after the end of the string
3807 next.......if non-NULL, *next is set to the first character after
3808 the descriptor. (Undefined if an error occurs.)
3810 mode.......a combination (binary or) of the following flags:
3812 (Flags marked with * are the default settings.)
3814 What to do if a reference type descriptor is parsed successfully:
3816 CLASSLOAD_SKIP...skip it and return something != NULL
3817 * CLASSLOAD_NEW....get classinfo * via class_new
3818 CLASSLOAD_LOAD...get classinfo * via loader_load
3820 How to handle primitive types:
3822 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3823 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3825 How to handle "V" descriptors:
3827 * CLASSLOAD_VOID.....handle it like other primitive types
3828 CLASSLOAD_NOVOID...treat it as an error
3830 How to deal with extra characters after the end of the
3833 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3834 CLASSLOAD_CHECKEND.....treat them as an error
3836 How to deal with errors:
3838 * CLASSLOAD_PANIC....abort execution with an error message
3839 CLASSLOAD_NOPANIC..return NULL on error
3841 ********************************************************************************/
3843 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3844 char **next, int mode)
3846 char *start = utf_ptr;
3850 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3852 if (mode & CLASSLOAD_CHECKEND)
3853 error |= (utf_ptr != end_ptr);
3856 if (next) *next = utf_ptr;
3860 if (mode & CLASSLOAD_NOVOID)
3871 return (mode & CLASSLOAD_NULLPRIMITIVE)
3873 : class_primitive_from_sig(*start);
3880 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3881 name = utf_new(start, utf_ptr - start);
3882 return (mode & CLASSLOAD_LOAD)
3883 ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
3887 /* An error occurred */
3888 if (mode & CLASSLOAD_NOPANIC)
3891 log_plain("Invalid descriptor at beginning of '");
3892 log_plain_utf(utf_new(start, end_ptr - start));
3896 panic("Invalid descriptor");
3898 /* keep compiler happy */
3903 /******************* function: type_from_descriptor ****************************
3905 return the basic type indicated by the given descriptor
3907 This function parses a descriptor and returns its basic type as
3908 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3910 cls...if non-NULL the referenced variable is set to the classinfo *
3911 returned by class_from_descriptor.
3913 For documentation of the arguments utf_ptr, end_ptr, next and mode
3914 see class_from_descriptor. The only difference is that
3915 type_from_descriptor always uses CLASSLOAD_PANIC.
3917 ********************************************************************************/
3919 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3920 char **next, int mode)
3923 if (!cls) cls = &mycls;
3924 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3941 return TYPE_ADDRESS;
3945 /*************** function: create_pseudo_classes *******************************
3947 create pseudo classes used by the typechecker
3949 ********************************************************************************/
3951 static void create_pseudo_classes()
3953 /* pseudo class for Arraystubs (extends java.lang.Object) */
3955 pseudo_class_Arraystub = class_new_int(utf_new_char("$ARRAYSTUB$"));
3956 pseudo_class_Arraystub->loaded = true;
3957 pseudo_class_Arraystub->super = class_java_lang_Object;
3958 pseudo_class_Arraystub->interfacescount = 2;
3959 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3960 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3961 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3963 class_link(pseudo_class_Arraystub);
3965 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3967 /* pseudo class representing the null type */
3969 pseudo_class_Null = class_new_int(utf_new_char("$NULL$"));
3970 pseudo_class_Null->loaded = true;
3971 pseudo_class_Null->super = class_java_lang_Object;
3972 class_link(pseudo_class_Null);
3974 /* pseudo class representing new uninitialized objects */
3976 pseudo_class_New = class_new_int(utf_new_char("$NEW$"));
3977 pseudo_class_New->loaded = true;
3978 pseudo_class_New->linked = true;
3979 pseudo_class_New->super = class_java_lang_Object;
3980 /* class_link(pseudo_class_New); */
3984 /********************** Function: loader_init **********************************
3986 Initializes all lists and loads all classes required for the system or the
3989 *******************************************************************************/
3991 void loader_init(u1 *stackbottom)
3995 /* create utf-symbols for pointer comparison of frequently used strings */
3996 utf_innerclasses = utf_new_char("InnerClasses");
3997 utf_constantvalue = utf_new_char("ConstantValue");
3998 utf_code = utf_new_char("Code");
3999 utf_exceptions = utf_new_char("Exceptions");
4000 utf_linenumbertable = utf_new_char("LineNumberTable");
4001 utf_sourcefile = utf_new_char("SourceFile");
4002 utf_finalize = utf_new_char("finalize");
4003 utf_fidesc = utf_new_char("()V");
4004 utf_init = utf_new_char("<init>");
4005 utf_clinit = utf_new_char("<clinit>");
4006 utf_initsystemclass = utf_new_char("initializeSystemClass");
4007 utf_systemclass = utf_new_char("java/lang/System");
4008 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
4009 utf_initialize = utf_new_char("initialize");
4010 utf_initializedesc = utf_new_char("(I)V");
4011 utf_vmclass = utf_new_char("java/lang/VMClass");
4012 utf_java_lang_Object= utf_new_char("java/lang/Object");
4013 array_packagename = utf_new_char("<the array package>");
4015 /* create some important classes */
4016 /* These classes have to be created now because the classinfo
4017 * pointers are used in the loading code.
4019 class_java_lang_Object =
4020 class_new_int(utf_java_lang_Object);
4021 class_load(class_java_lang_Object);
4022 class_link(class_java_lang_Object);
4024 class_java_lang_String =
4025 class_new_int(utf_new_char("java/lang/String"));
4026 class_load(class_java_lang_String);
4027 class_link(class_java_lang_String);
4029 class_java_lang_Cloneable =
4030 class_new_int(utf_new_char("java/lang/Cloneable"));
4031 class_load(class_java_lang_Cloneable);
4032 class_link(class_java_lang_Cloneable);
4034 class_java_io_Serializable =
4035 class_new_int(utf_new_char("java/io/Serializable"));
4036 class_load(class_java_io_Serializable);
4037 class_link(class_java_io_Serializable);
4039 /* create classes representing primitive types */
4040 create_primitive_classes();
4042 /* create classes used by the typechecker */
4043 create_pseudo_classes();
4045 /* correct vftbl-entries (retarded loading of class java/lang/String) */
4046 stringtable_update();
4048 #if defined(USE_THREADS)
4049 if (stackbottom != 0)
4055 static void loader_compute_class_values(classinfo *c)
4059 c->vftbl->baseval = ++classvalue;
4062 while (subs != NULL) {
4063 loader_compute_class_values(subs);
4064 subs = subs->nextsub;
4067 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4071 void loader_compute_subclasses(classinfo *c)
4073 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4077 if (!(c->flags & ACC_INTERFACE)) {
4082 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4083 c->nextsub = c->super->sub;
4089 /* this is the java.lang.Object special case */
4090 if (!class_java_lang_Object) {
4091 loader_compute_class_values(c);
4094 loader_compute_class_values(class_java_lang_Object);
4097 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4103 /******************** Function: loader_close ***********************************
4107 *******************************************************************************/
4113 /* while ((c = list_first(&unloadedclasses))) { */
4114 /* list_remove(&unloadedclasses, c); */
4115 /* class_free(c); */
4117 /* while ((c = list_first(&unlinkedclasses))) { */
4118 /* list_remove(&unlinkedclasses, c); */
4119 /* class_free(c); */
4121 /* while ((c = list_first(&linkedclasses))) { */
4122 /* list_remove(&linkedclasses, c); */
4123 /* class_free(c); */
4129 * These are local overrides for various environment variables in Emacs.
4130 * Please do not remove this and leave it at the end of the file, where
4131 * Emacs will automagically detect them.
4132 * ---------------------------------------------------------------------
4135 * indent-tabs-mode: t