1 /* src/native/native.cpp - native library support
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
37 #include "mm/memory.hpp"
39 #include "native/jni.hpp"
40 #include "native/native.hpp"
42 #include "threads/mutex.hpp"
44 #include "toolbox/logging.hpp"
46 #include "vm/jit/builtin.hpp"
47 #include "vm/exceptions.hpp"
48 #include "vm/global.h"
49 #include "vm/globals.hpp"
50 #include "vm/loader.hpp"
51 #include "vm/options.h"
53 #include "vm/resolve.hpp"
54 #include "vm/string.hpp"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.hpp"
60 #if defined(ENABLE_JVMTI)
61 #include "native/jvmti/cacaodbg.h"
65 /* native_make_overloaded_function *********************************************
69 *******************************************************************************/
71 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
80 utf_ptr = descriptor->text;
81 namelen = strlen(name->text) + strlen("__") + strlen("0");
83 /* calculate additional length */
85 while ((c = utf_nextu2(&utf_ptr)) != ')') {
102 while (utf_nextu2(&utf_ptr) != ';')
113 /* reallocate memory */
115 i = strlen(name->text);
117 newname = MNEW(char, namelen);
118 MCOPY(newname, name->text, char, i);
120 utf_ptr = descriptor->text;
125 while ((c = utf_nextu2(&utf_ptr)) != ')') {
143 while ((c = utf_nextu2(&utf_ptr)) != ';')
144 if (((c >= 'a') && (c <= 'z')) ||
145 ((c >= 'A') && (c <= 'Z')) ||
146 ((c >= '0') && (c <= '9')))
164 /* make a utf-string */
166 u = utf_new_char(newname);
170 MFREE(newname, char, namelen);
176 /* native_insert_char **********************************************************
178 Inserts the passed UTF character into the native method name. If
179 necessary it is escaped properly.
181 *******************************************************************************/
183 static s4 native_insert_char(char *name, u4 pos, u2 c)
191 /* replace '/' or '.' with '_' */
196 /* escape sequence for '_' is '_1' */
202 /* escape sequence for ';' is '_2' */
208 /* escape sequence for '[' is '_1' */
217 /* unicode character */
221 for (i = 0; i < 4; ++i) {
223 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
232 /* return the new buffer index */
238 /* native_method_symbol ********************************************************
240 Generate a method-symbol string out of the class name and the
243 *******************************************************************************/
245 static utf *native_method_symbol(utf *classname, utf *methodname)
255 /* Calculate length of native function name. We multiply the
256 class and method name length by 6 as this is the maxium
257 escape-sequence that can be generated (unicode). */
261 utf_get_number_of_u2s(classname) * 6 +
263 utf_get_number_of_u2s(methodname) * 6 +
266 /* allocate memory */
268 name = MNEW(char, namelen);
270 /* generate name of native functions */
272 strcpy(name, "Java_");
273 pos = strlen("Java_");
275 utf_ptr = classname->text;
276 utf_endptr = UTF_END(classname);
278 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
280 pos = native_insert_char(name, pos, c);
283 /* seperator between class and method */
287 utf_ptr = methodname->text;
288 utf_endptr = UTF_END(methodname);
290 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
292 pos = native_insert_char(name, pos, c);
299 /* check for an buffer overflow */
301 assert((int32_t) pos <= namelen);
303 /* make a utf-string */
305 u = utf_new_char(name);
309 MFREE(name, char, namelen);
315 bool operator< (const NativeMethod& first, const NativeMethod& second)
317 if (first._classname < second._classname)
319 else if (first._classname > second._classname)
322 if (first._name < second._name)
324 else if (first._name > second._name)
327 if (first._descriptor < second._descriptor)
329 else if (first._descriptor > second._descriptor)
332 // All pointers are equal, we have found the entry.
338 * Register native methods with the VM. This is done by inserting
339 * them into the native method table.
342 * @param methods Native methods array.
343 * @param count Number of methods in the array.
345 void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
347 // Insert all methods passed */
348 for (size_t i = 0; i < count; i++) {
349 if (opt_verbosejni) {
350 printf("[Registering JNI native method ");
351 utf_display_printable_ascii_classname(classname);
352 printf(".%s]\n", methods[i].name);
355 // Generate the UTF8 names.
356 utf* name = utf_new_char(methods[i].name);
357 utf* signature = utf_new_char(methods[i].signature);
359 NativeMethod nm(classname, name, signature, methods[i].fnPtr);
361 // Insert the method into the table.
368 * Resolves a native method, maybe from a dynamic library.
370 * @param m Method structure of the native Java method to resolve.
372 * @return Pointer to the resolved method (symbol).
374 void* NativeMethods::resolve_method(methodinfo* m)
377 if (opt_verbosejni) {
378 printf("[Dynamic-linking native method ");
379 utf_display_printable_ascii_classname(m->clazz->name);
381 utf_display_printable_ascii(m->name);
385 /* generate method symbol string */
387 utf* name = native_method_symbol(m->clazz->name, m->name);
389 /* generate overloaded function (having the types in it's name) */
391 utf* newname = native_make_overloaded_function(name, m->descriptor);
393 // Try to find the symbol.
396 #if defined(ENABLE_DL)
397 // Get the classloader.
398 classloader_t* classloader = class_get_classloader(m->clazz);
400 // Resolve the native method name from the native libraries.
401 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
402 symbol = libraries.resolve_symbol(name, classloader);
405 symbol = libraries.resolve_symbol(newname, classloader);
407 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
408 if (symbol == NULL) {
409 /* We can resolve the function directly from
410 java.lang.ClassLoader as it's a static function. */
411 /* XXX should be done in native_init */
413 methodinfo* method_findNative =
414 class_resolveclassmethod(class_java_lang_ClassLoader,
416 utf_java_lang_ClassLoader_java_lang_String__J,
417 class_java_lang_ClassLoader,
420 if (method_findNative == NULL)
423 // Try the normal name.
424 java_handle_t* s = javastring_new(name);
425 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
427 // If not found, try the mangled name.
428 if (symbol == NULL) {
429 s = javastring_new(newname);
430 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
440 // If not found already, try to find the native method symbol in
441 // the native methods registered with the VM.
442 if (symbol == NULL) {
443 symbol = find_registered_method(m);
447 printf("internal ]\n");
450 #if defined(ENABLE_JVMTI)
451 /* fire Native Method Bind event */
452 if (jvmti) jvmti_NativeMethodBind(m, f, &f);
455 // Symbol not found? Throw an exception.
456 if (symbol == NULL) {
458 printf("failed ]\n");
460 exceptions_throw_unsatisfiedlinkerror(m->name);
468 * Try to find the given method in the native methods registered with
471 * @param m Method structure.
473 * @return Pointer to function if found, NULL otherwise.
475 void* NativeMethods::find_registered_method(methodinfo* m)
478 std::set<NativeMethod>::iterator it = _methods.find(nm);
480 if (it == _methods.end())
483 return (*it).get_function();
488 * Open this native library.
490 * @return File handle on success, NULL otherwise.
492 #if defined(ENABLE_DL)
493 void* NativeLibrary::open()
495 if (opt_verbosejni) {
496 printf("[Loading native library ");
497 utf_display_printable_ascii(_filename);
502 assert(_filename != NULL);
504 // Try to open the library.
505 _handle = os::dlopen(_filename->text, RTLD_LAZY);
507 if (_handle == NULL) {
509 printf("failed ]\n");
513 log_print("NativeLibrary::open: os::dlopen failed: ");
514 log_print(os::dlerror());
530 * Close this native library.
532 #if defined(ENABLE_DL)
533 void NativeLibrary::close()
535 if (opt_verbosejni) {
536 printf("[Unloading native library ");
537 /* utf_display_printable_ascii(filename); */
542 assert(_handle != NULL);
544 // Close the library.
545 int result = os::dlclose(_handle);
549 printf("failed ]\n");
553 log_print("NativeLibrary::close: os::dlclose failed: ");
554 log_print(os::dlerror());
566 * Load this native library and initialize it, if possible.
568 * @param env JNI environment.
570 * @return true if library loaded successfully, false otherwise.
572 bool NativeLibrary::load(JNIEnv* env)
574 #if defined(ENABLE_DL)
575 if (_filename == NULL) {
576 exceptions_throw_nullpointerexception();
580 // Is the library already loaded?
590 # if defined(ENABLE_JNI)
591 // Resolve JNI_OnLoad function.
592 void* onload = os::dlsym(_handle, "JNI_OnLoad");
594 if (onload != NULL) {
595 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
598 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
602 jint version = JNI_OnLoad(vm, NULL);
604 // If the version is not 1.2 and not 1.4 the library cannot be
606 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
607 os::dlclose(_handle);
613 // Insert the library name into the native library table.
614 NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
615 nativelibraries.add(*this);
619 os::abort("NativeLibrary::load: Not available in this configuration.");
621 // Keep the compiler happy.
628 * Checks if this native library is loaded.
630 * @return true if loaded, false otherwise.
632 #if defined(ENABLE_DL)
633 bool NativeLibrary::is_loaded()
635 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
636 return libraries.is_loaded(*this);
642 * Resolve the given symbol in this native library.
644 * @param symbolname Symbol name.
646 * @return Pointer to symbol if found, NULL otherwise.
648 void* NativeLibrary::resolve_symbol(utf* symbolname) const
650 return os::dlsym(_handle, symbolname->text);
655 * Add the given native library to the native libraries table.
657 * @param library Native library to insert.
659 #if defined(ENABLE_DL)
660 void NativeLibraries::add(NativeLibrary& library)
662 // Make the container thread-safe.
665 // XXX Check for double entries.
666 // Insert the native library.
667 _libraries.insert(std::make_pair(library.get_classloader(), library));
675 * Checks if the given native library is loaded.
677 * @param library Native library.
679 * @return true if loaded, false otherwise.
681 bool NativeLibraries::is_loaded(NativeLibrary& library)
683 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
685 // No entry for the classloader was found (the range has length
687 if (its.first == its.second)
690 MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
692 // No matching entry in the range found.
693 if (it == its.second)
701 * Try to find a symbol with the given name in all loaded native
702 * libraries defined by classloader.
704 * @param symbolname Name of the symbol to find.
705 * @param classloader Defining classloader.
707 * @return Pointer to symbol if found, NULL otherwise.
709 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
711 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
713 // No entry for the classloader was found (the range has length
715 if (its.first == its.second)
718 for (MAP::const_iterator it = its.first; it != its.second; it++) {
719 const NativeLibrary& library = (*it).second;
720 void* symbol = library.resolve_symbol(symbolname);
730 /* native_new_and_init *********************************************************
732 Creates a new object on the heap and calls the initializer.
733 Returns the object pointer or NULL if memory is exhausted.
735 *******************************************************************************/
737 java_handle_t *native_new_and_init(classinfo *c)
743 vm_abort("native_new_and_init: c == NULL");
752 /* try to find the initializer */
754 m = class_findmethod(c, utf_init, utf_void__void);
756 /* ATTENTION: returning the object here is ok, since the class may
757 not have an initializer */
762 /* call initializer */
764 (void) vm_call_method(m, o);
770 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
776 vm_abort("native_new_and_init_string: c == NULL");
785 /* find initializer */
787 m = class_findmethod(c, utf_init, utf_java_lang_String__void);
789 /* initializer not found */
794 /* call initializer */
796 (void) vm_call_method(m, o, s);
803 * These are local overrides for various environment variables in Emacs.
804 * Please do not remove this and leave it at the end of the file, where
805 * Emacs will automagically detect them.
806 * ---------------------------------------------------------------------
809 * indent-tabs-mode: t
813 * vim:noexpandtab:sw=4:ts=4: