1 /* src/native/native.cpp - native library support
3 Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
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"
61 /* native_make_overloaded_function *********************************************
65 *******************************************************************************/
67 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
76 utf_ptr = descriptor->text;
77 namelen = strlen(name->text) + strlen("__") + strlen("0");
79 /* calculate additional length */
81 while ((c = utf_nextu2(&utf_ptr)) != ')') {
98 while (utf_nextu2(&utf_ptr) != ';')
109 /* reallocate memory */
111 i = strlen(name->text);
113 newname = MNEW(char, namelen);
114 MCOPY(newname, name->text, char, i);
116 utf_ptr = descriptor->text;
121 while ((c = utf_nextu2(&utf_ptr)) != ')') {
139 while ((c = utf_nextu2(&utf_ptr)) != ';')
140 if (((c >= 'a') && (c <= 'z')) ||
141 ((c >= 'A') && (c <= 'Z')) ||
142 ((c >= '0') && (c <= '9')))
160 /* make a utf-string */
162 u = utf_new_char(newname);
166 MFREE(newname, char, namelen);
172 /* native_insert_char **********************************************************
174 Inserts the passed UTF character into the native method name. If
175 necessary it is escaped properly.
177 *******************************************************************************/
179 static s4 native_insert_char(char *name, u4 pos, u2 c)
187 /* replace '/' or '.' with '_' */
192 /* escape sequence for '_' is '_1' */
198 /* escape sequence for ';' is '_2' */
204 /* escape sequence for '[' is '_1' */
213 /* unicode character */
217 for (i = 0; i < 4; ++i) {
219 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
228 /* return the new buffer index */
234 /* native_method_symbol ********************************************************
236 Generate a method-symbol string out of the class name and the
239 *******************************************************************************/
241 static utf *native_method_symbol(utf *classname, utf *methodname)
251 /* Calculate length of native function name. We multiply the
252 class and method name length by 6 as this is the maxium
253 escape-sequence that can be generated (unicode). */
257 utf_get_number_of_u2s(classname) * 6 +
259 utf_get_number_of_u2s(methodname) * 6 +
262 /* allocate memory */
264 name = MNEW(char, namelen);
266 /* generate name of native functions */
268 strcpy(name, "Java_");
269 pos = strlen("Java_");
271 utf_ptr = classname->text;
272 utf_endptr = UTF_END(classname);
274 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
276 pos = native_insert_char(name, pos, c);
279 /* seperator between class and method */
283 utf_ptr = methodname->text;
284 utf_endptr = UTF_END(methodname);
286 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
288 pos = native_insert_char(name, pos, c);
295 /* check for an buffer overflow */
297 assert((int32_t) pos <= namelen);
299 /* make a utf-string */
301 u = utf_new_char(name);
305 MFREE(name, char, namelen);
311 bool operator< (const NativeMethod& first, const NativeMethod& second)
313 if (first._classname < second._classname)
315 else if (first._classname > second._classname)
318 if (first._name < second._name)
320 else if (first._name > second._name)
323 if (first._descriptor < second._descriptor)
325 else if (first._descriptor > second._descriptor)
328 // All pointers are equal, we have found the entry.
334 * Register native methods with the VM. This is done by inserting
335 * them into the native method table.
338 * @param methods Native methods array.
339 * @param count Number of methods in the array.
341 void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
343 // Insert all methods passed */
344 for (size_t i = 0; i < count; i++) {
345 if (opt_verbosejni) {
346 printf("[Registering JNI native method ");
347 utf_display_printable_ascii_classname(classname);
348 printf(".%s]\n", methods[i].name);
351 // Generate the UTF8 names.
352 utf* name = utf_new_char(methods[i].name);
353 utf* signature = utf_new_char(methods[i].signature);
355 NativeMethod nm(classname, name, signature, methods[i].fnPtr);
357 // Insert the method into the table.
364 * Resolves a native method, maybe from a dynamic library.
366 * @param m Method structure of the native Java method to resolve.
368 * @return Pointer to the resolved method (symbol).
370 void* NativeMethods::resolve_method(methodinfo* m)
373 if (opt_verbosejni) {
374 printf("[Dynamic-linking native method ");
375 utf_display_printable_ascii_classname(m->clazz->name);
377 utf_display_printable_ascii(m->name);
381 /* generate method symbol string */
383 utf* name = native_method_symbol(m->clazz->name, m->name);
385 /* generate overloaded function (having the types in it's name) */
387 utf* newname = native_make_overloaded_function(name, m->descriptor);
389 // Try to find the symbol.
392 // Try to find the native method symbol in the native methods registered
394 symbol = find_registered_method(m);
398 printf("internal ]\n");
400 #if defined(ENABLE_DL)
401 classloader_t* classloader;
402 if (symbol == NULL) {
403 // Get the classloader.
404 classloader = class_get_classloader(m->clazz);
406 // Resolve the native method name from the native libraries.
407 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
409 symbol = libraries.resolve_symbol(name, classloader);
412 symbol = libraries.resolve_symbol(newname, classloader);
415 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
416 if (symbol == NULL) {
417 /* We can resolve the function directly from
418 java.lang.ClassLoader as it's a static function. */
419 /* XXX should be done in native_init */
421 methodinfo* method_findNative =
422 class_resolveclassmethod(class_java_lang_ClassLoader,
424 utf_java_lang_ClassLoader_java_lang_String__J,
425 class_java_lang_ClassLoader,
428 if (method_findNative != NULL) {
429 // Try the normal name.
430 java_handle_t* s = javastring_new(name);
431 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
433 // If not found, try the mangled name.
434 if (symbol == NULL) {
435 s = javastring_new(newname);
436 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
447 // Symbol not found? Throw an exception.
448 if (symbol == NULL) {
450 printf("failed ]\n");
452 exceptions_throw_unsatisfiedlinkerror(m->name);
460 * Try to find the given method in the native methods registered with
463 * @param m Method structure.
465 * @return Pointer to function if found, NULL otherwise.
467 void* NativeMethods::find_registered_method(methodinfo* m)
470 std::set<NativeMethod>::iterator it = _methods.find(nm);
472 if (it == _methods.end())
475 return (*it).get_function();
480 * Open this native library.
482 * @return File handle on success, NULL otherwise.
484 #if defined(ENABLE_DL)
485 void* NativeLibrary::open()
487 if (opt_verbosejni) {
488 printf("[Loading native library ");
489 utf_display_printable_ascii(_filename);
494 assert(_filename != NULL);
496 // Try to open the library.
497 _handle = os::dlopen(_filename->text, RTLD_LAZY);
499 if (_handle == NULL) {
501 printf("failed ]\n");
505 log_print("NativeLibrary::open: os::dlopen failed: ");
506 log_print(os::dlerror());
522 * Close this native library.
524 #if defined(ENABLE_DL)
525 void NativeLibrary::close()
527 if (opt_verbosejni) {
528 printf("[Unloading native library ");
529 /* utf_display_printable_ascii(filename); */
534 assert(_handle != NULL);
536 // Close the library.
537 int result = os::dlclose(_handle);
541 printf("failed ]\n");
545 log_print("NativeLibrary::close: os::dlclose failed: ");
546 log_print(os::dlerror());
558 * Load this native library and initialize it, if possible.
560 * @param env JNI environment.
562 * @return true if library loaded successfully, false otherwise.
564 bool NativeLibrary::load(JNIEnv* env)
566 #if defined(ENABLE_DL)
567 if (_filename == NULL) {
568 exceptions_throw_nullpointerexception();
572 // Is the library already loaded?
582 # if defined(ENABLE_JNI)
583 // Resolve JNI_OnLoad function.
584 void* onload = os::dlsym(_handle, "JNI_OnLoad");
586 if (onload != NULL) {
587 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
590 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
594 jint version = JNI_OnLoad(vm, NULL);
596 // If the version is not 1.2 and not 1.4 the library cannot be
598 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
599 os::dlclose(_handle);
605 // Insert the library name into the native library table.
606 NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
607 nativelibraries.add(*this);
611 os::abort("NativeLibrary::load: Not available in this configuration.");
613 // Keep the compiler happy.
620 * Checks if this native library is loaded.
622 * @return true if loaded, false otherwise.
624 #if defined(ENABLE_DL)
625 bool NativeLibrary::is_loaded()
627 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
628 return libraries.is_loaded(*this);
634 * Resolve the given symbol in this native library.
636 * @param symbolname Symbol name.
638 * @return Pointer to symbol if found, NULL otherwise.
640 void* NativeLibrary::resolve_symbol(utf* symbolname) const
642 return os::dlsym(_handle, symbolname->text);
647 * Add the given native library to the native libraries table.
649 * @param library Native library to insert.
651 #if defined(ENABLE_DL)
652 void NativeLibraries::add(NativeLibrary& library)
654 // Make the container thread-safe.
657 // XXX Check for double entries.
658 // Insert the native library.
659 _libraries.insert(std::make_pair(library.get_classloader(), library));
667 * Checks if the given native library is loaded.
669 * @param library Native library.
671 * @return true if loaded, false otherwise.
673 bool NativeLibraries::is_loaded(NativeLibrary& library)
675 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
677 // No entry for the classloader was found (the range has length
679 if (its.first == its.second)
682 MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
684 // No matching entry in the range found.
685 if (it == its.second)
693 * Try to find a symbol with the given name in all loaded native
694 * libraries defined by classloader.
696 * @param symbolname Name of the symbol to find.
697 * @param classloader Defining classloader.
699 * @return Pointer to symbol if found, NULL otherwise.
701 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
703 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
705 // No entry for the classloader was found (the range has length
707 if (its.first == its.second)
710 for (MAP::const_iterator it = its.first; it != its.second; it++) {
711 const NativeLibrary& library = (*it).second;
712 void* symbol = library.resolve_symbol(symbolname);
723 * Registers a new native agent by specified by it's library name
724 * and with an optional options string.
726 * @param library Name of the native agent library.
727 * @param options The options string or NULL if not specified.
729 #if defined(ENABLE_JVMTI)
730 void NativeAgents::register_agent_library(char* library, char* options)
732 NativeAgent na(library, options);
734 // Insert native agent into list of agents.
735 _agents.push_back(na);
741 * Registers a new native agent by specified by a path to it's library
742 * and with an optional options string.
744 * @param path Path of the native agent library.
745 * @param options The options string or NULL if not specified.
747 #if defined(ENABLE_JVMTI)
748 void NativeAgents::register_agent_path(char* path, char* options)
750 os::abort("NativeAgents::register_agent_library: Implement me!");
756 * Loads all registered native agents and in turn calls their exported
757 * start-up functions (Agent_OnLoad). If one of the agents reports an
758 * error during start-up, the loading is stopped.
760 * @return True if all agents were loaded successfully, false if
761 * one of them was not found or reported an error.
763 #if defined(ENABLE_JVMTI)
764 bool NativeAgents::load_agents()
766 // Iterate over all registered agents.
767 for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
768 NativeAgent& na = *(it);
770 // Construct agent library name.
772 os::strlen(NATIVE_LIBRARY_PREFIX) +
773 os::strlen(na.get_library()) +
774 os::strlen(NATIVE_LIBRARY_SUFFIX) +
777 char* p = MNEW(char, len);
779 os::strcpy(p, NATIVE_LIBRARY_PREFIX);
780 os::strcat(p, na.get_library());
781 os::strcat(p, NATIVE_LIBRARY_SUFFIX);
783 utf* u = utf_new_char(p);
787 // Construct new native library.
790 // Try to open the library.
791 if (nl.open() == NULL)
794 // Resolve Agent_OnLoad function.
795 void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
797 // Call Agent_OnLoad function if present.
798 if (onload != NULL) {
799 JNIEXPORT jint (JNICALL *Agent_OnLoad) (JavaVM*, char*, void*);
800 JavaVM* vm = VM::get_current()->get_javavm();
802 Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
804 jint result = Agent_OnLoad(vm, na.get_options(), NULL);
806 // Check for error in Agent_OnLoad.
813 // According to the interface spec, the library _must_ export
814 // a start-up function.
816 log_println("NativeAgents::load_agents: Native agent library does not export Agent_OnLoad");
826 /* native_new_and_init *********************************************************
828 Creates a new object on the heap and calls the initializer.
829 Returns the object pointer or NULL if memory is exhausted.
831 *******************************************************************************/
833 java_handle_t *native_new_and_init(classinfo *c)
839 vm_abort("native_new_and_init: c == NULL");
848 /* try to find the initializer */
850 m = class_findmethod(c, utf_init, utf_void__void);
852 /* ATTENTION: returning the object here is ok, since the class may
853 not have an initializer */
858 /* call initializer */
860 (void) vm_call_method(m, o);
866 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
872 vm_abort("native_new_and_init_string: c == NULL");
881 /* find initializer */
883 m = class_findmethod(c, utf_init, utf_java_lang_String__void);
885 /* initializer not found */
890 /* call initializer */
892 (void) vm_call_method(m, o, s);
899 * These are local overrides for various environment variables in Emacs.
900 * Please do not remove this and leave it at the end of the file, where
901 * Emacs will automagically detect them.
902 * ---------------------------------------------------------------------
905 * indent-tabs-mode: t
909 * vim:noexpandtab:sw=4:ts=4: