1 /****************************** native.c ***************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Enth"alt die Tabellen f"ur die native-methods.
8 Die vom Headerfile-Generator erzeugten -.hh - Dateien werden hier
9 eingebunden, und ebenso alle C-Funktionen, mit denen diese
10 Methoden implementiert werden.
12 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
14 Last Change: 1996/11/14
16 *******************************************************************************/
22 #include "nativetypes.hh"
32 #include "../threads/thread.h" /* schani */
33 #include "../threads/locks.h"
35 /* INCLUDE-Files fuer IO-Funktionen */
39 #include <sys/types.h>
45 #include "../threads/threadio.h"
47 /* searchpath for classfiles */
48 static char *classpath;
50 /* for java-string to char conversion */
51 #define MAXSTRINGSIZE 1000
53 /******************** systemclasses required for native methods *****/
55 static classinfo *class_java_lang_Class;
56 static classinfo *class_java_lang_Cloneable;
57 static classinfo *class_java_lang_CloneNotSupportedException;
58 static classinfo *class_java_lang_System;
59 static classinfo *class_java_lang_ClassLoader;
60 static classinfo *class_java_lang_ClassNotFoundException;
61 static classinfo *class_java_lang_InstantiationException;
62 static classinfo *class_java_lang_NoSuchMethodError;
63 static classinfo *class_java_lang_NoSuchFieldError;
64 static classinfo *class_java_lang_ClassFormatError;
65 static classinfo *class_java_lang_IllegalArgumentException;
66 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
67 static classinfo *class_java_lang_NoSuchFieldException;
68 static classinfo *class_java_io_SyncFailedException;
69 static classinfo *class_java_io_IOException;
70 static classinfo *class_java_io_UnixFileSystem;
71 static classinfo *class_java_security_PrivilegedActionException;
72 static classinfo *class_java_lang_NoSuchMethodException;
73 static classinfo *class_java_lang_Double;
74 static classinfo *class_java_lang_Float;
75 static classinfo *class_java_lang_Long;
76 static classinfo *class_java_lang_Byte;
77 static classinfo *class_java_lang_Short;
78 static classinfo *class_java_lang_Boolean;
79 static classinfo *class_java_lang_Void;
80 static classinfo *class_java_lang_Character;
81 static classinfo *class_java_lang_Integer;
83 /* the system classloader object */
84 struct java_lang_ClassLoader *SystemClassLoader = NULL;
86 /* for raising exceptions from native methods */
87 java_objectheader* exceptionptr = NULL;
89 /************* use classinfo structure as java.lang.Class object *************/
91 static void use_class_as_object (classinfo *c)
93 c->header.vftbl = class_java_lang_Class -> vftbl;
96 /*********************** include Java Native Interface ***********************/
100 /*************************** include native methods **************************/
102 #include "nat/Object.c"
103 #include "nat/String.c"
104 #include "nat/ClassLoader.c"
105 #include "nat/Class.c"
106 #include "nat/Compiler.c"
107 #include "nat/Double.c"
108 #include "nat/Float.c"
109 #include "nat/Math.c"
110 #include "nat/Package.c"
111 #include "nat/Runtime.c"
112 #include "nat/SecurityManager.c"
113 #include "nat/System.c"
114 #include "nat/Thread.c"
115 #include "nat/Throwable.c"
116 #include "nat/Finalizer.c"
117 #include "nat/Array.c"
118 #include "nat/Constructor.c"
119 #include "nat/Field.c"
120 #include "nat/Method.c"
121 #include "nat/FileDescriptor.c"
122 #include "nat/FileInputStream.c"
123 #include "nat/FileOutputStream.c"
124 #include "nat/FileSystem.c"
125 #include "nat/ObjectInputStream.c"
126 #include "nat/ObjectStreamClass.c"
127 #include "nat/RandomAccessFile.c"
128 #include "nat/ResourceBundle.c"
129 #include "nat/JarFile.c"
130 #include "nat/Adler32.c"
131 #include "nat/CRC32.c"
132 #include "nat/Deflater.c"
133 #include "nat/Inflater.c"
134 #include "nat/ZipEntry.c"
135 #include "nat/ZipFile.c"
136 #include "nat/BigInteger.c"
137 #include "nat/InetAddress.c"
138 #include "nat/InetAddressImpl.c"
139 #include "nat/AccessController.c"
140 #include "nat/ClassLoader_NativeLibrary.c"
141 #include "nat/UnixFileSystem.c"
143 /************************** tables for methods *******************************/
145 /* table for locating native methods */
146 static struct nativeref {
154 #include "nativetable.hh"
159 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
161 /* table for fast string comparison */
162 static struct nativecompref {
168 } nativecomptable [NATIVETABLESIZE];
170 /* string comparsion table initialized */
171 static bool nativecompdone = false;
174 /*********************** function: native_loadclasses ************************
176 load classes required for native methods
178 ******************************************************************************/
180 void native_loadclasses()
182 /* class_new adds the class to the list of classes to be loaded */
183 class_java_lang_Cloneable =
184 class_new ( utf_new_char ("java/lang/Cloneable") );
185 class_java_lang_CloneNotSupportedException =
186 class_new ( utf_new_char ("java/lang/CloneNotSupportedException") );
187 class_java_lang_Class =
188 class_new ( utf_new_char ("java/lang/Class") );
189 class_java_io_IOException =
190 class_new ( utf_new_char ("java/io/IOException") );
191 class_java_lang_ClassNotFoundException =
192 class_new ( utf_new_char ("java/lang/ClassNotFoundException") );
193 class_java_lang_InstantiationException =
194 class_new ( utf_new_char ("java/lang/InstantiationException") );
195 class_java_lang_NoSuchMethodError =
196 class_new ( utf_new_char ("java/lang/NoSuchMethodError") );
197 class_java_lang_NoSuchFieldError =
198 class_new ( utf_new_char ("java/lang/NoSuchFieldError") );
199 class_java_lang_ClassFormatError =
200 class_new ( utf_new_char ("java/lang/ClassFormatError") );
201 class_java_io_SyncFailedException =
202 class_new ( utf_new_char ("java/io/SyncFailedException") );
203 class_java_io_UnixFileSystem =
204 class_new ( utf_new_char ("java/io/UnixFileSystem") );
205 class_java_lang_System =
206 class_new ( utf_new_char ("java/lang/System") );
207 class_java_lang_ClassLoader =
208 class_new ( utf_new_char ("java/lang/ClassLoader") );
209 class_java_security_PrivilegedActionException =
210 class_new( utf_new_char("java/security/PrivilegedActionException"));
211 class_java_lang_IllegalArgumentException =
212 class_new( utf_new_char("java/lang/IllegalArgumentException"));
213 class_java_lang_ArrayIndexOutOfBoundsException =
214 class_new( utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
215 class_java_lang_NoSuchFieldException =
216 class_new( utf_new_char ("java/lang/NoSuchFieldException") );
217 class_java_lang_NoSuchMethodException =
218 class_new( utf_new_char ("java/lang/NoSuchMethodException") );
220 /* load classes for wrapping primitive types */
221 class_java_lang_Double =
222 class_new( utf_new_char ("java/lang/Double") );
223 class_java_lang_Float =
224 class_new( utf_new_char ("java/lang/Float") );
225 class_java_lang_Character =
226 class_new( utf_new_char ("java/lang/Character") );
227 class_java_lang_Integer =
228 class_new( utf_new_char ("java/lang/Integer") );
229 class_java_lang_Long =
230 class_new( utf_new_char ("java/lang/Long") );
231 class_java_lang_Byte =
232 class_new( utf_new_char ("java/lang/Byte") );
233 class_java_lang_Short =
234 class_new( utf_new_char ("java/lang/Short") );
235 class_java_lang_Boolean =
236 class_new( utf_new_char ("java/lang/Boolean") );
237 class_java_lang_Void =
238 class_new( utf_new_char ("java/lang/Void") );
240 /* load to avoid dynamic classloading */
241 class_new(utf_new_char("sun/net/www/protocol/file/Handler"));
242 class_new(utf_new_char("sun/net/www/protocol/jar/Handler"));
243 class_new(utf_new_char("sun/io/CharToByteISO8859_1"));
245 /* start classloader */
246 loader_load(utf_new_char("sun/io/ByteToCharISO8859_1"));
250 /*************** adds a class to the vector of loaded classes ****************/
252 void systemclassloader_addclass(classinfo *c)
256 /* find method addClass of java.lang.ClassLoader */
257 m = class_resolvemethod (
258 class_java_lang_ClassLoader,
259 utf_new_char("addClass"),
260 utf_new_char("(Ljava/lang/Class;)")
263 if (!m) panic("warning: cannot initialize classloader");
265 /* prepare class to be passed as argument */
266 use_class_as_object (c);
268 /* call 'addClass' */
269 asm_calljavamethod(m,
270 (java_objectheader*) SystemClassLoader,
271 (java_objectheader*) c,
277 /*************** adds a library to the vector of loaded libraries ************/
279 void systemclassloader_addlibrary(java_objectheader *o)
283 /* find method addElement of java.util.Vector */
284 m = class_resolvemethod (
285 loader_load ( utf_new_char ("java/util/Vector") ),
286 utf_new_char("addElement"),
287 utf_new_char("(Ljava/lang/Object;)V")
290 if (!m) panic("cannot initialize classloader");
292 /* call 'addElement' */
293 asm_calljavamethod(m,
294 SystemClassLoader->nativeLibraries,
301 /*****************************************************************************
303 create systemclassloader object and initialize instance fields
305 ******************************************************************************/
307 void init_systemclassloader()
309 if (!SystemClassLoader) {
311 /* create object and call initializer */
312 SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_java_lang_ClassLoader);
314 /* systemclassloader has no parent */
315 SystemClassLoader->parent = NULL;
316 SystemClassLoader->initialized = true;
321 /********************* add loaded library name ******************************/
323 void systemclassloader_addlibname(java_objectheader *o)
326 java_objectheader *LibraryNameVector;
329 m = class_resolvemethod (
330 loader_load ( utf_new_char ("java/util/Vector") ),
331 utf_new_char("addElement"),
332 utf_new_char("(Ljava/lang/Object;)V")
335 if (!m) panic("cannot initialize classloader");
337 id = env.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
338 if (!id) panic("can not access ClassLoader");
340 asm_calljavamethod(m,
341 GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
349 /********************* function: native_setclasspath *************************/
351 void native_setclasspath (char *path)
353 /* set searchpath for classfiles */
357 /***************** function: throw_classnotfoundexception ********************/
359 void throw_classnotfoundexception()
361 /* throws a ClassNotFoundException */
362 exceptionptr = native_new_and_init (class_java_lang_ClassNotFoundException);
366 /*********************** Funktion: native_findfunction ************************
368 Sucht in der Tabelle die passende Methode (muss mit Klassennamen,
369 Methodennamen, Descriptor und 'static'-Status "ubereinstimmen),
370 und gibt den Funktionszeiger darauf zur"uck.
371 Return: Funktionszeiger oder NULL (wenn es keine solche Methode gibt)
373 Anmerkung: Zu Beschleunigung des Suchens werden die als C-Strings
374 vorliegenden Namen/Descriptors in entsprechende unicode-Symbole
375 umgewandelt (beim ersten Aufruf dieser Funktion).
377 *******************************************************************************/
379 functionptr native_findfunction (utf *cname, utf *mname,
380 utf *desc, bool isstatic)
383 /* entry of table for fast string comparison */
384 struct nativecompref *n;
385 /* for warning message if no function is found */
389 isstatic = isstatic ? true : false;
391 if (!nativecompdone) {
392 for (i=0; i<NATIVETABLESIZE; i++) {
393 nativecomptable[i].classname =
394 utf_new_char(nativetable[i].classname);
395 nativecomptable[i].methodname =
396 utf_new_char(nativetable[i].methodname);
397 nativecomptable[i].descriptor =
398 utf_new_char(nativetable[i].descriptor);
399 nativecomptable[i].isstatic =
400 nativetable[i].isstatic;
401 nativecomptable[i].func =
404 nativecompdone = true;
407 for (i=0; i<NATIVETABLESIZE; i++) {
408 n = &(nativecomptable[i]);
410 if (cname==n->classname && mname==n->methodname &&
411 desc==n->descriptor && isstatic==n->isstatic) return n->func;
414 /* no function was found, display warning */
417 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
419 buffer = MNEW(char, buffer_len);
421 strcpy(buffer,"warning: native function ");
422 utf_sprint(buffer+strlen(buffer),mname);
423 strcpy(buffer+strlen(buffer),": ");
424 utf_sprint(buffer+strlen(buffer),desc);
425 strcpy(buffer+strlen(buffer)," not found in class ");
426 utf_sprint(buffer+strlen(buffer),cname);
430 MFREE(buffer,char,buffer_len);
436 /********************** function: javastring_new *****************************
438 creates a new object of type java/lang/String with the text of
439 the specified utf8-string
441 return: pointer to the string or NULL (no memory)
443 *****************************************************************************/
445 java_objectheader *javastring_new (utf *u)
447 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
448 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
449 java_lang_String *s; /* result-string */
453 s = (java_lang_String*) builtin_new (class_java_lang_String);
454 a = builtin_newarray_char (utflength);
456 /* javastring or character-array could not be created */
457 if ( (!a) || (!s) ) return NULL;
459 /* decompress utf-string */
460 for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);
462 /* set fields of the javastring-object */
465 s -> count = utflength;
467 return (java_objectheader*) s;
470 /********************** Funktion: javastring_new_char ************************
472 Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
473 den "ubergebenen C-String ein.
474 Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
476 *****************************************************************************/
478 java_objectheader *javastring_new_char (char *text)
481 u4 len = strlen(text); /* length of the string */
482 java_lang_String *s; /* result-string */
485 s = (java_lang_String*) builtin_new (class_java_lang_String);
486 a = builtin_newarray_char (len);
488 /* javastring or character-array could not be created */
489 if ( (!a) || (!s) ) return NULL;
492 for (i=0; i<len; i++) a->data[i] = text[i];
494 /* set fields of the javastring-object */
499 return (java_objectheader*) s;
503 /************************* Funktion: javastring_tochar *****************************
505 Macht aus einem java-string einen C-String, und liefert den Zeiger
507 Achtung: Beim n"achsten Aufruf der Funktion wird der vorige String
510 ***********************************************************************************/
512 char stringbuffer[MAXSTRINGSIZE];
514 char *javastring_tochar (java_objectheader *so)
516 java_lang_String *s = (java_lang_String*) so;
523 if (s->count > MAXSTRINGSIZE) return "";
524 for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
525 stringbuffer[i] = '\0';
529 /****************** function class_findfield_approx ***************************
531 searches in 'classinfo'-structure for a field with the
534 *******************************************************************************/
536 fieldinfo *class_findfield_approx (classinfo *c, utf *name)
539 for (i = 0; i < c->fieldscount; i++) {
540 /* compare field names */
541 if ((c->fields[i].name == name))
542 return &(c->fields[i]);
545 /* field was not found, raise exception */
546 exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
551 /******************** Funktion: native_new_and_init *************************
553 Legt ein neues Objekt einer Klasse am Heap an, und ruft automatisch
554 die Initialisierungsmethode auf.
555 Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
558 *****************************************************************************/
560 java_objectheader *native_new_and_init (classinfo *c)
563 java_objectheader *o = builtin_new (c); /* create object */
567 /* find initializer */
568 m = class_findmethod (c,
569 utf_new_char ("<init>"),
570 utf_new_char ("()V"));
573 /* initializer not ofund */
574 log_text ("warning: class has no instance-initializer:");
575 utf_sprint (logtext, c->name);
580 /* call initializer */
581 asm_calljavamethod (m, o,NULL,NULL,NULL);
585 /******************** function: stringtable_update ****************************
587 traverses the javastring hashtable and sets the vftbl-entries of
588 javastrings which were temporarily set to NULL, because
589 java.lang.Object was not yet loaded
591 *******************************************************************************/
593 void stringtable_update ()
595 java_lang_String *js;
597 literalstring *s; /* hashtable entry */
600 for (i=0; i<string_hash.size; i++) {
601 s = string_hash.ptr[i];
605 js = (java_lang_String *) s->string;
607 if (!js || !(a = js->value))
608 /* error in hashtable found */
609 panic("invalid literalstring in hashtable");
611 if (!js->header.vftbl)
612 /* vftbl of javastring is NULL */
613 js->header.vftbl = class_java_lang_String -> vftbl;
615 if (!a->header.objheader.vftbl)
616 /* vftbl of character-array is NULL */
617 a->header.objheader.vftbl = class_array -> vftbl;
619 /* follow link in external hash chain */
627 /************************* function: u2_utflength ***************************
629 returns the utf length in bytes of a u2 array
631 *****************************************************************************/
634 u4 u2_utflength(u2 *text, u4 u2_length)
636 u4 result_len = 0; /* utf length in bytes */
637 u2 ch; /* current unicode character */
640 for (len = 0; len < u2_length; len++) {
642 /* next unicode character */
645 /* determine bytes required to store unicode character as utf */
646 if (ch && (ch < 0x80))
657 /********************* function: utf_new_u2 ***********************************
659 make utf symbol from u2 array,
660 if isclassname is true '.' is replaced by '/'
662 *******************************************************************************/
664 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
666 char *buffer; /* memory buffer for unicode characters */
667 char *pos; /* pointer to current position in buffer */
668 u4 left; /* unicode characters left */
669 u4 buflength; /* utf length in bytes of the u2 array */
670 utf *result; /* resulting utf-string */
673 /* determine utf length in bytes and allocate memory */
674 buflength = u2_utflength(unicode_pos, unicode_length);
675 buffer = MNEW(char,buflength);
677 /* memory allocation failed */
678 if (!buffer) return NULL;
683 for (i = 0; i++ < unicode_length; unicode_pos++) {
684 /* next unicode character */
687 if ((c != 0) && (c < 0x80)) {
690 if ((int) left < 0) break;
691 /* convert classname */
692 if (isclassname && c=='.')
696 } else if (c < 0x800) {
698 unsigned char high = c >> 6;
699 unsigned char low = c & 0x3F;
701 if ((int) left < 0) break;
702 *pos++ = high | 0xC0;
707 char mid = (c >> 6) & 0x3F;
710 if ((int) left < 0) break;
711 *pos++ = high | 0xE0;
717 /* insert utf-string into symbol-table */
718 result = utf_new(buffer,buflength);
719 MFREE(buffer, char, buflength);
723 /********************* function: javastring_toutf *****************************
725 make utf symbol from javastring
727 *******************************************************************************/
729 utf *javastring_toutf(java_lang_String *string, bool isclassname)
731 java_lang_String *str = (java_lang_String *) string;
732 return utf_new_u2(str->value->data,str->count, isclassname);
735 /********************* function: literalstring_u2 *****************************
737 searches for the javastring with the specified u2-array in
738 the string hashtable, if there is no such string a new one is
741 if copymode is true a copy of the u2-array is made
743 *******************************************************************************/
745 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
747 literalstring *s; /* hashtable element */
748 java_lang_String *js; /* u2-array wrapped in javastring */
749 java_chararray *stringdata; /* copy of u2-array */
754 /* find location in hashtable */
755 key = unicode_hashkey (a->data, length);
756 slot = key & (string_hash.size-1);
757 s = string_hash.ptr[slot];
761 js = (java_lang_String *) s->string;
763 if (js->count == length) {
765 for (i=0; i<length; i++)
766 if (js->value->data[i] != a->data[i]) goto nomatch;
768 /* string already in hashtable, free memory */
770 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2)*(length-1)+10);
772 return (java_objectheader *) js;
776 /* follow link in external hash chain */
781 /* create copy of u2-array for new javastring */
782 u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
783 stringdata = lit_mem_alloc ( arraysize );
784 memcpy(stringdata, a, arraysize );
789 /* location in hashtable found, complete arrayheader */
790 if (class_array==NULL) panic("class_array not initialized");
791 stringdata -> header.objheader.vftbl = class_array -> vftbl;
792 stringdata -> header.size = length;
793 stringdata -> header.arraytype = ARRAYTYPE_CHAR;
795 /* create new javastring */
796 js = LNEW (java_lang_String);
797 js -> header.vftbl = class_java_lang_String -> vftbl;
798 js -> value = stringdata;
800 js -> count = length;
802 /* create new literalstring */
803 s = NEW (literalstring);
804 s->hashlink = string_hash.ptr[slot];
805 s->string = (java_objectheader *) js;
806 string_hash.ptr[slot] = s;
808 /* update numbe of hashtable entries */
809 string_hash.entries++;
811 /* reorganization of hashtable */
812 if ( string_hash.entries > (string_hash.size*2)) {
814 /* reorganization of hashtable, average length of
815 the external chains is approx. 2 */
819 hashtable newhash; /* the new hashtable */
821 /* create new hashtable, double the size */
822 init_hashtable(&newhash, string_hash.size*2);
823 newhash.entries=string_hash.entries;
825 /* transfer elements to new hashtable */
826 for (i=0; i<string_hash.size; i++) {
827 s = string_hash.ptr[i];
829 literalstring *nexts = s -> hashlink;
830 js = (java_lang_String*) s->string;
831 slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
833 s->hashlink = newhash.ptr[slot];
834 newhash.ptr[slot] = s;
836 /* follow link in external hash chain */
841 /* dispose old table */
842 MFREE (string_hash.ptr, void*, string_hash.size);
843 string_hash = newhash;
846 return (java_objectheader *) js;
849 /******************** Funktion: literalstring_new *****************************
851 creates a new javastring with the text of the utf-symbol
852 and inserts it into the string hashtable
854 *******************************************************************************/
856 java_objectheader *literalstring_new (utf *u)
858 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
859 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
860 java_chararray *a; /* u2-array constructed from utf string */
861 java_objectheader *js;
864 /* allocate memory */
865 a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );
866 /* convert utf-string to u2-array */
867 for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);
869 return literalstring_u2(a, utflength, false);
873 /********************** function: literalstring_free **************************
875 removes a javastring from memory
877 ******************************************************************************/
879 void literalstring_free (java_objectheader* sobj)
881 java_lang_String *s = (java_lang_String*) sobj;
882 java_chararray *a = s->value;
884 log_text("literalstring_free called");
886 /* dispose memory of java.lang.String object */
887 LFREE (s, java_lang_String);
888 /* dispose memory of java-characterarray */
889 LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */