-/* src/native/native.c - table of native functions
+/* src/native/native.c - native library support
- 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.
#include <assert.h>
#include <ctype.h>
-#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
-# include <ltdl.h>
-#endif
-
#include <stdint.h>
#include "vm/types.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/resolve.h"
#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
-#include "vm/resolve.h"
+#include "vmcore/system.h"
#if defined(ENABLE_JVMTI)
#include "native/jvmti/cacaodbg.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)
+#if defined(ENABLE_DL)
static hashtable *hashtable_library;
#endif
bool native_init(void)
{
-#if defined(ENABLE_LTDL)
- /* initialize libltdl */
-
- if (lt_dlinit())
- vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
+ TRACESUBSYSTEMINITIALIZATION("native_init");
+#if defined(ENABLE_DL)
/* initialize library hashtable, 10 entries should be enough */
hashtable_library = NEW(hashtable);
*******************************************************************************/
-#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;
}
/* 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_DL)
+ 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_DL)
+ /* 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) system_dlsym(ne->handle, name->text);
+
+ if (f == NULL)
+ f = (functionptr) (ptrint) system_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(ENABLE_LTDL)
-lt_dlhandle native_library_open(utf *filename)
+#if defined(ENABLE_DL)
+void* native_library_open(utf *filename)
{
- lt_dlhandle handle;
+ void* handle;
if (opt_verbosejni) {
printf("[Loading native library ");
/* try to open the library */
- handle = lt_dlopen(filename->text);
+ handle = system_dlopen(filename->text, RTLD_LAZY);
if (handle == NULL) {
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
if (opt_verbose) {
log_start();
- log_print("native_library_load: lt_dlopen failed: ");
- log_print(lt_dlerror());
+ log_print("native_library_open: system_dlopen failed: ");
+ log_print(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_DL)
+void native_library_close(void* handle)
+{
+ int result;
+
+ if (opt_verbosejni) {
+ printf("[Unloading native library ");
+/* utf_display_printable_ascii(filename); */
+ printf(" ... ");
+ }
+
+ /* Close the library. */
+
+ result = system_dlclose(handle);
+
+ if (result != 0) {
+ if (opt_verbose) {
+ log_start();
+ log_print("native_library_close: system_dlclose failed: ");
+ log_print(dlerror());
+ log_finish();
+ }
+ }
+}
+#endif
+
+
/* native_library_add **********************************************************
Adds an entry to the native library hashtable.
*******************************************************************************/
-#if defined(ENABLE_LTDL)
-void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
+#if defined(ENABLE_DL)
+void native_library_add(utf *filename, classloader_t *loader, void* handle)
{
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
*******************************************************************************/
-#if defined(ENABLE_LTDL)
+#if defined(ENABLE_DL)
hashtable_library_name_entry *native_library_find(utf *filename,
- classloader *loader)
+ classloader_t *loader)
{
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
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
- exceptions_throw_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)
{
- classloader *cl;
- utf *name;
- utf *newname;
- functionptr f;
-#if defined(ENABLE_LTDL)
- 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
-
- cl = m->class->classloader;
-
- /* verbose output */
+#if defined(ENABLE_DL)
+ void* handle;
+# if defined(ENABLE_JNI)
+ void* onload;
+ int32_t version;
+# endif
- 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 (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);
-
- /* 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)
- /* 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];
+ if (native_library_find(name, cl) != NULL)
+ return 1;
- /* iterate through loaders in this hash slot */
+ /* Open the library. */
- 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);
+ handle = native_library_open(name);
- if (f == NULL)
- f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
+ if (handle == NULL)
+ return 0;
- ne = ne->hashlink;
- }
+# if defined(ENABLE_JNI)
+ /* Resolve JNI_OnLoad function. */
- le = le->hashlink;
- }
+ onload = system_dlsym(handle, "JNI_OnLoad");
-# 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 */
+ if (onload != NULL) {
+ JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
+ JavaVM *vm;
- method_findNative =
- class_resolveclassmethod(class_java_lang_ClassLoader,
- utf_findNative,
- utf_java_lang_ClassLoader_java_lang_String__J,
- class_java_lang_ClassLoader,
- true);
+ JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
- if (method_findNative == NULL)
- return NULL;
+ (*env)->GetJavaVM(env, &vm);
- /* try the normal name */
+ version = JNI_OnLoad(vm, NULL);
- s = javastring_new(name);
+ /* If the version is not 1.2 and not 1.4 the library cannot be
+ loaded. */
- 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);
+ if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+ system_dlclose(handle);
+ return 0;
}
}
# endif
- if (f != NULL)
- if (opt_verbosejni)
- printf("JNI ]\n");
-#endif
+ /* 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 *********************************************************