/* 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.
#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;
bool native_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("native_init");
+
#if defined(ENABLE_LTDL)
/* initialize libltdl */
*******************************************************************************/
-#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_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(ENABLE_LTDL)
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(ENABLE_LTDL)
-void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
+void native_library_add(utf *filename, classloader_t *loader, lt_dlhandle handle)
{
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
#if defined(ENABLE_LTDL)
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 */
+ lt_dlhandle handle;
+# if defined(ENABLE_JNI)
+ lt_ptr 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];
-
- /* 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 (native_library_find(name, cl) != NULL)
+ return 1;
- if (f == NULL)
- f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
+ /* Open the library. */
- ne = ne->hashlink;
- }
+ handle = native_library_open(name);
- le = le->hashlink;
- }
+ if (handle == NULL)
+ return 0;
-# 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 defined(ENABLE_JNI)
+ /* Resolve JNI_OnLoad function. */
- if (method_findNative == NULL)
- return NULL;
+ onload = lt_dlsym(handle, "JNI_OnLoad");
- /* try the normal name */
+ if (onload != NULL) {
+ JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
+ JavaVM *vm;
- s = javastring_new(name);
+ JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
- f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
- NULL, cl, s);
+ (*env)->GetJavaVM(env, &vm);
- /* if not found, try the mangled name */
+ version = JNI_OnLoad(vm, NULL);
- if (f == NULL) {
- s = javastring_new(newname);
+ /* 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 ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+ lt_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 *********************************************************
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/