X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fnative%2Fnative.c;h=be2aea2f5bac0a89ea44c16a311f92fc827da93b;hb=8e3a80e58cbed2661470983cba9ea10adc44d249;hp=d6f0ef019c1e100380e21b3efdca5641cdfcf66d;hpb=029810ea15a8e293ebda051900e021629cc017be;p=cacao.git diff --git a/src/native/native.c b/src/native/native.c index d6f0ef019..be2aea2f5 100644 --- a/src/native/native.c +++ b/src/native/native.c @@ -1,9 +1,7 @@ /* src/native/native.c - table of native functions - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,8 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: native.c 8062 2007-06-11 08:12:14Z twisti $ - */ @@ -32,10 +28,12 @@ #include #include -#if !defined(WITH_STATIC_CLASSPATH) +#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H) # include #endif +#include + #include "vm/types.h" #include "mm/memory.h" @@ -69,30 +67,13 @@ #endif -/* include table of native functions ******************************************/ - -#if defined(WITH_STATIC_CLASSPATH) -# include "native/nativetable.inc" -#endif - - -/* tables for methods *********************************************************/ - -#if defined(WITH_STATIC_CLASSPATH) -#define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref)) - -/* table for fast string comparison */ -static nativecompref nativecomptable[NATIVETABLESIZE]; - -/* string comparsion table initialized */ -static bool nativecompdone = false; -#endif - - /* global variables ***********************************************************/ static avl_tree_t *tree_native_methods; + +#if defined(ENABLE_LTDL) static hashtable *hashtable_library; +#endif /* prototypes *****************************************************************/ @@ -108,7 +89,9 @@ static s4 native_tree_native_methods_comparator(const void *treenode, const void bool native_init(void) { -#if !defined(WITH_STATIC_CLASSPATH) + TRACESUBSYSTEMINITIALIZATION("native_init"); + +#if defined(ENABLE_LTDL) /* initialize libltdl */ if (lt_dlinit()) @@ -125,11 +108,6 @@ bool native_init(void) tree_native_methods = avl_create(&native_tree_native_methods_comparator); - /* register the intern native functions */ - - if (!nativevm_init()) - return false; - /* everything's ok */ return true; @@ -186,7 +164,6 @@ static s4 native_tree_native_methods_comparator(const void *treenode, const void *******************************************************************************/ -#if !defined(WITH_STATIC_CLASSPATH) static utf *native_make_overloaded_function(utf *name, utf *descriptor) { char *newname; @@ -194,12 +171,12 @@ static utf *native_make_overloaded_function(utf *name, utf *descriptor) char *utf_ptr; u2 c; s4 i; - s4 dumpsize; utf *u; + int32_t dumpmarker; /* mark memory */ - dumpsize = dump_size(); + DMARKER; utf_ptr = descriptor->text; namelen = strlen(name->text) + strlen("__") + strlen("0"); @@ -291,7 +268,7 @@ static utf *native_make_overloaded_function(utf *name, utf *descriptor) /* release memory */ - dump_release(dumpsize); + DRELEASE; return u; } @@ -374,12 +351,12 @@ static utf *native_method_symbol(utf *classname, utf *methodname) char *utf_endptr; u2 c; u4 pos; - s4 dumpsize; utf *u; + int32_t dumpmarker; /* mark memory */ - dumpsize = dump_size(); + DMARKER; /* Calculate length of native function name. We multiply the class and method name length by 6 as this is the maxium @@ -435,7 +412,7 @@ static utf *native_method_symbol(utf *classname, utf *methodname) /* release memory */ - dump_release(dumpsize); + DRELEASE; return u; } @@ -447,12 +424,13 @@ static utf *native_method_symbol(utf *classname, utf *methodname) *******************************************************************************/ -void native_method_register(utf *classname, JNINativeMethod *methods, s4 count) +void native_method_register(utf *classname, const JNINativeMethod *methods, + int32_t count) { native_methods_node_t *nmn; utf *name; utf *descriptor; - s4 i; + int32_t i; /* insert all methods passed */ @@ -497,7 +475,7 @@ static functionptr native_method_find(methodinfo *m) /* fill the temporary structure used for searching the tree */ - tmpnmn.classname = m->class->name; + tmpnmn.classname = m->clazz->name; tmpnmn.name = m->name; tmpnmn.descriptor = m->descriptor; @@ -512,25 +490,190 @@ static functionptr native_method_find(methodinfo *m) } +/* native_method_resolve ******************************************************* + + Resolves a native method, maybe from a dynamic library. + + IN: + m ... methodinfo of the native Java method to resolve + + RESULT: + pointer to the resolved method (symbol) + +*******************************************************************************/ + +functionptr native_method_resolve(methodinfo *m) +{ + utf *name; + utf *newname; + functionptr f; +#if defined(ENABLE_LTDL) + classloader_t *cl; + hashtable_library_loader_entry *le; + hashtable_library_name_entry *ne; + u4 key; /* hashkey */ + u4 slot; /* slot in hashtable */ +#endif +#if defined(WITH_CLASSPATH_SUN) + methodinfo *method_findNative; + java_handle_t *s; +#endif + + /* verbose output */ + + if (opt_verbosejni) { + printf("[Dynamic-linking native method "); + utf_display_printable_ascii_classname(m->clazz->name); + printf("."); + utf_display_printable_ascii(m->name); + printf(" ... "); + } + + /* generate method symbol string */ + + name = native_method_symbol(m->clazz->name, m->name); + + /* generate overloaded function (having the types in it's name) */ + + newname = native_make_overloaded_function(name, m->descriptor); + + /* check the library hash entries of the classloader of the + methods's class */ + + f = NULL; + +#if defined(ENABLE_LTDL) + /* Get the classloader. */ + + cl = class_get_classloader(m->clazz); + + /* normally addresses are aligned to 4, 8 or 16 bytes */ + + key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */ + slot = key & (hashtable_library->size - 1); + le = hashtable_library->ptr[slot]; + + /* iterate through loaders in this hash slot */ + + while ((le != NULL) && (f == NULL)) { + /* iterate through names in this loader */ + + ne = le->namelink; + + while ((ne != NULL) && (f == NULL)) { + f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text); + + if (f == NULL) + f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text); + + ne = ne->hashlink; + } + + le = le->hashlink; + } + +# if defined(WITH_CLASSPATH_SUN) + if (f == NULL) { + /* We can resolve the function directly from + java.lang.ClassLoader as it's a static function. */ + /* XXX should be done in native_init */ + + method_findNative = + class_resolveclassmethod(class_java_lang_ClassLoader, + utf_findNative, + utf_java_lang_ClassLoader_java_lang_String__J, + class_java_lang_ClassLoader, + true); + + if (method_findNative == NULL) + return NULL; + + /* try the normal name */ + + s = javastring_new(name); + + f = (functionptr) (intptr_t) vm_call_method_long(method_findNative, + NULL, cl, s); + + /* if not found, try the mangled name */ + + if (f == NULL) { + s = javastring_new(newname); + + f = (functionptr) (intptr_t) vm_call_method_long(method_findNative, + NULL, cl, s); + } + } +# endif + + if (f != NULL) + if (opt_verbosejni) + printf("JNI ]\n"); +#endif + + /* If not found, try to find the native function symbol in the + main program. */ + + if (f == NULL) { + f = native_method_find(m); + + if (f != NULL) + if (opt_verbosejni) + printf("internal ]\n"); + } + +#if defined(ENABLE_JVMTI) + /* fire Native Method Bind event */ + if (jvmti) jvmti_NativeMethodBind(m, f, &f); +#endif + + /* no symbol found? throw exception */ + + if (f == NULL) { + if (opt_verbosejni) + printf("failed ]\n"); + + exceptions_throw_unsatisfiedlinkerror(m->name); + } + + return f; +} + + /* native_library_open ********************************************************* Open a native library with the given utf8 name. + IN: + filename ... filename of the library to open + + RETURN: + handle of the opened library + *******************************************************************************/ -#if !defined(WITH_STATIC_CLASSPATH) +#if defined(ENABLE_LTDL) lt_dlhandle native_library_open(utf *filename) { lt_dlhandle handle; + if (opt_verbosejni) { + printf("[Loading native library "); + utf_display_printable_ascii(filename); + printf(" ... "); + } + /* try to open the library */ handle = lt_dlopen(filename->text); if (handle == NULL) { + if (opt_verbosejni) + printf("failed ]\n"); + if (opt_verbose) { log_start(); - log_print("native_library_load: lt_dlopen failed: "); + log_print("native_library_open: lt_dlopen failed: "); log_print(lt_dlerror()); log_finish(); } @@ -538,20 +681,58 @@ lt_dlhandle native_library_open(utf *filename) return NULL; } + if (opt_verbosejni) + printf("OK ]\n"); + return handle; } #endif +/* native_library_close ******************************************************** + + Close the native library of the given handle. + + IN: + handle ... handle of the open library + +*******************************************************************************/ + +#if defined(ENABLE_LTDL) +void native_library_close(lt_dlhandle handle) +{ + int result; + + if (opt_verbosejni) { + printf("[Unloading native library "); +/* utf_display_printable_ascii(filename); */ + printf(" ... "); + } + + /* Close the library. */ + + result = lt_dlclose(handle); + + if (result != 0) { + if (opt_verbose) { + log_start(); + log_print("native_library_close: lt_dlclose failed: "); + log_print(lt_dlerror()); + log_finish(); + } + } +} +#endif + + /* native_library_add ********************************************************** Adds an entry to the native library hashtable. *******************************************************************************/ -#if !defined(WITH_STATIC_CLASSPATH) -void native_library_add(utf *filename, java_objectheader *loader, - lt_dlhandle handle) +#if defined(ENABLE_LTDL) +void native_library_add(utf *filename, classloader_t *loader, lt_dlhandle handle) { hashtable_library_loader_entry *le; hashtable_library_name_entry *ne; /* library name */ @@ -623,7 +804,7 @@ void native_library_add(utf *filename, java_objectheader *loader, LOCK_MONITOR_EXIT(hashtable_library->header); } -#endif /* !defined(WITH_STATIC_CLASSPATH) */ +#endif /* native_library_find ********************************************************* @@ -632,9 +813,9 @@ void native_library_add(utf *filename, java_objectheader *loader, *******************************************************************************/ -#if !defined(WITH_STATIC_CLASSPATH) +#if defined(ENABLE_LTDL) hashtable_library_name_entry *native_library_find(utf *filename, - java_objectheader *loader) + classloader_t *loader) { hashtable_library_loader_entry *le; hashtable_library_name_entry *ne; /* library name */ @@ -676,163 +857,87 @@ hashtable_library_name_entry *native_library_find(utf *filename, return ne; } -#endif /* !defined(WITH_STATIC_CLASSPATH) */ - - -/* native_findfunction ********************************************************* - - Looks up a method (must have the same class name, method name, - descriptor and 'static'ness) and returns a function pointer to it. - Returns: function pointer or NULL (if there is no such method) - - Remark: For faster operation, the names/descriptors are converted - from C strings to Unicode the first time this function is called. - -*******************************************************************************/ - -#if defined(WITH_STATIC_CLASSPATH) -functionptr native_findfunction(utf *cname, utf *mname, utf *desc, - bool isstatic) -{ - /* entry of table for fast string comparison */ - struct nativecompref *n; - s4 i; - - isstatic = isstatic ? true : false; - - if (!nativecompdone) { - for (i = 0; i < NATIVETABLESIZE; i++) { - nativecomptable[i].classname = - utf_new_char(nativetable[i].classname); - - nativecomptable[i].methodname = - utf_new_char(nativetable[i].methodname); - - nativecomptable[i].descriptor = - utf_new_char(nativetable[i].descriptor); - - nativecomptable[i].isstatic = nativetable[i].isstatic; - nativecomptable[i].func = nativetable[i].func; - } - - nativecompdone = true; - } - - for (i = 0; i < NATIVETABLESIZE; i++) { - n = &(nativecomptable[i]); - - if (cname == n->classname && mname == n->methodname && - desc == n->descriptor && isstatic == n->isstatic) - return n->func; - } +#endif - /* no function was found, throw exception */ - *exceptionptr = - new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError, - mname); +/* native_library_load ********************************************************* - return NULL; -} -#endif /* defined(WITH_STATIC_CLASSPATH) */ + Load a native library and initialize it, if possible. + IN: + name ... name of the library + cl ..... classloader which loads this library -/* native_resolve_function ***************************************************** - - Resolves a native function, maybe from a dynamic library. + RETURN: + 1 ... library loaded successfully + 0 ... error *******************************************************************************/ -functionptr native_resolve_function(methodinfo *m) +int native_library_load(JNIEnv *env, utf *name, classloader_t *cl) { - utf *name; - utf *newname; - functionptr f; - hashtable_library_loader_entry *le; - hashtable_library_name_entry *ne; - u4 key; /* hashkey */ - u4 slot; /* slot in hashtable */ - - /* verbose output */ - - if (opt_verbosejni) { - printf("[Dynamic-linking native method "); - utf_display_printable_ascii_classname(m->class->name); - printf("."); - utf_display_printable_ascii(m->name); - printf(" ... "); +#if defined(ENABLE_LTDL) + lt_dlhandle handle; +# if defined(ENABLE_JNI) + lt_ptr onload; + int32_t version; +# endif + + if (name == NULL) { + exceptions_throw_nullpointerexception(); + return 0; } - /* generate method symbol string */ + /* Is the library already loaded? */ - name = native_method_symbol(m->class->name, m->name); + if (native_library_find(name, cl) != NULL) + return 1; - /* generate overloaded function (having the types in it's name) */ + /* Open the library. */ - newname = native_make_overloaded_function(name, m->descriptor); + handle = native_library_open(name); - /* check the library hash entries of the classloader of the - methods's class */ + if (handle == NULL) + return 0; - f = NULL; +# if defined(ENABLE_JNI) + /* Resolve JNI_OnLoad function. */ - /* normally addresses are aligned to 4, 8 or 16 bytes */ + onload = lt_dlsym(handle, "JNI_OnLoad"); - key = ((u4) (ptrint) m->class->classloader) >> 4; /* align to 16-byte */ - slot = key & (hashtable_library->size - 1); - le = hashtable_library->ptr[slot]; + if (onload != NULL) { + JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *); + JavaVM *vm; - /* iterate through loaders in this hash slot */ + JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload; - while ((le != NULL) && (f == NULL)) { - /* iterate through names in this loader */ + (*env)->GetJavaVM(env, &vm); - ne = le->namelink; - - while ((ne != NULL) && (f == NULL)) { - f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text); + version = JNI_OnLoad(vm, NULL); - if (f == NULL) - f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text); + /* If the version is not 1.2 and not 1.4 the library cannot be + loaded. */ - ne = ne->hashlink; + if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) { + lt_dlclose(handle); + return 0; } - - le = le->hashlink; } +# endif - if (f != NULL) - if (opt_verbosejni) - printf("JNI ]\n"); + /* Insert the library name into the library hash. */ - /* If not found, try to find the native function symbol in the - main program. */ + native_library_add(name, cl, handle); - if (f == NULL) { - f = native_method_find(m); + return 1; +#else + vm_abort("native_library_load: not available"); - if (f != NULL) - if (opt_verbosejni) - printf("internal ]\n"); - } + /* Keep compiler happy. */ -#if defined(ENABLE_JVMTI) - /* fire Native Method Bind event */ - if (jvmti) jvmti_NativeMethodBind(m, f, &f); + return 0; #endif - - /* no symbol found? throw exception */ - - if (f == NULL) { - if (opt_verbosejni) - printf("failed ]\n"); - - exceptions_throw_unsatisfiedlinkerror(m->name); - } - - return f; } -#endif /* !defined(WITH_STATIC_CLASSPATH) */ /* native_new_and_init ********************************************************* @@ -842,10 +947,10 @@ functionptr native_resolve_function(methodinfo *m) *******************************************************************************/ -java_objectheader *native_new_and_init(classinfo *c) +java_handle_t *native_new_and_init(classinfo *c) { - methodinfo *m; - java_objectheader *o; + methodinfo *m; + java_handle_t *o; if (c == NULL) vm_abort("native_new_and_init: c == NULL"); @@ -875,10 +980,10 @@ java_objectheader *native_new_and_init(classinfo *c) } -java_objectheader *native_new_and_init_string(classinfo *c, java_objectheader *s) +java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s) { - methodinfo *m; - java_objectheader *o; + methodinfo *m; + java_handle_t *o; if (c == NULL) vm_abort("native_new_and_init_string: c == NULL"); @@ -918,4 +1023,5 @@ java_objectheader *native_new_and_init_string(classinfo *c, java_objectheader *s * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */