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 1096 2004-05-27 15:57:33Z twisti $
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)
2527 static classinfo *class_link_intern(classinfo *c)
2529 s4 supervftbllength; /* vftbllegnth of super class */
2530 s4 vftbllength; /* vftbllength of current class */
2531 s4 interfacetablelength; /* interface table length */
2532 classinfo *super = c->super; /* super class */
2533 classinfo *ic, *c2; /* intermediate class variables */
2534 vftbl *v; /* vftbl of current class */
2535 s4 i; /* interface/method/field counter */
2536 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2538 /* maybe the class is already linked */
2543 log_message_class("Linking class: ", c);
2545 /* ok, this class is somewhat linked */
2548 /* check interfaces */
2550 for (i = 0; i < c->interfacescount; i++) {
2551 ic = c->interfaces[i];
2553 /* detect circularity */
2556 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2568 if (!(ic->flags & ACC_INTERFACE)) {
2569 dolog("Specified interface is not declared as interface:");
2573 panic("Specified interface is not declared as interface");
2577 /* check super class */
2579 if (super == NULL) { /* class java.lang.Object */
2581 c->classUsed = USED; /* Object class is always used CO-RT*/
2583 c->instancesize = sizeof(java_objectheader);
2585 vftbllength = supervftbllength = 0;
2587 c->finalizer = NULL;
2590 /* detect circularity */
2593 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2605 if (super->flags & ACC_INTERFACE)
2606 panic("Interface specified as super class");
2608 /* handle array classes */
2609 /* The component class must have been linked already. */
2610 if (c->name->text[0] == '[') {
2611 if ((arraydesc = class_link_array(c)) == NULL) {
2612 panic("class_link: class_link_array");
2616 /* Don't allow extending final classes */
2617 if (super->flags & ACC_FINAL)
2618 panic("Trying to extend final class");
2620 if (c->flags & ACC_INTERFACE)
2621 c->index = interfaceindex++;
2623 c->index = super->index + 1;
2625 c->instancesize = super->instancesize;
2627 vftbllength = supervftbllength = super->vftbl->vftbllength;
2629 c->finalizer = super->finalizer;
2632 /* compute vftbl length */
2634 for (i = 0; i < c->methodscount; i++) {
2635 methodinfo *m = &(c->methods[i]);
2637 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2638 classinfo *sc = super;
2641 for (j = 0; j < sc->methodscount; j++) {
2642 if (method_canoverwrite(m, &(sc->methods[j]))) {
2643 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2644 goto notfoundvftblindex;
2646 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2649 log_utf(sc->methods[j].name);
2650 log_utf(sc->methods[j].descriptor);
2651 panic("Trying to overwrite final method");
2653 m->vftblindex = sc->methods[j].vftblindex;
2654 goto foundvftblindex;
2660 m->vftblindex = (vftbllength++);
2669 sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2672 /* compute interfacetable length */
2674 interfacetablelength = 0;
2677 for (i = 0; i < c2->interfacescount; i++) {
2678 s4 h = class_highestinterface(c2->interfaces[i]) + 1;
2679 if (h > interfacetablelength)
2680 interfacetablelength = h;
2685 /* allocate virtual function table */
2687 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2688 (vftbllength - 1) + sizeof(methodptr*) *
2689 (interfacetablelength - (interfacetablelength > 0)));
2690 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2691 (interfacetablelength > 1));
2692 c->header.vftbl = c->vftbl = v;
2693 /* utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
2695 v->vftbllength = vftbllength;
2696 v->interfacetablelength = interfacetablelength;
2697 v->arraydesc = arraydesc;
2699 /* store interface index in vftbl */
2700 if (c->flags & ACC_INTERFACE)
2701 v->baseval = -(c->index);
2703 /* copy virtual function table of super class */
2705 for (i = 0; i < supervftbllength; i++)
2706 v->table[i] = super->vftbl->table[i];
2708 /* add method stubs into virtual function table */
2710 for (i = 0; i < c->methodscount; i++) {
2711 methodinfo *m = &(c->methods[i]);
2712 if (!(m->flags & ACC_STATIC)) {
2713 v->table[m->vftblindex] = m->stubroutine;
2717 /* compute instance size and offset of each field */
2719 for (i = 0; i < c->fieldscount; i++) {
2721 fieldinfo *f = &(c->fields[i]);
2723 if (!(f->flags & ACC_STATIC)) {
2724 dsize = desc_typesize(f->descriptor);
2725 c->instancesize = ALIGN(c->instancesize, dsize);
2726 f->offset = c->instancesize;
2727 c->instancesize += dsize;
2731 /* initialize interfacetable and interfacevftbllength */
2733 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2737 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2740 for (i = 0; i < interfacetablelength; i++) {
2741 v->interfacevftbllength[i] = 0;
2742 v->interfacetable[-i] = NULL;
2745 /* add interfaces */
2747 for (c2 = c; c2 != NULL; c2 = c2->super)
2748 for (i = 0; i < c2->interfacescount; i++) {
2749 class_addinterface(c, c2->interfaces[i]);
2752 /* add finalizer method (not for java.lang.Object) */
2754 if (super != NULL) {
2756 static utf *finame = NULL;
2757 static utf *fidesc = NULL;
2760 finame = utf_finalize;
2762 fidesc = utf_fidesc;
2764 fi = class_findmethod(c, finame, fidesc);
2766 if (!(fi->flags & ACC_STATIC)) {
2774 loader_compute_subclasses(c);
2777 log_message_class("Linking done class: ", c);
2779 /* just return c to show that we didn't had a problem */
2785 /******************* Function: class_freepool **********************************
2787 Frees all resources used by this classes Constant Pool.
2789 *******************************************************************************/
2791 static void class_freecpool(classinfo *c)
2797 for (idx=0; idx < c->cpcount; idx++) {
2798 tag = c->cptags[idx];
2799 info = c->cpinfos[idx];
2803 case CONSTANT_Fieldref:
2804 case CONSTANT_Methodref:
2805 case CONSTANT_InterfaceMethodref:
2806 FREE(info, constant_FMIref);
2808 case CONSTANT_Integer:
2809 FREE(info, constant_integer);
2811 case CONSTANT_Float:
2812 FREE(info, constant_float);
2815 FREE(info, constant_long);
2817 case CONSTANT_Double:
2818 FREE(info, constant_double);
2820 case CONSTANT_NameAndType:
2821 FREE(info, constant_nameandtype);
2827 MFREE(c->cptags, u1, c->cpcount);
2828 MFREE(c->cpinfos, voidptr, c->cpcount);
2832 /*********************** Function: class_free **********************************
2834 Frees all resources used by the class.
2836 *******************************************************************************/
2838 static void class_free(classinfo *c)
2845 MFREE(c->interfaces, classinfo*, c->interfacescount);
2847 for (i = 0; i < c->fieldscount; i++)
2848 field_free(&(c->fields[i]));
2850 for (i = 0; i < c->methodscount; i++)
2851 method_free(&(c->methods[i]));
2852 MFREE(c->methods, methodinfo, c->methodscount);
2854 if ((v = c->vftbl) != NULL) {
2856 mem_free(v->arraydesc,sizeof(arraydescriptor));
2858 for (i = 0; i < v->interfacetablelength; i++) {
2859 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2861 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2863 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2864 sizeof(methodptr*) * (v->interfacetablelength -
2865 (v->interfacetablelength > 0));
2866 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2867 (v->interfacetablelength > 1));
2871 if (c->innerclasscount)
2872 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2874 /* if (c->classvftbl)
2875 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2881 /************************* Function: class_findfield ***************************
2883 Searches a 'classinfo' structure for a field having the given name and
2886 *******************************************************************************/
2888 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2892 for (i = 0; i < c->fieldscount; i++) {
2893 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2894 return &(c->fields[i]);
2897 panic("Can not find field given in CONSTANT_Fieldref");
2899 /* keep compiler happy */
2904 /****************** Function: class_resolvefield_int ***************************
2906 This is an internally used helper function. Do not use this directly.
2908 Tries to resolve a field having the given name and type.
2909 If the field cannot be resolved, NULL is returned.
2911 *******************************************************************************/
2913 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2918 /* search for field in class c */
2919 for (i = 0; i < c->fieldscount; i++) {
2920 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2921 return &(c->fields[i]);
2925 /* try superinterfaces recursively */
2926 for (i = 0; i < c->interfacescount; ++i) {
2927 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2932 /* try superclass */
2934 return class_resolvefield_int(c->super, name, desc);
2941 /********************* Function: class_resolvefield ***************************
2943 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2945 If the field cannot be resolved the return value is NULL. If EXCEPT is
2946 true *exceptionptr is set, too.
2948 *******************************************************************************/
2950 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2951 classinfo *referer, bool except)
2955 /* XXX resolve class c */
2956 /* XXX check access from REFERER to C */
2958 fi = class_resolvefield_int(c, name, desc);
2963 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2969 /* XXX check access rights */
2975 /************************* Function: class_findmethod **************************
2977 Searches a 'classinfo' structure for a method having the given name and
2978 type and returns the index in the class info structure.
2979 If type is NULL, it is ignored.
2981 *******************************************************************************/
2983 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2987 for (i = 0; i < c->methodscount; i++) {
2989 /* utf_display_classname(c->name);printf("."); */
2990 /* utf_display(c->methods[i].name);printf("."); */
2991 /* utf_display(c->methods[i].descriptor); */
2994 if ((c->methods[i].name == name) && ((desc == NULL) ||
2995 (c->methods[i].descriptor == desc))) {
3004 /************************* Function: class_findmethod **************************
3006 Searches a 'classinfo' structure for a method having the given name and
3008 If type is NULL, it is ignored.
3010 *******************************************************************************/
3012 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3014 s4 idx = class_findmethodIndex(c, name, desc);
3019 return &(c->methods[idx]);
3023 /*********************** Function: class_fetchmethod **************************
3025 like class_findmethod, but aborts with an error if the method is not found
3027 *******************************************************************************/
3029 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3033 mi = class_findmethod(c, name, desc);
3036 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3037 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3038 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3039 panic("Method not found");
3046 /*********************** Function: class_findmethod_w**************************
3048 like class_findmethod, but logs a warning if the method is not found
3050 *******************************************************************************/
3052 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
3055 mi = class_findmethod(c, name, desc);
3058 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3059 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3060 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3062 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
3063 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
3064 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
3065 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
3066 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
3067 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
3068 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
3069 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
3070 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
3071 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
3072 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
3075 log_plain(" : WARNING: Method not found");log_nl( );
3082 /************************* Function: class_findmethod_approx ******************
3084 like class_findmethod but ignores the return value when comparing the
3087 *******************************************************************************/
3089 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3093 for (i = 0; i < c->methodscount; i++) {
3094 if (c->methods[i].name == name) {
3095 utf *meth_descr = c->methods[i].descriptor;
3099 return &(c->methods[i]);
3101 if (desc->blength <= meth_descr->blength) {
3102 /* current position in utf text */
3103 char *desc_utf_ptr = desc->text;
3104 char *meth_utf_ptr = meth_descr->text;
3105 /* points behind utf strings */
3106 char *desc_end = utf_end(desc);
3107 char *meth_end = utf_end(meth_descr);
3110 /* compare argument types */
3111 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3113 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3114 break; /* no match */
3117 return &(c->methods[i]); /* all parameter types equal */
3127 /***************** Function: class_resolvemethod_approx ***********************
3129 Searches a class and every super class for a method (without paying
3130 attention to the return value)
3132 *******************************************************************************/
3134 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3137 /* search for method (ignore returntype) */
3138 methodinfo *m = class_findmethod_approx(c, name, desc);
3141 /* search superclass */
3149 /************************* Function: class_resolvemethod ***********************
3151 Searches a class and every super class for a method.
3153 *******************************************************************************/
3155 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3158 methodinfo *m = class_findmethod(c, name, desc);
3160 /* search superclass */
3168 /****************** Function: class_resolveinterfacemethod_int ****************
3170 Internally used helper function. Do not use this directly.
3172 *******************************************************************************/
3175 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
3180 mi = class_findmethod(c,name,desc);
3184 /* try the superinterfaces */
3185 for (i=0; i<c->interfacescount; ++i) {
3186 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3194 /******************** Function: class_resolveinterfacemethod ******************
3196 Resolves a reference from REFERER to a method with NAME and DESC in
3199 If the method cannot be resolved the return value is NULL. If EXCEPT is
3200 true *exceptionptr is set, too.
3202 *******************************************************************************/
3204 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3205 classinfo *referer, bool except)
3209 /* XXX resolve class c */
3210 /* XXX check access from REFERER to C */
3212 if (!(c->flags & ACC_INTERFACE)) {
3215 new_exception(string_java_lang_IncompatibleClassChangeError);
3220 mi = class_resolveinterfacemethod_int(c, name, desc);
3225 /* try class java.lang.Object */
3226 mi = class_findmethod(class_java_lang_Object, name, desc);
3233 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3239 /********************* Function: class_resolveclassmethod *********************
3241 Resolves a reference from REFERER to a method with NAME and DESC in
3244 If the method cannot be resolved the return value is NULL. If EXCEPT is
3245 true *exceptionptr is set, too.
3247 *******************************************************************************/
3249 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3250 classinfo *referer, bool except)
3255 char msg[MAXLOGTEXT];
3257 /* XXX resolve class c */
3258 /* XXX check access from REFERER to C */
3260 /* if (c->flags & ACC_INTERFACE) { */
3262 /* *exceptionptr = */
3263 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
3267 /* try class c and its superclasses */
3270 mi = class_findmethod(cls, name, desc);
3273 } while ((cls = cls->super) != NULL); /* try the superclass */
3275 /* try the superinterfaces */
3276 for (i = 0; i < c->interfacescount; ++i) {
3277 mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
3283 utf_sprint(msg, c->name);
3284 sprintf(msg + strlen(msg), ".");
3285 utf_sprint(msg + strlen(msg), name);
3286 utf_sprint(msg + strlen(msg), desc);
3289 new_exception_message(string_java_lang_NoSuchMethodError, msg);
3295 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3297 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3302 /* XXX check access rights */
3308 /************************* Function: class_issubclass **************************
3310 Checks if sub is a descendant of super.
3312 *******************************************************************************/
3314 bool class_issubclass(classinfo *sub, classinfo *super)
3317 if (!sub) return false;
3318 if (sub == super) return true;
3324 /****************** Initialization function for classes ******************
3326 In Java, every class can have a static initialization function. This
3327 function has to be called BEFORE calling other methods or accessing static
3330 *******************************************************************************/
3332 classinfo *class_init(classinfo *c)
3336 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3340 if (!makeinitializations)
3346 /* class is somewhat initialized */
3347 c->initialized = true;
3357 #if defined(STATISTICS)
3359 count_class_inits++;
3362 /* initialize super class */
3364 if (!c->super->loaded)
3365 if (!class_load(c->super))
3368 if (!c->super->linked)
3369 if (!class_link(c->super))
3372 if (!c->super->initialized) {
3374 char logtext[MAXLOGTEXT];
3375 sprintf(logtext, "Initialize super class ");
3376 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3377 sprintf(logtext + strlen(logtext), " from ");
3378 utf_sprint_classname(logtext + strlen(logtext), c->name);
3382 if (!class_init(c->super))
3387 /* initialize interface classes */
3388 for (i = 0; i < c->interfacescount; i++) {
3389 if (!c->interfaces[i]->loaded)
3390 if (!class_load(c->interfaces[i]))
3393 if (!c->interfaces[i]->linked)
3394 if (!class_link(c->interfaces[i]))
3397 if (!c->interfaces[i]->initialized) {
3399 char logtext[MAXLOGTEXT];
3400 sprintf(logtext, "Initialize interface class ");
3401 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3402 sprintf(logtext + strlen(logtext), " from ");
3403 utf_sprint_classname(logtext + strlen(logtext), c->name);
3407 if (!class_init(c->interfaces[i]))
3412 m = class_findmethod(c, utf_clinit, utf_fidesc);
3416 char logtext[MAXLOGTEXT];
3417 sprintf(logtext, "Class ");
3418 utf_sprint_classname(logtext + strlen(logtext), c->name);
3419 sprintf(logtext + strlen(logtext), " has no static class initializer");
3426 if (!(m->flags & ACC_STATIC))
3427 panic("Class initializer is not static!");
3430 log_message_class("Starting static class initializer for class: ", c);
3432 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3437 /* now call the initializer */
3438 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3440 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3441 assert(blockInts == 0);
3445 /* we have an exception */
3446 if (*exceptionptr) {
3447 java_objectheader *xptr;
3448 java_objectheader *cause;
3450 /* class is NOT initialized */
3451 c->initialized = false;
3454 cause = *exceptionptr;
3456 /* clear exception, because we are calling jit code again */
3457 *exceptionptr = NULL;
3459 /* wrap the exception */
3461 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3462 (java_lang_Throwable *) cause);
3464 if (*exceptionptr) {
3468 /* set new exception */
3469 *exceptionptr = xptr;
3475 log_message_class("Finished static class initializer for class: ", c);
3481 /********* Function: find_class_method_constant *********/
3483 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3488 for (i=0; i<c->cpcount; i++) {
3490 e = c -> cpinfos [i];
3493 switch (c -> cptags [i]) {
3494 case CONSTANT_Methodref:
3496 constant_FMIref *fmi = e;
3497 if ( (fmi->class->name == c1)
3498 && (fmi->name == m1)
3499 && (fmi->descriptor == d1)) {
3506 case CONSTANT_InterfaceMethodref:
3508 constant_FMIref *fmi = e;
3509 if ( (fmi->class->name == c1)
3510 && (fmi->name == m1)
3511 && (fmi->descriptor == d1)) {
3525 void class_showconstanti(classinfo *c, int ii)
3531 printf ("#%d: ", (int) i);
3533 switch (c->cptags [i]) {
3534 case CONSTANT_Class:
3535 printf("Classreference -> ");
3536 utf_display(((classinfo*)e)->name);
3539 case CONSTANT_Fieldref:
3540 printf("Fieldref -> "); goto displayFMIi;
3541 case CONSTANT_Methodref:
3542 printf("Methodref -> "); goto displayFMIi;
3543 case CONSTANT_InterfaceMethodref:
3544 printf("InterfaceMethod -> "); goto displayFMIi;
3547 constant_FMIref *fmi = e;
3548 utf_display(fmi->class->name);
3550 utf_display(fmi->name);
3552 utf_display(fmi->descriptor);
3556 case CONSTANT_String:
3557 printf("String -> ");
3560 case CONSTANT_Integer:
3561 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3563 case CONSTANT_Float:
3564 printf("Float -> %f", ((constant_float*)e)->value);
3566 case CONSTANT_Double:
3567 printf("Double -> %f", ((constant_double*)e)->value);
3571 u8 v = ((constant_long*)e)->value;
3573 printf("Long -> %ld", (long int) v);
3575 printf("Long -> HI: %ld, LO: %ld\n",
3576 (long int) v.high, (long int) v.low);
3580 case CONSTANT_NameAndType:
3582 constant_nameandtype *cnt = e;
3583 printf("NameAndType: ");
3584 utf_display(cnt->name);
3586 utf_display(cnt->descriptor);
3594 panic("Invalid type of ConstantPool-Entry");
3601 void class_showconstantpool (classinfo *c)
3606 printf ("---- dump of constant pool ----\n");
3608 for (i=0; i<c->cpcount; i++) {
3609 printf ("#%d: ", (int) i);
3611 e = c -> cpinfos [i];
3614 switch (c -> cptags [i]) {
3615 case CONSTANT_Class:
3616 printf ("Classreference -> ");
3617 utf_display ( ((classinfo*)e) -> name );
3620 case CONSTANT_Fieldref:
3621 printf ("Fieldref -> "); goto displayFMI;
3622 case CONSTANT_Methodref:
3623 printf ("Methodref -> "); goto displayFMI;
3624 case CONSTANT_InterfaceMethodref:
3625 printf ("InterfaceMethod -> "); goto displayFMI;
3628 constant_FMIref *fmi = e;
3629 utf_display ( fmi->class->name );
3631 utf_display ( fmi->name);
3633 utf_display ( fmi->descriptor );
3637 case CONSTANT_String:
3638 printf ("String -> ");
3641 case CONSTANT_Integer:
3642 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3644 case CONSTANT_Float:
3645 printf ("Float -> %f", ((constant_float*)e) -> value);
3647 case CONSTANT_Double:
3648 printf ("Double -> %f", ((constant_double*)e) -> value);
3652 u8 v = ((constant_long*)e) -> value;
3654 printf ("Long -> %ld", (long int) v);
3656 printf ("Long -> HI: %ld, LO: %ld\n",
3657 (long int) v.high, (long int) v.low);
3661 case CONSTANT_NameAndType:
3663 constant_nameandtype *cnt = e;
3664 printf ("NameAndType: ");
3665 utf_display (cnt->name);
3667 utf_display (cnt->descriptor);
3671 printf ("Utf8 -> ");
3675 panic ("Invalid type of ConstantPool-Entry");
3685 /********** Function: class_showmethods (debugging only) *************/
3687 void class_showmethods (classinfo *c)
3691 printf ("--------- Fields and Methods ----------------\n");
3692 printf ("Flags: "); printflags (c->flags); printf ("\n");
3694 printf ("This: "); utf_display (c->name); printf ("\n");
3696 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3698 printf ("Index: %d\n", c->index);
3700 printf ("interfaces:\n");
3701 for (i=0; i < c-> interfacescount; i++) {
3703 utf_display (c -> interfaces[i] -> name);
3704 printf (" (%d)\n", c->interfaces[i] -> index);
3707 printf ("fields:\n");
3708 for (i=0; i < c -> fieldscount; i++) {
3709 field_display (&(c -> fields[i]));
3712 printf ("methods:\n");
3713 for (i=0; i < c -> methodscount; i++) {
3714 methodinfo *m = &(c->methods[i]);
3715 if ( !(m->flags & ACC_STATIC))
3716 printf ("vftblindex: %d ", m->vftblindex);
3718 method_display ( m );
3722 printf ("Virtual function table:\n");
3723 for (i=0; i<c->vftbl->vftbllength; i++) {
3724 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3730 /******************************************************************************/
3731 /******************* General functions for the class loader *******************/
3732 /******************************************************************************/
3734 /**************** function: create_primitive_classes ***************************
3736 create classes representing primitive types
3738 *******************************************************************************/
3740 void create_primitive_classes()
3744 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
3745 /* create primitive class */
3746 classinfo *c = class_new_int(utf_new_char(primitivetype_table[i].name));
3747 c->classUsed = NOTUSED; /* not used initially CO-RT */
3750 /* prevent loader from loading primitive class */
3754 primitivetype_table[i].class_primitive = c;
3756 /* create class for wrapping the primitive type */
3757 c = class_new_int(utf_new_char(primitivetype_table[i].wrapname));
3758 primitivetype_table[i].class_wrap = c;
3759 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
3760 primitivetype_table[i].class_wrap->impldBy = NULL;
3762 /* create the primitive array class */
3763 if (primitivetype_table[i].arrayname) {
3764 c = class_new_int(utf_new_char(primitivetype_table[i].arrayname));
3765 primitivetype_table[i].arrayclass = c;
3769 primitivetype_table[i].arrayvftbl = c->vftbl;
3775 /**************** function: class_primitive_from_sig ***************************
3777 return the primitive class indicated by the given signature character
3779 If the descriptor does not indicate a valid primitive type the
3780 return value is NULL.
3782 ********************************************************************************/
3784 classinfo *class_primitive_from_sig(char sig)
3787 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3788 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3789 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3790 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3791 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3792 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3793 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3794 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3795 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3800 /****************** function: class_from_descriptor ****************************
3802 return the class indicated by the given descriptor
3804 utf_ptr....first character of descriptor
3805 end_ptr....first character after the end of the string
3806 next.......if non-NULL, *next is set to the first character after
3807 the descriptor. (Undefined if an error occurs.)
3809 mode.......a combination (binary or) of the following flags:
3811 (Flags marked with * are the default settings.)
3813 What to do if a reference type descriptor is parsed successfully:
3815 CLASSLOAD_SKIP...skip it and return something != NULL
3816 * CLASSLOAD_NEW....get classinfo * via class_new
3817 CLASSLOAD_LOAD...get classinfo * via loader_load
3819 How to handle primitive types:
3821 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3822 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3824 How to handle "V" descriptors:
3826 * CLASSLOAD_VOID.....handle it like other primitive types
3827 CLASSLOAD_NOVOID...treat it as an error
3829 How to deal with extra characters after the end of the
3832 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3833 CLASSLOAD_CHECKEND.....treat them as an error
3835 How to deal with errors:
3837 * CLASSLOAD_PANIC....abort execution with an error message
3838 CLASSLOAD_NOPANIC..return NULL on error
3840 ********************************************************************************/
3842 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3843 char **next, int mode)
3845 char *start = utf_ptr;
3849 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3851 if (mode & CLASSLOAD_CHECKEND)
3852 error |= (utf_ptr != end_ptr);
3855 if (next) *next = utf_ptr;
3859 if (mode & CLASSLOAD_NOVOID)
3870 return (mode & CLASSLOAD_NULLPRIMITIVE)
3872 : class_primitive_from_sig(*start);
3879 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3880 name = utf_new(start, utf_ptr - start);
3881 return (mode & CLASSLOAD_LOAD)
3882 ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
3886 /* An error occurred */
3887 if (mode & CLASSLOAD_NOPANIC)
3890 log_plain("Invalid descriptor at beginning of '");
3891 log_plain_utf(utf_new(start, end_ptr - start));
3895 panic("Invalid descriptor");
3897 /* keep compiler happy */
3902 /******************* function: type_from_descriptor ****************************
3904 return the basic type indicated by the given descriptor
3906 This function parses a descriptor and returns its basic type as
3907 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3909 cls...if non-NULL the referenced variable is set to the classinfo *
3910 returned by class_from_descriptor.
3912 For documentation of the arguments utf_ptr, end_ptr, next and mode
3913 see class_from_descriptor. The only difference is that
3914 type_from_descriptor always uses CLASSLOAD_PANIC.
3916 ********************************************************************************/
3918 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3919 char **next, int mode)
3922 if (!cls) cls = &mycls;
3923 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3940 return TYPE_ADDRESS;
3944 /*************** function: create_pseudo_classes *******************************
3946 create pseudo classes used by the typechecker
3948 ********************************************************************************/
3950 static void create_pseudo_classes()
3952 /* pseudo class for Arraystubs (extends java.lang.Object) */
3954 pseudo_class_Arraystub = class_new_int(utf_new_char("$ARRAYSTUB$"));
3955 pseudo_class_Arraystub->loaded = true;
3956 pseudo_class_Arraystub->super = class_java_lang_Object;
3957 pseudo_class_Arraystub->interfacescount = 2;
3958 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3959 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3960 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3962 class_link(pseudo_class_Arraystub);
3964 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3966 /* pseudo class representing the null type */
3968 pseudo_class_Null = class_new_int(utf_new_char("$NULL$"));
3969 pseudo_class_Null->loaded = true;
3970 pseudo_class_Null->super = class_java_lang_Object;
3971 class_link(pseudo_class_Null);
3973 /* pseudo class representing new uninitialized objects */
3975 pseudo_class_New = class_new_int(utf_new_char("$NEW$"));
3976 pseudo_class_New->loaded = true;
3977 pseudo_class_New->linked = true;
3978 pseudo_class_New->super = class_java_lang_Object;
3979 /* class_link(pseudo_class_New); */
3983 /********************** Function: loader_init **********************************
3985 Initializes all lists and loads all classes required for the system or the
3988 *******************************************************************************/
3990 void loader_init(u1 *stackbottom)
3994 /* create utf-symbols for pointer comparison of frequently used strings */
3995 utf_innerclasses = utf_new_char("InnerClasses");
3996 utf_constantvalue = utf_new_char("ConstantValue");
3997 utf_code = utf_new_char("Code");
3998 utf_exceptions = utf_new_char("Exceptions");
3999 utf_linenumbertable = utf_new_char("LineNumberTable");
4000 utf_sourcefile = utf_new_char("SourceFile");
4001 utf_finalize = utf_new_char("finalize");
4002 utf_fidesc = utf_new_char("()V");
4003 utf_init = utf_new_char("<init>");
4004 utf_clinit = utf_new_char("<clinit>");
4005 utf_initsystemclass = utf_new_char("initializeSystemClass");
4006 utf_systemclass = utf_new_char("java/lang/System");
4007 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
4008 utf_initialize = utf_new_char("initialize");
4009 utf_initializedesc = utf_new_char("(I)V");
4010 utf_vmclass = utf_new_char("java/lang/VMClass");
4011 utf_java_lang_Object= utf_new_char("java/lang/Object");
4012 array_packagename = utf_new_char("<the array package>");
4014 /* create some important classes */
4015 /* These classes have to be created now because the classinfo
4016 * pointers are used in the loading code.
4018 class_java_lang_Object =
4019 class_new_int(utf_java_lang_Object);
4020 class_load(class_java_lang_Object);
4021 class_link(class_java_lang_Object);
4023 class_java_lang_String =
4024 class_new_int(utf_new_char("java/lang/String"));
4025 class_load(class_java_lang_String);
4026 class_link(class_java_lang_String);
4028 class_java_lang_Cloneable =
4029 class_new_int(utf_new_char("java/lang/Cloneable"));
4030 class_load(class_java_lang_Cloneable);
4031 class_link(class_java_lang_Cloneable);
4033 class_java_io_Serializable =
4034 class_new_int(utf_new_char("java/io/Serializable"));
4035 class_load(class_java_io_Serializable);
4036 class_link(class_java_io_Serializable);
4038 /* create classes representing primitive types */
4039 create_primitive_classes();
4041 /* create classes used by the typechecker */
4042 create_pseudo_classes();
4044 /* correct vftbl-entries (retarded loading of class java/lang/String) */
4045 stringtable_update();
4047 #if defined(USE_THREADS)
4048 if (stackbottom != 0)
4054 static void loader_compute_class_values(classinfo *c)
4058 c->vftbl->baseval = ++classvalue;
4061 while (subs != NULL) {
4062 loader_compute_class_values(subs);
4063 subs = subs->nextsub;
4066 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4070 void loader_compute_subclasses(classinfo *c)
4072 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4076 if (!(c->flags & ACC_INTERFACE)) {
4081 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4082 c->nextsub = c->super->sub;
4088 /* this is the java.lang.Object special case */
4089 if (!class_java_lang_Object) {
4090 loader_compute_class_values(c);
4093 loader_compute_class_values(class_java_lang_Object);
4096 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4102 /******************** Function: loader_close ***********************************
4106 *******************************************************************************/
4112 /* while ((c = list_first(&unloadedclasses))) { */
4113 /* list_remove(&unloadedclasses, c); */
4114 /* class_free(c); */
4116 /* while ((c = list_first(&unlinkedclasses))) { */
4117 /* list_remove(&unlinkedclasses, c); */
4118 /* class_free(c); */
4120 /* while ((c = list_first(&linkedclasses))) { */
4121 /* list_remove(&linkedclasses, c); */
4122 /* class_free(c); */
4128 * These are local overrides for various environment variables in Emacs.
4129 * Please do not remove this and leave it at the end of the file, where
4130 * Emacs will automagically detect them.
4131 * ---------------------------------------------------------------------
4134 * indent-tabs-mode: t