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/hook.hpp"
51 #include "vm/loader.hpp"
52 #include "vm/options.h"
54 #include "vm/resolve.hpp"
55 #include "vm/string.hpp"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.hpp"
62 /* native_make_overloaded_function *********************************************
66 *******************************************************************************/
68 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
77 utf_ptr = descriptor->text;
78 namelen = strlen(name->text) + strlen("__") + strlen("0");
80 /* calculate additional length */
82 while ((c = utf_nextu2(&utf_ptr)) != ')') {
99 while (utf_nextu2(&utf_ptr) != ';')
110 /* reallocate memory */
112 i = strlen(name->text);
114 newname = MNEW(char, namelen);
115 MCOPY(newname, name->text, char, i);
117 utf_ptr = descriptor->text;
122 while ((c = utf_nextu2(&utf_ptr)) != ')') {
140 while ((c = utf_nextu2(&utf_ptr)) != ';')
141 if (((c >= 'a') && (c <= 'z')) ||
142 ((c >= 'A') && (c <= 'Z')) ||
143 ((c >= '0') && (c <= '9')))
161 /* make a utf-string */
163 u = utf_new_char(newname);
167 MFREE(newname, char, namelen);
173 /* native_insert_char **********************************************************
175 Inserts the passed UTF character into the native method name. If
176 necessary it is escaped properly.
178 *******************************************************************************/
180 static s4 native_insert_char(char *name, u4 pos, u2 c)
188 /* replace '/' or '.' with '_' */
193 /* escape sequence for '_' is '_1' */
199 /* escape sequence for ';' is '_2' */
205 /* escape sequence for '[' is '_1' */
214 /* unicode character */
218 for (i = 0; i < 4; ++i) {
220 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
229 /* return the new buffer index */
235 /* native_method_symbol ********************************************************
237 Generate a method-symbol string out of the class name and the
240 *******************************************************************************/
242 static utf *native_method_symbol(utf *classname, utf *methodname)
252 /* Calculate length of native function name. We multiply the
253 class and method name length by 6 as this is the maxium
254 escape-sequence that can be generated (unicode). */
258 utf_get_number_of_u2s(classname) * 6 +
260 utf_get_number_of_u2s(methodname) * 6 +
263 /* allocate memory */
265 name = MNEW(char, namelen);
267 /* generate name of native functions */
269 strcpy(name, "Java_");
270 pos = strlen("Java_");
272 utf_ptr = classname->text;
273 utf_endptr = UTF_END(classname);
275 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
277 pos = native_insert_char(name, pos, c);
280 /* seperator between class and method */
284 utf_ptr = methodname->text;
285 utf_endptr = UTF_END(methodname);
287 for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
289 pos = native_insert_char(name, pos, c);
296 /* check for an buffer overflow */
298 assert((int32_t) pos <= namelen);
300 /* make a utf-string */
302 u = utf_new_char(name);
306 MFREE(name, char, namelen);
312 bool operator< (const NativeMethod& first, const NativeMethod& second)
314 if (first._classname < second._classname)
316 else if (first._classname > second._classname)
319 if (first._name < second._name)
321 else if (first._name > second._name)
324 if (first._descriptor < second._descriptor)
326 else if (first._descriptor > second._descriptor)
329 // All pointers are equal, we have found the entry.
335 * Register native methods with the VM. This is done by inserting
336 * them into the native method table.
339 * @param methods Native methods array.
340 * @param count Number of methods in the array.
342 void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
344 // Insert all methods passed */
345 for (size_t i = 0; i < count; i++) {
346 if (opt_verbosejni) {
347 printf("[Registering JNI native method ");
348 utf_display_printable_ascii_classname(classname);
349 printf(".%s]\n", methods[i].name);
352 // Generate the UTF8 names.
353 utf* name = utf_new_char(methods[i].name);
354 utf* signature = utf_new_char(methods[i].signature);
356 NativeMethod nm(classname, name, signature, methods[i].fnPtr);
358 // Insert the method into the table.
365 * Resolves a native method, maybe from a dynamic library.
367 * @param m Method structure of the native Java method to resolve.
369 * @return Pointer to the resolved method (symbol).
371 void* NativeMethods::resolve_method(methodinfo* m)
374 if (opt_verbosejni) {
375 printf("[Dynamic-linking native method ");
376 utf_display_printable_ascii_classname(m->clazz->name);
378 utf_display_printable_ascii(m->name);
382 /* generate method symbol string */
384 utf* name = native_method_symbol(m->clazz->name, m->name);
386 /* generate overloaded function (having the types in it's name) */
388 utf* newname = native_make_overloaded_function(name, m->descriptor);
390 // Try to find the symbol.
393 // Try to find the native method symbol in the native methods registered
395 symbol = find_registered_method(m);
399 printf("internal ]\n");
401 #if defined(ENABLE_DL)
402 classloader_t* classloader;
403 if (symbol == NULL) {
404 // Get the classloader.
405 classloader = class_get_classloader(m->clazz);
407 // Resolve the native method name from the native libraries.
408 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
410 symbol = libraries.resolve_symbol(name, classloader);
413 symbol = libraries.resolve_symbol(newname, classloader);
416 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
417 if (symbol == NULL) {
418 /* We can resolve the function directly from
419 java.lang.ClassLoader as it's a static function. */
420 /* XXX should be done in native_init */
422 methodinfo* method_findNative =
423 class_resolveclassmethod(class_java_lang_ClassLoader,
425 utf_java_lang_ClassLoader_java_lang_String__J,
426 class_java_lang_ClassLoader,
429 if (method_findNative != NULL) {
430 // Try the normal name.
431 java_handle_t* s = javastring_new(name);
432 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
434 // If not found, try the mangled name.
435 if (symbol == NULL) {
436 s = javastring_new(newname);
437 symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
448 // Symbol not found? Throw an exception.
449 if (symbol == NULL) {
451 printf("failed ]\n");
453 exceptions_throw_unsatisfiedlinkerror(m->name);
456 // Hook point just after method resolving finished.
457 Hook::native_resolved(m, symbol, &symbol);
464 * Try to find the given method in the native methods registered with
467 * @param m Method structure.
469 * @return Pointer to function if found, NULL otherwise.
471 void* NativeMethods::find_registered_method(methodinfo* m)
474 std::set<NativeMethod>::iterator it = _methods.find(nm);
476 if (it == _methods.end())
479 return (*it).get_function();
484 * Open this native library.
486 * @return File handle on success, NULL otherwise.
488 #if defined(ENABLE_DL)
489 void* NativeLibrary::open()
491 if (opt_verbosejni) {
492 printf("[Loading native library ");
493 utf_display_printable_ascii(_filename);
498 assert(_filename != NULL);
500 // Try to open the library.
501 _handle = os::dlopen(_filename->text, RTLD_LAZY);
503 if (_handle == NULL) {
505 printf("failed ]\n");
507 if (opt_PrintWarnings)
508 log_println("NativeLibrary::open: os::dlopen failed: %s", 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");
543 if (opt_PrintWarnings)
544 log_println("NativeLibrary::close: os::dlclose failed: %s", os::dlerror());
554 * Load this native library and initialize it, if possible.
556 * @param env JNI environment.
558 * @return true if library loaded successfully, false otherwise.
560 bool NativeLibrary::load(JNIEnv* env)
562 #if defined(ENABLE_DL)
563 if (_filename == NULL) {
564 exceptions_throw_nullpointerexception();
568 // Is the library already loaded?
578 # if defined(ENABLE_JNI)
579 // Resolve JNI_OnLoad function.
580 void* onload = os::dlsym(_handle, "JNI_OnLoad");
582 if (onload != NULL) {
583 JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
586 JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
590 jint version = JNI_OnLoad(vm, NULL);
592 // If the version is not 1.2 and not 1.4 the library cannot be
594 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
595 os::dlclose(_handle);
601 // Insert the library name into the native library table.
602 NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
603 nativelibraries.add(*this);
607 os::abort("NativeLibrary::load: Not available in this configuration.");
609 // Keep the compiler happy.
616 * Checks if this native library is loaded.
618 * @return true if loaded, false otherwise.
620 #if defined(ENABLE_DL)
621 bool NativeLibrary::is_loaded()
623 NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
624 return libraries.is_loaded(*this);
630 * Resolve the given symbol in this native library.
632 * @param symbolname Symbol name.
634 * @return Pointer to symbol if found, NULL otherwise.
636 void* NativeLibrary::resolve_symbol(utf* symbolname) const
638 return os::dlsym(_handle, symbolname->text);
643 * Add the given native library to the native libraries table.
645 * @param library Native library to insert.
647 #if defined(ENABLE_DL)
648 void NativeLibraries::add(NativeLibrary& library)
650 // Make the container thread-safe.
653 // XXX Check for double entries.
654 // Insert the native library.
655 _libraries.insert(std::make_pair(library.get_classloader(), library));
663 * Checks if the given native library is loaded.
665 * @param library Native library.
667 * @return true if loaded, false otherwise.
669 bool NativeLibraries::is_loaded(NativeLibrary& library)
671 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
673 // No entry for the classloader was found (the range has length
675 if (its.first == its.second)
678 MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
680 // No matching entry in the range found.
681 if (it == its.second)
689 * Try to find a symbol with the given name in all loaded native
690 * libraries defined by classloader.
692 * @param symbolname Name of the symbol to find.
693 * @param classloader Defining classloader.
695 * @return Pointer to symbol if found, NULL otherwise.
697 void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
699 std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
701 // No entry for the classloader was found (the range has length
703 if (its.first == its.second)
706 for (MAP::const_iterator it = its.first; it != its.second; it++) {
707 const NativeLibrary& library = (*it).second;
708 void* symbol = library.resolve_symbol(symbolname);
719 * Registers a new native agent by specified by it's library name
720 * and with an optional options string.
722 * @param library Name of the native agent library.
723 * @param options The options string or NULL if not specified.
725 #if defined(ENABLE_JVMTI)
726 void NativeAgents::register_agent_library(char* library, char* options)
728 NativeAgent na(library, options);
730 // Insert native agent into list of agents.
731 _agents.push_back(na);
737 * Registers a new native agent by specified by a path to it's library
738 * and with an optional options string.
740 * @param path Path of the native agent library.
741 * @param options The options string or NULL if not specified.
743 #if defined(ENABLE_JVMTI)
744 void NativeAgents::register_agent_path(char* path, char* options)
746 os::abort("NativeAgents::register_agent_library: Implement me!");
752 * Loads all registered native agents and in turn calls their exported
753 * start-up functions (Agent_OnLoad). If one of the agents reports an
754 * error during start-up, the loading is stopped.
756 * @return True if all agents were loaded successfully, false if
757 * one of them was not found or reported an error.
759 #if defined(ENABLE_JVMTI)
760 bool NativeAgents::load_agents()
762 // Iterate over all registered agents.
763 for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
764 NativeAgent& na = *(it);
766 // Construct agent library name.
768 os::strlen(NATIVE_LIBRARY_PREFIX) +
769 os::strlen(na.get_library()) +
770 os::strlen(NATIVE_LIBRARY_SUFFIX) +
773 char* p = MNEW(char, len);
775 os::strcpy(p, NATIVE_LIBRARY_PREFIX);
776 os::strcat(p, na.get_library());
777 os::strcat(p, NATIVE_LIBRARY_SUFFIX);
779 utf* u = utf_new_char(p);
783 // Construct new native library.
786 // Try to open the library.
787 if (nl.open() == NULL)
790 // Resolve Agent_OnLoad function.
791 void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
793 // Call Agent_OnLoad function if present.
794 if (onload != NULL) {
795 JNIEXPORT jint (JNICALL *Agent_OnLoad) (JavaVM*, char*, void*);
796 JavaVM* vm = VM::get_current()->get_javavm();
798 Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
800 jint result = Agent_OnLoad(vm, na.get_options(), NULL);
802 // Check for error in Agent_OnLoad.
809 // According to the interface spec, the library _must_ export
810 // a start-up function.
812 log_println("NativeAgents::load_agents: Native agent library does not export Agent_OnLoad");
822 /* native_new_and_init *********************************************************
824 Creates a new object on the heap and calls the initializer.
825 Returns the object pointer or NULL if memory is exhausted.
827 *******************************************************************************/
829 java_handle_t *native_new_and_init(classinfo *c)
835 vm_abort("native_new_and_init: c == NULL");
844 /* try to find the initializer */
846 m = class_findmethod(c, utf_init, utf_void__void);
848 /* ATTENTION: returning the object here is ok, since the class may
849 not have an initializer */
854 /* call initializer */
856 (void) vm_call_method(m, o);
862 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
868 vm_abort("native_new_and_init_string: c == NULL");
877 /* find initializer */
879 m = class_findmethod(c, utf_init, utf_java_lang_String__void);
881 /* initializer not found */
886 /* call initializer */
888 (void) vm_call_method(m, o, s);
895 * These are local overrides for various environment variables in Emacs.
896 * Please do not remove this and leave it at the end of the file, where
897 * Emacs will automagically detect them.
898 * ---------------------------------------------------------------------
901 * indent-tabs-mode: t
905 * vim:noexpandtab:sw=4:ts=4: