/* 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: native.c 7918 2007-05-20 20:42:18Z michi $
-
*/
#include <assert.h>
#include <ctype.h>
-#if !defined(WITH_STATIC_CLASSPATH)
+#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
# include <ltdl.h>
#endif
+#include <stdint.h>
+
#include "vm/types.h"
#include "mm/memory.h"
#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 *****************************************************************/
bool native_init(void)
{
-#if !defined(WITH_STATIC_CLASSPATH)
+ TRACESUBSYSTEMINITIALIZATION("native_init");
+
+#if defined(ENABLE_LTDL)
/* initialize libltdl */
if (lt_dlinit())
tree_native_methods = avl_create(&native_tree_native_methods_comparator);
- /* register the intern native functions */
-
- nativevm_init();
-
/* everything's ok */
return true;
*******************************************************************************/
-#if !defined(WITH_STATIC_CLASSPATH)
static utf *native_make_overloaded_function(utf *name, utf *descriptor)
{
char *newname;
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");
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return u;
}
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
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return u;
}
*******************************************************************************/
-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 */
/* 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;
}
+/* 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_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ 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_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ 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();
}
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_classloader_entry *cle;
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
u4 key; /* hashkey */
LOCK_MONITOR_ENTER(hashtable_library->header);
- /* insert loader into the classloader hashtable */
-
- cle = loader_hashtable_classloader_add(loader);
-
/* normally addresses are aligned to 4, 8 or 16 bytes */
- key = ((u4) (ptrint) cle) >> 4; /* align to 16-byte boundaries */
+ key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
slot = key & (hashtable_library->size - 1);
le = hashtable_library->ptr[slot];
/* search external hash chain for the entry */
while (le) {
- if (le->cle == cle)
+ if (le->loader == loader)
break;
le = le->hashlink; /* next element in external chain */
if (le == NULL) {
le = NEW(hashtable_library_loader_entry);
- le->cle = cle;
+ le->loader = loader;
le->namelink = NULL;
/* insert entry into hashtable */
LOCK_MONITOR_EXIT(hashtable_library->header);
}
-#endif /* !defined(WITH_STATIC_CLASSPATH) */
+#endif
/* native_library_find *********************************************************
*******************************************************************************/
-#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_classloader_entry *cle;
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
u4 key; /* hashkey */
u4 slot; /* slot in hashtable */
- /* search loader in the classloader hashtable */
-
- cle = loader_hashtable_classloader_find(loader);
-
- if (!cle)
- return NULL;
-
/* normally addresses are aligned to 4, 8 or 16 bytes */
- key = ((u4) (ptrint) cle) >> 4; /* align to 16-byte boundaries */
+ key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
slot = key & (hashtable_library->size - 1);
le = hashtable_library->ptr[slot];
/* search external hash chain for the entry */
while (le) {
- if (le->cle == cle)
+ if (le->loader == loader)
break;
le = le->hashlink; /* next element in external chain */
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;
- }
-
- /* no function was found, throw exception */
+#endif
- *exceptionptr =
- new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
- mname);
- return NULL;
-}
-#endif /* defined(WITH_STATIC_CLASSPATH) */
+/* native_library_load *********************************************************
+ Load a native library and initialize it, if possible.
-/* native_resolve_function *****************************************************
+ IN:
+ name ... name of the library
+ cl ..... classloader which loads this library
- 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 *********************************************************
*******************************************************************************/
-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");
}
-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");
/* find initializer */
- m = class_resolveclassmethod(c,
- utf_init,
- utf_java_lang_String__void,
- NULL,
- true);
+ m = class_findmethod(c, utf_init, utf_java_lang_String__void);
/* initializer not found */
}
-java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
-{
- methodinfo *m;
- java_objectheader *o;
-
- if (c == NULL)
- vm_abort("native_new_and_init_int: c == NULL");
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* find initializer */
-
- m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
-
- /* initializer not found */
-
- if (m == NULL)
- return NULL;
-
- /* call initializer */
-
- (void) vm_call_method(m, o, i);
-
- return o;
-}
-
-
-java_objectheader *native_new_and_init_throwable(classinfo *c, java_objectheader *t)
-{
- java_objectheader *o;
- methodinfo *m;
-
- if (c == NULL)
- vm_abort("native_new_and_init_throwable: c == NULL");
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* find initializer */
-
- m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
-
- /* initializer not found */
-
- if (m == NULL)
- return NULL;
-
- /* call initializer */
-
- (void) vm_call_method(m, o, t);
-
- return o;
-}
-
-
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/