1 /* src/native/native.c - table of native functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
33 $Id: native.c 4357 2006-01-22 23:33:38Z twisti $
42 #if !defined(ENABLE_STATICVM)
48 #include "cacao/cacao.h"
49 #include "mm/memory.h"
50 #include "native/jni.h"
51 #include "native/native.h"
52 #include "native/include/java_lang_Throwable.h"
53 #include "toolbox/logging.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/hashtable.h"
58 #include "vm/loader.h"
59 #include "vm/options.h"
60 #include "vm/resolve.h"
61 #include "vm/stringlocal.h"
62 #include "vm/jit/asmpart.h"
63 #include "vm/jit/jit.h"
66 /* include table of native functions ******************************************/
68 #include "native/include/java_lang_Cloneable.h"
69 #include "native/include/java_util_Properties.h"
70 #include "native/include/java_io_InputStream.h"
71 #include "native/include/java_io_PrintStream.h"
73 #include "native/include/gnu_classpath_VMStackWalker.h"
74 #include "native/include/gnu_classpath_VMSystemProperties.h"
75 #include "native/include/java_lang_Class.h"
76 #include "native/include/java_lang_Object.h"
77 #include "native/include/java_lang_VMClass.h"
78 #include "native/include/java_lang_VMClassLoader.h"
79 #include "native/include/java_lang_VMObject.h"
80 #include "native/include/java_lang_VMRuntime.h"
81 #include "native/include/java_lang_VMString.h"
82 #include "native/include/java_lang_VMSystem.h"
83 #include "native/include/java_lang_VMThread.h"
84 #include "native/include/java_lang_VMThrowable.h"
85 #include "native/include/java_lang_reflect_Constructor.h"
86 #include "native/include/java_lang_reflect_Field.h"
87 #include "native/include/java_lang_reflect_Method.h"
88 #include "native/include/java_lang_reflect_VMProxy.h"
89 #include "native/include/java_security_VMAccessController.h"
91 #if defined(ENABLE_STATICVM)
93 /* these are required to prevent compiler warnings */
95 #include "native/include/java_net_DatagramPacket.h"
96 #include "native/include/java_net_InetAddress.h"
97 #include "native/include/java_net_SocketImpl.h"
99 #include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
100 #include "native/include/gnu_java_net_PlainSocketImpl.h"
101 #include "native/include/gnu_java_nio_PipeImpl.h"
102 #include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
103 #include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
104 #include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
105 #include "native/include/java_lang_VMProcess.h"
106 #include "native/include/java_nio_MappedByteBufferImpl.h"
107 #include "native/include/java_nio_channels_spi_SelectorProvider.h"
109 /* now include the native table */
111 #include "native/nativetable.inc"
113 #else /* defined(ENABLE_STATICVM) */
115 /* Ensure that symbols for functions implemented within CACAO are used and */
116 /* exported to dlopen. */
118 static functionptr dummynativetable[] = {
119 (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
121 (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
123 (functionptr) Java_java_lang_VMClass_isInstance,
124 (functionptr) Java_java_lang_VMClass_isAssignableFrom,
125 (functionptr) Java_java_lang_VMClass_isInterface,
126 (functionptr) Java_java_lang_VMClass_isPrimitive,
127 (functionptr) Java_java_lang_VMClass_getName,
128 (functionptr) Java_java_lang_VMClass_getSuperclass,
129 (functionptr) Java_java_lang_VMClass_getInterfaces,
130 (functionptr) Java_java_lang_VMClass_getComponentType,
131 (functionptr) Java_java_lang_VMClass_getModifiers,
132 (functionptr) Java_java_lang_VMClass_getDeclaringClass,
133 (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
134 (functionptr) Java_java_lang_VMClass_getDeclaredFields,
135 (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
136 (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
137 (functionptr) Java_java_lang_VMClass_getClassLoader,
138 (functionptr) Java_java_lang_VMClass_forName,
139 (functionptr) Java_java_lang_VMClass_isArray,
140 (functionptr) Java_java_lang_VMClass_throwException,
142 (functionptr) Java_java_lang_VMClassLoader_defineClass,
143 (functionptr) Java_java_lang_VMClassLoader_resolveClass,
144 (functionptr) Java_java_lang_VMClassLoader_loadClass,
145 (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
146 (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
147 (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
149 (functionptr) Java_java_lang_VMObject_getClass,
150 (functionptr) Java_java_lang_VMObject_clone,
151 (functionptr) Java_java_lang_VMObject_notify,
152 (functionptr) Java_java_lang_VMObject_notifyAll,
153 (functionptr) Java_java_lang_VMObject_wait,
155 (functionptr) Java_java_lang_VMRuntime_availableProcessors,
156 (functionptr) Java_java_lang_VMRuntime_freeMemory,
157 (functionptr) Java_java_lang_VMRuntime_totalMemory,
158 (functionptr) Java_java_lang_VMRuntime_maxMemory,
159 (functionptr) Java_java_lang_VMRuntime_gc,
160 (functionptr) Java_java_lang_VMRuntime_runFinalization,
161 (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
162 (functionptr) Java_java_lang_VMRuntime_traceInstructions,
163 (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
164 (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
165 (functionptr) Java_java_lang_VMRuntime_exit,
166 (functionptr) Java_java_lang_VMRuntime_nativeLoad,
167 (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
169 (functionptr) Java_java_lang_VMString_intern,
171 (functionptr) Java_java_lang_VMSystem_arraycopy,
172 (functionptr) Java_java_lang_VMSystem_identityHashCode,
174 (functionptr) Java_java_lang_VMThread_start,
175 (functionptr) Java_java_lang_VMThread_interrupt,
176 (functionptr) Java_java_lang_VMThread_isInterrupted,
177 (functionptr) Java_java_lang_VMThread_suspend,
178 (functionptr) Java_java_lang_VMThread_resume,
179 (functionptr) Java_java_lang_VMThread_nativeSetPriority,
180 (functionptr) Java_java_lang_VMThread_nativeStop,
181 (functionptr) Java_java_lang_VMThread_currentThread,
182 (functionptr) Java_java_lang_VMThread_yield,
183 (functionptr) Java_java_lang_VMThread_interrupted,
184 (functionptr) Java_java_lang_VMThread_holdsLock,
186 (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
187 (functionptr) Java_java_lang_VMThrowable_getStackTrace,
189 (functionptr) Java_java_lang_reflect_Constructor_getModifiers,
190 (functionptr) Java_java_lang_reflect_Constructor_constructNative,
192 (functionptr) Java_java_lang_reflect_Field_getModifiers,
193 (functionptr) Java_java_lang_reflect_Field_getType,
194 (functionptr) Java_java_lang_reflect_Field_get,
195 (functionptr) Java_java_lang_reflect_Field_getBoolean,
196 (functionptr) Java_java_lang_reflect_Field_getByte,
197 (functionptr) Java_java_lang_reflect_Field_getChar,
198 (functionptr) Java_java_lang_reflect_Field_getShort,
199 (functionptr) Java_java_lang_reflect_Field_getInt,
200 (functionptr) Java_java_lang_reflect_Field_getLong,
201 (functionptr) Java_java_lang_reflect_Field_getFloat,
202 (functionptr) Java_java_lang_reflect_Field_getDouble,
203 (functionptr) Java_java_lang_reflect_Field_set,
204 (functionptr) Java_java_lang_reflect_Field_setBoolean,
205 (functionptr) Java_java_lang_reflect_Field_setByte,
206 (functionptr) Java_java_lang_reflect_Field_setChar,
207 (functionptr) Java_java_lang_reflect_Field_setShort,
208 (functionptr) Java_java_lang_reflect_Field_setInt,
209 (functionptr) Java_java_lang_reflect_Field_setLong,
210 (functionptr) Java_java_lang_reflect_Field_setFloat,
211 (functionptr) Java_java_lang_reflect_Field_setDouble,
213 (functionptr) Java_java_lang_reflect_Method_getModifiers,
214 (functionptr) Java_java_lang_reflect_Method_getReturnType,
215 (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
216 (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
217 (functionptr) Java_java_lang_reflect_Method_invokeNative,
219 (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
220 (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
221 (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
223 (functionptr) Java_java_security_VMAccessController_getStack,
226 #endif /* defined(ENABLE_STATICVM) */
229 /* tables for methods *********************************************************/
231 #ifdef ENABLE_STATICVM
232 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
234 /* table for fast string comparison */
235 static nativecompref nativecomptable[NATIVETABLESIZE];
237 /* string comparsion table initialized */
238 static bool nativecompdone = false;
242 /* global variables ***********************************************************/
244 #if !defined(ENABLE_STATICVM)
245 static hashtable hashtable_library;
246 static lt_dlhandle mainhandle;
250 /* native_loadclasses **********************************************************
252 Load classes required for native methods.
254 *******************************************************************************/
256 bool native_init(void)
258 #if !defined(ENABLE_STATICVM)
261 /* We need to access the dummy native table, not only to remove a warning */
262 /* but to be sure that the table is not optimized away (gcc does this */
265 p = &dummynativetable;
267 /* initialize libltdl */
270 /* XXX how can we throw an exception here? */
271 log_text(lt_dlerror());
276 /* get the handle for the main program */
278 if (!(mainhandle = lt_dlopen(NULL)))
281 /* initialize library hashtable, 10 entries should be enough */
283 hashtable_create(&hashtable_library, 10);
287 /* everything's ok */
293 /* native_hashtable_library_add ************************************************
295 Adds an entry to the native library hashtable.
297 *******************************************************************************/
299 #if !defined(ENABLE_STATICVM)
300 void native_hashtable_library_add(utf *filename, java_objectheader *loader,
303 hashtable_library_loader_entry *le;
304 hashtable_library_name_entry *ne; /* library name */
305 u4 key; /* hashkey */
306 u4 slot; /* slot in hashtable */
308 /* normally addresses are aligned to 4, 8 or 16 bytes */
310 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
311 slot = key & (hashtable_library.size - 1);
312 le = hashtable_library.ptr[slot];
314 /* search external hash chain for the entry */
317 if (le->loader == loader)
320 le = le->hashlink; /* next element in external chain */
323 /* no loader found? create a new entry */
326 le = NEW(hashtable_library_loader_entry);
331 /* insert entry into hashtable */
334 (hashtable_library_loader_entry *) hashtable_library.ptr[slot];
335 hashtable_library.ptr[slot] = le;
337 /* update number of hashtable-entries */
339 hashtable_library.entries++;
343 /* search for library name */
348 if (ne->name == filename)
351 ne = ne->hashlink; /* next element in external chain */
354 /* not found? add the library name to the classloader */
356 ne = NEW(hashtable_library_name_entry);
361 /* insert entry into external chain */
363 ne->hashlink = le->namelink;
366 #endif /* !defined(ENABLE_STATICVM) */
369 /* native_hashtable_library_find ***********************************************
371 Find an entry in the native library hashtable.
373 *******************************************************************************/
375 #if !defined(ENABLE_STATICVM)
376 hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
377 java_objectheader *loader)
379 hashtable_library_loader_entry *le;
380 hashtable_library_name_entry *ne; /* library name */
381 u4 key; /* hashkey */
382 u4 slot; /* slot in hashtable */
384 /* normally addresses are aligned to 4, 8 or 16 bytes */
386 key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
387 slot = key & (hashtable_library.size - 1);
388 le = hashtable_library.ptr[slot];
390 /* search external hash chain for the entry */
393 if (le->loader == loader)
396 le = le->hashlink; /* next element in external chain */
399 /* no loader found? return NULL */
404 /* search for library name */
409 if (ne->name == filename)
412 ne = ne->hashlink; /* next element in external chain */
415 /* return entry, if no entry was found, ne is NULL */
419 #endif /* !defined(ENABLE_STATICVM) */
422 /* native_findfunction *********************************************************
424 Looks up a method (must have the same class name, method name,
425 descriptor and 'static'ness) and returns a function pointer to it.
426 Returns: function pointer or NULL (if there is no such method)
428 Remark: For faster operation, the names/descriptors are converted
429 from C strings to Unicode the first time this function is called.
431 *******************************************************************************/
433 #if defined(ENABLE_STATICVM)
434 functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
437 /* entry of table for fast string comparison */
438 struct nativecompref *n;
441 isstatic = isstatic ? true : false;
443 if (!nativecompdone) {
444 for (i = 0; i < NATIVETABLESIZE; i++) {
445 nativecomptable[i].classname =
446 utf_new_char(nativetable[i].classname);
448 nativecomptable[i].methodname =
449 utf_new_char(nativetable[i].methodname);
451 nativecomptable[i].descriptor =
452 utf_new_char(nativetable[i].descriptor);
454 nativecomptable[i].isstatic = nativetable[i].isstatic;
455 nativecomptable[i].func = nativetable[i].func;
458 nativecompdone = true;
461 for (i = 0; i < NATIVETABLESIZE; i++) {
462 n = &(nativecomptable[i]);
464 if (cname == n->classname && mname == n->methodname &&
465 desc == n->descriptor && isstatic == n->isstatic)
470 /* no function was found, throw exception */
473 new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
478 #endif /* defined(ENABLE_STATICVM) */
481 /* native_make_overloaded_function *********************************************
485 *******************************************************************************/
487 #if !defined(ENABLE_STATICVM)
488 static char *native_make_overloaded_function(char *name, utf *desc)
496 utf_ptr = desc->text;
497 namelen = strlen(name) + strlen("__") + strlen("0");
499 /* calculate additional length */
501 while ((c = utf_nextu2(&utf_ptr)) != ')') {
518 while (utf_nextu2(&utf_ptr) != ';')
530 /* reallocate memory */
534 newname = DMNEW(char, namelen);
535 MCOPY(newname, name, char, i);
537 utf_ptr = desc->text;
542 while ((c = utf_nextu2(&utf_ptr)) != ')') {
560 while ((c = utf_nextu2(&utf_ptr)) != ';')
561 if (((c >= 'a') && (c <= 'z')) ||
562 ((c >= 'A') && (c <= 'Z')) ||
563 ((c >= '0') && (c <= '9')))
585 /* native_resolve_function *****************************************************
587 Resolves a native function, maybe from a dynamic library.
589 *******************************************************************************/
591 functionptr native_resolve_function(methodinfo *m)
600 hashtable_library_loader_entry *le;
601 hashtable_library_name_entry *ne;
602 u4 key; /* hashkey */
603 u4 slot; /* slot in hashtable */
609 if (opt_verbosejni) {
610 printf("[Dynamic-linking native method ");
611 utf_display_classname(m->class->name);
613 utf_display(m->name);
617 /* calculate length of native function name */
619 namelen = strlen("Java_") + utf_strlen(m->class->name) + strlen("_") +
620 utf_strlen(m->name) + strlen("0");
622 /* check for underscores in class name */
624 utf_ptr = m->class->name->text;
625 utf_endptr = UTF_END(m->class->name);
627 while (utf_ptr < utf_endptr)
628 if (utf_nextu2(&utf_ptr) == '_')
631 /* check for underscores in method name */
633 utf_ptr = m->name->text;
634 utf_endptr = UTF_END(m->name);
636 while (utf_ptr < utf_endptr)
637 if (utf_nextu2(&utf_ptr) == '_')
640 /* allocate memory */
642 dumpsize = dump_size();
644 name = DMNEW(char, namelen);
647 /* generate name of native functions */
649 strcpy(name, "Java_");
652 utf_ptr = m->class->name->text;
653 utf_endptr = UTF_END(m->class->name);
655 for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
658 /* escape sequence for '_' is '_1' */
663 /* replace '/' with '_' */
669 /* seperator between class and method */
673 utf_ptr = m->name->text;
674 utf_endptr = UTF_END(m->name);
676 for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
679 /* escape sequence for '_' is '_1' */
690 /* generate overloaded function (having the types in it's name) */
692 newname = native_make_overloaded_function(name, m->descriptor);
694 /* check the library hash entries of the classloader of the methods's */
699 /* normally addresses are aligned to 4, 8 or 16 bytes */
701 key = ((u4) (ptrint) m->class->classloader) >> 4; /* align to 16-byte */
702 slot = key & (hashtable_library.size - 1);
703 le = hashtable_library.ptr[slot];
705 /* iterate through loaders in this hash slot */
708 /* iterate through names in this loader */
713 sym = lt_dlsym(ne->handle, name);
716 sym = lt_dlsym(ne->handle, newname);
729 /* if not found, try to find the native function symbol in the main */
733 sym = lt_dlsym(mainhandle, name);
736 sym = lt_dlsym(mainhandle, newname);
740 printf("internal ]\n");
744 /* no symbol found? throw exception */
748 new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
753 dump_release(dumpsize);
755 return (functionptr) (ptrint) sym;
757 #endif /* !defined(ENABLE_STATICVM) */
760 /* native_new_and_init *********************************************************
762 Creates a new object on the heap and calls the initializer.
763 Returns the object pointer or NULL if memory is exhausted.
765 *******************************************************************************/
767 java_objectheader *native_new_and_init(classinfo *c)
770 java_objectheader *o;
773 return *exceptionptr;
782 /* try to find the initializer */
784 m = class_findmethod(c, utf_init, utf_void__void);
786 /* ATTENTION: returning the object here is ok, since the class may
787 not have an initializer */
792 /* call initializer */
794 ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL);
800 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
803 java_objectheader *o;
806 return *exceptionptr;
815 /* find initializer */
817 m = class_resolveclassmethod(c,
819 utf_java_lang_String__void,
823 /* initializer not found */
828 /* call initializer */
830 ASM_CALLJAVAFUNCTION(m, o, s, NULL, NULL);
836 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
839 java_objectheader *o;
842 return *exceptionptr;
851 /* find initializer */
853 m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
855 /* initializer not found */
860 /* call initializer */
862 ASM_CALLJAVAFUNCTION(m, o, (void *) (ptrint) i, NULL, NULL);
868 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
871 java_objectheader *o;
874 return *exceptionptr;
883 /* find initializer */
885 m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
887 /* initializer not found */
892 /* call initializer */
894 ASM_CALLJAVAFUNCTION(m, o, t, NULL, NULL);
900 /* native_get_parametertypes ***************************************************
902 Use the descriptor of a method to generate a java/lang/Class array
903 which contains the classes of the parametertypes of the method.
905 *******************************************************************************/
907 java_objectarray *native_get_parametertypes(methodinfo *m)
910 typedesc *paramtypes;
912 java_objectarray *oa;
917 /* is the descriptor fully parsed? */
919 if (!m->parseddesc->params)
920 if (!descriptor_params_from_paramtypes(md, m->flags))
923 paramtypes = md->paramtypes;
924 paramcount = md->paramcount;
926 /* skip `this' pointer */
928 if (!(m->flags & ACC_STATIC)) {
933 /* create class-array */
935 oa = builtin_anewarray(paramcount, class_java_lang_Class);
942 for (i = 0; i < paramcount; i++)
943 if (!resolve_class_from_typedesc(¶mtypes[i], true, false,
944 (classinfo **) &oa->data[i]))
951 /* native_get_exceptiontypes ***************************************************
953 Get the exceptions which can be thrown by a method.
955 *******************************************************************************/
957 java_objectarray *native_get_exceptiontypes(methodinfo *m)
959 java_objectarray *oa;
963 /* create class-array */
965 oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
970 for (i = 0; i < m->thrownexceptionscount; i++) {
971 if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
972 resolveEager, true, false, &c))
975 oa->data[i] = (java_objectheader *) c;
982 /* native_get_returntype *******************************************************
984 Get the returntype class of a method.
986 *******************************************************************************/
988 classinfo *native_get_returntype(methodinfo *m)
992 if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
1001 * These are local overrides for various environment variables in Emacs.
1002 * Please do not remove this and leave it at the end of the file, where
1003 * Emacs will automagically detect them.
1004 * ---------------------------------------------------------------------
1007 * indent-tabs-mode: t