* Removed all Id tags.
[cacao.git] / src / native / native.c
index 97391cda697281fdfe6a8f60368c4af1d243042e..37f86f45c72fbd3da3442479f1440b929d0d0271 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/native.c - table of native functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-            Roman Obermaisser
-            Andreas Krall
-
-   Changes: Christian Thalinger
-
-   $Id: native.c 5031 2006-06-14 18:36:22Z motse $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <ctype.h>
 
-#if !defined(WITH_STATIC_CLASSPATH)
+#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
 # include <ltdl.h>
 #endif
 
+#include <stdint.h>
+
 #include "vm/types.h"
 
 #include "mm/memory.h"
+
 #include "native/jni.h"
 #include "native/native.h"
-#include "native/include/java_lang_Throwable.h"
+
+#include "native/vm/nativevm.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/avl.h"
+#include "toolbox/hashtable.h"
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/hashtable.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/resolve.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vm/resolve.h"
 
-/* include table of native functions ******************************************/
-
-#include "native/include/java_lang_Cloneable.h"
-#include "native/include/java_util_Properties.h"
-#include "native/include/java_io_InputStream.h"
-#include "native/include/java_io_PrintStream.h"
-
-#include "native/include/gnu_classpath_VMStackWalker.h"
-#include "native/include/gnu_classpath_VMSystemProperties.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_VMClass.h"
-#include "native/include/java_lang_VMClassLoader.h"
-#include "native/include/java_lang_VMObject.h"
-#include "native/include/java_lang_VMRuntime.h"
-#include "native/include/java_lang_VMString.h"
-#include "native/include/java_lang_VMSystem.h"
-#include "native/include/java_lang_VMThread.h"
-#include "native/include/java_lang_VMThrowable.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_Field.h"
-#include "native/include/java_lang_reflect_Method.h"
-#include "native/include/java_lang_reflect_VMProxy.h"
-#include "native/include/java_security_VMAccessController.h"
 #if defined(ENABLE_JVMTI)
-#include "native/include/gnu_classpath_jdwp_event_EventRequest.h"
-#include "native/include/java_nio_ByteBuffer.h"
-#include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
-#include "native/include/gnu_classpath_jdwp_VMFrame.h"
-#include "native/include/gnu_classpath_jdwp_VMMethod.h"
+#include "native/jvmti/cacaodbg.h"
 #endif
 
-#if defined(WITH_STATIC_CLASSPATH)
 
-/* these are required to prevent compiler warnings */
-
-#include "native/include/java_net_DatagramPacket.h"
-#include "native/include/java_net_InetAddress.h"
-#include "native/include/java_net_SocketImpl.h"
-
-#include "native/include/gnu_java_net_PlainDatagramSocketImpl.h"
-#include "native/include/gnu_java_net_PlainSocketImpl.h"
-#include "native/include/gnu_java_nio_PipeImpl.h"
-#include "native/include/gnu_java_nio_channels_FileChannelImpl.h"
-#include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h"
-#include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h"
-#include "native/include/java_lang_VMProcess.h"
-#include "native/include/java_nio_MappedByteBufferImpl.h"
-#include "native/include/java_nio_channels_spi_SelectorProvider.h"
-
-/* now include the native table */
-
-#include "native/nativetable.inc"
-
-#else /* defined(WITH_STATIC_CLASSPATH) */
-
-/* Ensure that symbols for functions implemented within CACAO are used
-   and exported to dlopen. */
-
-static functionptr dummynativetable[] = {
-       (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
-
-       (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
-
-       (functionptr) Java_java_lang_VMClass_isInstance,
-       (functionptr) Java_java_lang_VMClass_isAssignableFrom,
-       (functionptr) Java_java_lang_VMClass_isInterface,
-       (functionptr) Java_java_lang_VMClass_isPrimitive,
-       (functionptr) Java_java_lang_VMClass_getName,
-       (functionptr) Java_java_lang_VMClass_getSuperclass,
-       (functionptr) Java_java_lang_VMClass_getInterfaces,
-       (functionptr) Java_java_lang_VMClass_getComponentType,
-       (functionptr) Java_java_lang_VMClass_getModifiers,
-       (functionptr) Java_java_lang_VMClass_getDeclaringClass,
-       (functionptr) Java_java_lang_VMClass_getDeclaredClasses,
-       (functionptr) Java_java_lang_VMClass_getDeclaredFields,
-       (functionptr) Java_java_lang_VMClass_getDeclaredMethods,
-       (functionptr) Java_java_lang_VMClass_getDeclaredConstructors,
-       (functionptr) Java_java_lang_VMClass_getClassLoader,
-       (functionptr) Java_java_lang_VMClass_forName,
-       (functionptr) Java_java_lang_VMClass_isArray,
-       (functionptr) Java_java_lang_VMClass_throwException,
-
-       (functionptr) Java_java_lang_VMClassLoader_defineClass,
-       (functionptr) Java_java_lang_VMClassLoader_resolveClass,
-       (functionptr) Java_java_lang_VMClassLoader_loadClass,
-       (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass,
-       (functionptr) Java_java_lang_VMClassLoader_nativeGetResources,
-       (functionptr) Java_java_lang_VMClassLoader_findLoadedClass,
-
-       (functionptr) Java_java_lang_VMObject_getClass,
-       (functionptr) Java_java_lang_VMObject_clone,
-       (functionptr) Java_java_lang_VMObject_notify,
-       (functionptr) Java_java_lang_VMObject_notifyAll,
-       (functionptr) Java_java_lang_VMObject_wait,
-
-       (functionptr) Java_java_lang_VMRuntime_availableProcessors,
-       (functionptr) Java_java_lang_VMRuntime_freeMemory,
-       (functionptr) Java_java_lang_VMRuntime_totalMemory,
-       (functionptr) Java_java_lang_VMRuntime_maxMemory,
-       (functionptr) Java_java_lang_VMRuntime_gc,
-       (functionptr) Java_java_lang_VMRuntime_runFinalization,
-       (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit,
-       (functionptr) Java_java_lang_VMRuntime_traceInstructions,
-       (functionptr) Java_java_lang_VMRuntime_traceMethodCalls,
-       (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit,
-       (functionptr) Java_java_lang_VMRuntime_exit,
-       (functionptr) Java_java_lang_VMRuntime_nativeLoad,
-       (functionptr) Java_java_lang_VMRuntime_mapLibraryName,
-
-       (functionptr) Java_java_lang_VMString_intern,
-
-       (functionptr) Java_java_lang_VMSystem_arraycopy,
-       (functionptr) Java_java_lang_VMSystem_identityHashCode,
-
-       (functionptr) Java_java_lang_VMThread_start,
-       (functionptr) Java_java_lang_VMThread_interrupt,
-       (functionptr) Java_java_lang_VMThread_isInterrupted,
-       (functionptr) Java_java_lang_VMThread_suspend,
-       (functionptr) Java_java_lang_VMThread_resume,
-       (functionptr) Java_java_lang_VMThread_nativeSetPriority,
-       (functionptr) Java_java_lang_VMThread_nativeStop,
-       (functionptr) Java_java_lang_VMThread_currentThread,
-       (functionptr) Java_java_lang_VMThread_yield,
-       (functionptr) Java_java_lang_VMThread_interrupted,
-       (functionptr) Java_java_lang_VMThread_holdsLock,
-
-       (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
-       (functionptr) Java_java_lang_VMThrowable_getStackTrace,
-
-       (functionptr) Java_java_lang_reflect_Constructor_getModifiersInternal,
-       (functionptr) Java_java_lang_reflect_Constructor_constructNative,
-
-       (functionptr) Java_java_lang_reflect_Field_getModifiersInternal,
-       (functionptr) Java_java_lang_reflect_Field_getType,
-       (functionptr) Java_java_lang_reflect_Field_get,
-       (functionptr) Java_java_lang_reflect_Field_getBoolean,
-       (functionptr) Java_java_lang_reflect_Field_getByte,
-       (functionptr) Java_java_lang_reflect_Field_getChar,
-       (functionptr) Java_java_lang_reflect_Field_getShort,
-       (functionptr) Java_java_lang_reflect_Field_getInt,
-       (functionptr) Java_java_lang_reflect_Field_getLong,
-       (functionptr) Java_java_lang_reflect_Field_getFloat,
-       (functionptr) Java_java_lang_reflect_Field_getDouble,
-       (functionptr) Java_java_lang_reflect_Field_set,
-       (functionptr) Java_java_lang_reflect_Field_setBoolean,
-       (functionptr) Java_java_lang_reflect_Field_setByte,
-       (functionptr) Java_java_lang_reflect_Field_setChar,
-       (functionptr) Java_java_lang_reflect_Field_setShort,
-       (functionptr) Java_java_lang_reflect_Field_setInt,
-       (functionptr) Java_java_lang_reflect_Field_setLong,
-       (functionptr) Java_java_lang_reflect_Field_setFloat,
-       (functionptr) Java_java_lang_reflect_Field_setDouble,
-
-       (functionptr) Java_java_lang_reflect_Method_getModifiersInternal,
-       (functionptr) Java_java_lang_reflect_Method_getReturnType,
-       (functionptr) Java_java_lang_reflect_Method_getParameterTypes,
-       (functionptr) Java_java_lang_reflect_Method_getExceptionTypes,
-       (functionptr) Java_java_lang_reflect_Method_invokeNative,
-
-       (functionptr) Java_java_lang_reflect_VMProxy_getProxyClass,
-       (functionptr) Java_java_lang_reflect_VMProxy_getProxyData,
-       (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
-
-       (functionptr) Java_java_security_VMAccessController_getStack,
-#if defined(ENABLE_JVMTI)
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllClassMethods,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassMethod,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrame,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getLoadRequests,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSourceFile,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents,
-       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasses,
-       (functionptr) Java_gnu_classpath_jdwp_VMFrame_setValue,
-       (functionptr) Java_gnu_classpath_jdwp_VMFrame_getValue,
-       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getName,
-       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getSignature,
-       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getModifiers,
-       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getLineTable,
-       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getVariableTable
-#endif
-
-};
+/* include table of native functions ******************************************/
 
-#endif /* defined(WITH_STATIC_CLASSPATH) */
+#if defined(WITH_STATIC_CLASSPATH)
+# include "native/nativetable.inc"
+#endif
 
 
 /* tables for methods *********************************************************/
@@ -276,74 +91,478 @@ static bool nativecompdone = false;
 
 /* global variables ***********************************************************/
 
-#if !defined(WITH_STATIC_CLASSPATH)
+static avl_tree_t *tree_native_methods;
+
+#if defined(ENABLE_LTDL)
 static hashtable *hashtable_library;
-static lt_dlhandle mainhandle;
 #endif
 
 
-/* native_loadclasses **********************************************************
+/* prototypes *****************************************************************/
+
+static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
 
-   Load classes required for native methods.
+
+/* native_init *****************************************************************
+
+   Initializes the native subsystem.
 
 *******************************************************************************/
 
 bool native_init(void)
 {
+#if defined(ENABLE_LTDL)
+       /* initialize libltdl */
+
+       if (lt_dlinit())
+               vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
+
+       /* initialize library hashtable, 10 entries should be enough */
+
+       hashtable_library = NEW(hashtable);
+
+       hashtable_create(hashtable_library, 10);
+#endif
+
+       /* initialize the native methods table */
+
+       tree_native_methods = avl_create(&native_tree_native_methods_comparator);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* native_tree_native_methods_comparator ***************************************
+
+   Comparison function for AVL tree of native methods.
+
+   IN:
+       treenode....node in the tree
+          node........node to compare with tree-node
+
+   RETURN VALUE:
+       -1, 0, +1
+
+*******************************************************************************/
+
+static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
+{
+       const native_methods_node_t *treenmn;
+       const native_methods_node_t *nmn;
+
+       treenmn = treenode;
+       nmn     = node;
+
+       /* these are for walking the tree */
+
+       if (treenmn->classname < nmn->classname)
+               return -1;
+       else if (treenmn->classname > nmn->classname)
+               return 1;
+
+       if (treenmn->name < nmn->name)
+               return -1;
+       else if (treenmn->name > nmn->name)
+               return 1;
+
+       if (treenmn->descriptor < nmn->descriptor)
+               return -1;
+       else if (treenmn->descriptor > nmn->descriptor)
+               return 1;
+
+       /* all pointers are equal, we have found the entry */
+
+       return 0;
+}
+
+
+/* native_make_overloaded_function *********************************************
+
+   XXX
+
+*******************************************************************************/
+
 #if !defined(WITH_STATIC_CLASSPATH)
-       void *p;
+static utf *native_make_overloaded_function(utf *name, utf *descriptor)
+{
+       char *newname;
+       s4    namelen;
+       char *utf_ptr;
+       u2    c;
+       s4    i;
+       s4    dumpsize;
+       utf  *u;
 
-       /* We need to access the dummy native table, not only to remove a
-          warning but to be sure that the table is not optimized away
-          (gcc does this since 3.4). */
+       /* mark memory */
 
-       p = &dummynativetable;
+       dumpsize = dump_size();
 
-       /* initialize libltdl */
+       utf_ptr = descriptor->text;
+       namelen = strlen(name->text) + strlen("__") + strlen("0");
 
-       if (lt_dlinit()) {
-               /* XXX how can we throw an exception here? */
-               log_text(lt_dlerror());
+       /* calculate additional length */
 
-               return false;
+       while ((c = utf_nextu2(&utf_ptr)) != ')') {
+               switch (c) {
+               case 'Z':
+               case 'B':
+               case 'C':
+               case 'S':
+               case 'I':
+               case 'J':
+               case 'F':
+               case 'D':
+                       namelen++;
+                       break;
+               case '[':
+                       namelen += 2;
+                       break;
+               case 'L':
+                       namelen++;
+                       while (utf_nextu2(&utf_ptr) != ';')
+                               namelen++;
+                       namelen += 2;
+                       break;
+               case '(':
+                       break;
+               default:
+                       assert(0);
+               }
        }
 
-       /* get the handle for the main program */
+       /* reallocate memory */
 
-       if (!(mainhandle = lt_dlopen(NULL)))
-               return false;
+       i = strlen(name->text);
 
-       /* initialize library hashtable, 10 entries should be enough */
+       newname = DMNEW(char, namelen);
+       MCOPY(newname, name->text, char, i);
 
-       hashtable_library = NEW(hashtable);
+       utf_ptr = descriptor->text;
 
-       hashtable_create(hashtable_library, 10);
-#endif
+       newname[i++] = '_';
+       newname[i++] = '_';
 
-       /* everything's ok */
+       while ((c = utf_nextu2(&utf_ptr)) != ')') {
+               switch (c) {
+               case 'Z':
+               case 'B':
+               case 'C':
+               case 'S':
+               case 'J':
+               case 'I':
+               case 'F':
+               case 'D':
+                       newname[i++] = c;
+                       break;
+               case '[':
+                       newname[i++] = '_';
+                       newname[i++] = '3';
+                       break;
+               case 'L':
+                       newname[i++] = 'L';
+                       while ((c = utf_nextu2(&utf_ptr)) != ';')
+                               if (((c >= 'a') && (c <= 'z')) ||
+                                       ((c >= 'A') && (c <= 'Z')) ||
+                                       ((c >= '0') && (c <= '9')))
+                                       newname[i++] = c;
+                               else
+                                       newname[i++] = '_';
+                       newname[i++] = '_';
+                       newname[i++] = '2';
+                       break;
+               case '(':
+                       break;
+               default:
+                       assert(0);
+               }
+       }
 
-       return true;
+       /* close string */
+
+       newname[i] = '\0';
+
+       /* make a utf-string */
+
+       u = utf_new_char(newname);
+
+       /* release memory */
+
+       dump_release(dumpsize);
+
+       return u;
+}
+
+
+/* native_insert_char **********************************************************
+
+   Inserts the passed UTF character into the native method name.  If
+   necessary it is escaped properly.
+
+*******************************************************************************/
+
+static s4 native_insert_char(char *name, u4 pos, u2 c)
+{
+       s4 val;
+       s4 i;
+
+       switch (c) {
+       case '/':
+       case '.':
+               /* replace '/' or '.' with '_' */
+               name[pos] = '_';
+               break;
+
+       case '_':
+               /* escape sequence for '_' is '_1' */
+               name[pos]   = '_';
+               name[++pos] = '1';
+               break;
+
+       case ';':
+               /* escape sequence for ';' is '_2' */
+               name[pos]   = '_';
+               name[++pos] = '2';
+               break;
+
+       case '[':
+               /* escape sequence for '[' is '_1' */
+               name[pos]   = '_';
+               name[++pos] = '3';
+               break;
+
+       default:
+               if (isalnum(c))
+                       name[pos] = c;
+               else {
+                       /* unicode character */
+                       name[pos]   = '_';
+                       name[++pos] = '0';
+
+                       for (i = 0; i < 4; ++i) {
+                               val = c & 0x0f;
+                               name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
+                               c >>= 4;
+                       }
+
+                       pos += 4;
+               }
+               break;
+       }
+
+       /* return the new buffer index */
+
+       return pos;
 }
 
 
-/* native_hashtable_library_add ************************************************
+/* native_method_symbol ********************************************************
+
+   Generate a method-symbol string out of the class name and the
+   method name.
+
+*******************************************************************************/
+
+static utf *native_method_symbol(utf *classname, utf *methodname)
+{
+       char *name;
+       s4    namelen;
+       char *utf_ptr;
+       char *utf_endptr;
+       u2    c;
+       u4    pos;
+       s4    dumpsize;
+       utf  *u;
+
+       /* mark memory */
+
+       dumpsize = dump_size();
+
+       /* Calculate length of native function name.  We multiply the
+          class and method name length by 6 as this is the maxium
+          escape-sequence that can be generated (unicode). */
+
+       namelen =
+               strlen("Java_") +
+               utf_get_number_of_u2s(classname) * 6 +
+               strlen("_") +
+               utf_get_number_of_u2s(methodname) * 6 +
+               strlen("0");
+
+       /* allocate memory */
+
+       name = DMNEW(char, namelen);
+
+       /* generate name of native functions */
+
+       strcpy(name, "Java_");
+       pos = strlen("Java_");
+
+       utf_ptr    = classname->text;
+       utf_endptr = UTF_END(classname);
+
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
+       }
+
+       /* seperator between class and method */
+
+       name[pos++] = '_';
+
+       utf_ptr    = methodname->text;
+       utf_endptr = UTF_END(methodname);
+
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
+       }
+
+       /* close string */
+
+       name[pos] = '\0';
+
+       /* check for an buffer overflow */
+
+       assert(pos <= namelen);
+
+       /* make a utf-string */
+
+       u = utf_new_char(name);
+
+       /* release memory */
+
+       dump_release(dumpsize);
+
+       return u;
+}
+
+
+/* native_method_register ******************************************************
+
+   Register a native method in the native method table.
+
+*******************************************************************************/
+
+void native_method_register(utf *classname, const JNINativeMethod *methods,
+                                                       int32_t count)
+{
+       native_methods_node_t *nmn;
+       utf                   *name;
+       utf                   *descriptor;
+       int32_t                i;
+
+       /* insert all methods passed */
+
+       for (i = 0; i < count; i++) {
+               if (opt_verbosejni) {
+                       printf("[Registering JNI native method ");
+                       utf_display_printable_ascii_classname(classname);
+                       printf(".%s]\n", methods[i].name);
+               }
+
+               /* generate the utf8 names */
+
+               name       = utf_new_char(methods[i].name);
+               descriptor = utf_new_char(methods[i].signature);
+
+               /* allocate a new tree node */
+
+               nmn = NEW(native_methods_node_t);
+
+               nmn->classname  = classname;
+               nmn->name       = name;
+               nmn->descriptor = descriptor;
+               nmn->function   = (functionptr) (ptrint) methods[i].fnPtr;
+
+               /* insert the method into the tree */
+
+               avl_insert(tree_native_methods, nmn);
+       }
+}
+
+
+/* native_method_find **********************************************************
+
+   Find a native method in the native method table.
+
+*******************************************************************************/
+
+static functionptr native_method_find(methodinfo *m)
+{
+       native_methods_node_t  tmpnmn;
+       native_methods_node_t *nmn;
+
+       /* fill the temporary structure used for searching the tree */
+
+       tmpnmn.classname  = m->class->name;
+       tmpnmn.name       = m->name;
+       tmpnmn.descriptor = m->descriptor;
+
+       /* find the entry in the AVL-tree */
+
+       nmn = avl_find(tree_native_methods, &tmpnmn);
+
+       if (nmn == NULL)
+               return NULL;
+
+       return nmn->function;
+}
+
+
+/* native_library_open *********************************************************
+
+   Open a native library with the given utf8 name.
+
+*******************************************************************************/
+
+#if defined(ENABLE_LTDL)
+lt_dlhandle native_library_open(utf *filename)
+{
+       lt_dlhandle handle;
+
+       if (opt_verbosejni) {
+               printf("[Loading native library ");
+               utf_display_printable_ascii(filename);
+               printf(" ... ");
+       }
+
+       /* try to open the library */
+
+       handle = lt_dlopen(filename->text);
+
+       if (handle == NULL) {
+               if (opt_verbose) {
+                       log_start();
+                       log_print("native_library_load: lt_dlopen failed: ");
+                       log_print(lt_dlerror());
+                       log_finish();
+               }
+
+               return NULL;
+       }
+
+       return handle;
+}
+#endif
+
+
+/* native_library_add **********************************************************
 
    Adds an entry to the native library hashtable.
 
 *******************************************************************************/
 
-#if !defined(WITH_STATIC_CLASSPATH)
-void native_hashtable_library_add(utf *filename, java_objectheader *loader,
-                                                                 lt_dlhandle handle)
+#if defined(ENABLE_LTDL)
+void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
 {
        hashtable_library_loader_entry *le;
        hashtable_library_name_entry   *ne; /* library name                       */
        u4   key;                           /* hashkey                            */
        u4   slot;                          /* slot in hashtable                  */
 
-#if defined(ENABLE_THREADS)
-       builtin_monitorenter(hashtable_library->header);
-#endif
+       LOCK_MONITOR_ENTER(hashtable_library->header);
 
        /* normally addresses are aligned to 4, 8 or 16 bytes */
 
@@ -386,9 +605,7 @@ void native_hashtable_library_add(utf *filename, java_objectheader *loader,
 
        while (ne) {
                if (ne->name == filename) {
-#if defined(ENABLE_THREADS)
-                       builtin_monitorexit(hashtable_library->header);
-#endif
+                       LOCK_MONITOR_EXIT(hashtable_library->header);
 
                        return;
                }
@@ -408,22 +625,20 @@ void native_hashtable_library_add(utf *filename, java_objectheader *loader,
        ne->hashlink = le->namelink;
        le->namelink = ne;
 
-#if defined(ENABLE_THREADS)
-       builtin_monitorexit(hashtable_library->header);
-#endif
+       LOCK_MONITOR_EXIT(hashtable_library->header);
 }
-#endif /* !defined(WITH_STATIC_CLASSPATH) */
+#endif
 
 
-/* native_hashtable_library_find ***********************************************
+/* native_library_find *********************************************************
 
    Find an entry in the native library hashtable.
 
 *******************************************************************************/
 
-#if !defined(WITH_STATIC_CLASSPATH)
-hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
-                                                                                                                       java_objectheader *loader)
+#if defined(ENABLE_LTDL)
+hashtable_library_name_entry *native_library_find(utf *filename,
+                                                                                                 classloader *loader)
 {
        hashtable_library_loader_entry *le;
        hashtable_library_name_entry   *ne; /* library name                       */
@@ -447,7 +662,7 @@ hashtable_library_name_entry *native_hashtable_library_find(utf *filename,
 
        /* no loader found? return NULL */
 
-       if (!le)
+       if (le == NULL)
                return NULL;
 
        /* search for library name */
@@ -515,122 +730,15 @@ functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
                        return n->func;
        }
 
-               
        /* no function was found, throw exception */
 
-       *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
-                                                                        mname);
+       exceptions_throw_unsatisfiedlinkerror(mname);
 
        return NULL;
 }
 #endif /* defined(WITH_STATIC_CLASSPATH) */
 
 
-/* native_make_overloaded_function *********************************************
-
-   XXX
-
-*******************************************************************************/
-
-#if !defined(WITH_STATIC_CLASSPATH)
-static char *native_make_overloaded_function(char *name, utf *desc)
-{
-       char *newname;
-       s4    namelen;
-       char *utf_ptr;
-       u2    c;
-       s4    i;
-
-       utf_ptr = desc->text;
-       namelen = strlen(name) + strlen("__") + strlen("0");
-
-       /* calculate additional length */
-
-       while ((c = utf_nextu2(&utf_ptr)) != ')') {
-               switch (c) {
-               case 'Z':
-               case 'B':
-               case 'C':
-               case 'S':
-               case 'I':
-               case 'J':
-               case 'F':
-               case 'D':
-                       namelen++;
-                       break;
-               case '[':
-                       namelen += 2;
-                       break;
-               case 'L':
-                       namelen++;
-                       while (utf_nextu2(&utf_ptr) != ';')
-                               namelen++;
-                       namelen += 2;
-                       break;
-               case '(':
-                       break;
-               default:
-                       assert(0);
-               }
-       }
-
-
-       /* reallocate memory */
-
-       i = strlen(name);
-
-       newname = DMNEW(char, namelen);
-       MCOPY(newname, name, char, i);
-
-       utf_ptr = desc->text;
-
-       newname[i++] = '_';
-       newname[i++] = '_';
-
-       while ((c = utf_nextu2(&utf_ptr)) != ')') {
-               switch (c) {
-               case 'Z':
-               case 'B':
-               case 'C':
-               case 'S':
-               case 'J':
-               case 'I':
-               case 'F':
-               case 'D':
-                       newname[i++] = c;
-                       break;
-               case '[':
-                       newname[i++] = '_';
-                       newname[i++] = '3';
-                       break;
-               case 'L':
-                       newname[i++] = 'L';
-                       while ((c = utf_nextu2(&utf_ptr)) != ';')
-                               if (((c >= 'a') && (c <= 'z')) ||
-                                       ((c >= 'A') && (c <= 'Z')) ||
-                                       ((c >= '0') && (c <= '9')))
-                                       newname[i++] = c;
-                               else
-                                       newname[i++] = '_';
-                       newname[i++] = '_';
-                       newname[i++] = '2';
-                       break;
-               case '(':
-                       break;
-               default:
-                       assert(0);
-               }
-       }
-
-       /* close string */
-
-       newname[i] = '\0';
-
-       return newname;
-}
-
-
 /* native_resolve_function *****************************************************
 
    Resolves a native function, maybe from a dynamic library.
@@ -639,19 +747,22 @@ static char *native_make_overloaded_function(char *name, utf *desc)
 
 functionptr native_resolve_function(methodinfo *m)
 {
-       lt_ptr                     sym;
-       char                      *name;
-       char                      *newname;
-       s4                         namelen;
-       char                      *utf_ptr;
-       char                      *utf_endptr;
-       s4                         dumpsize;
+       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                  */
-       u4                         i;
+       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 */
 
@@ -662,79 +773,10 @@ functionptr native_resolve_function(methodinfo *m)
                utf_display_printable_ascii(m->name);
                printf(" ... ");
        }
-               
-       /* calculate length of native function name */
-
-       namelen = strlen("Java_") + utf_get_number_of_u2s(m->class->name) + strlen("_") +
-               utf_get_number_of_u2s(m->name) + strlen("0");
-
-       /* check for underscores in class name */
-
-       utf_ptr = m->class->name->text;
-       utf_endptr = UTF_END(m->class->name);
-
-       while (utf_ptr < utf_endptr)
-               if (utf_nextu2(&utf_ptr) == '_')
-                       namelen++;
-
-       /* check for underscores in method name */
-
-       utf_ptr = m->name->text;
-       utf_endptr = UTF_END(m->name);
-
-       while (utf_ptr < utf_endptr)
-               if (utf_nextu2(&utf_ptr) == '_')
-                       namelen++;
-
-       /* allocate memory */
-
-       dumpsize = dump_size();
-
-       name = DMNEW(char, namelen);
-
-
-       /* generate name of native functions */
-
-       strcpy(name, "Java_");
-       i = strlen("Java_");
-
-       utf_ptr = m->class->name->text;
-       utf_endptr = UTF_END(m->class->name);
-
-       for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
-               name[i] = *utf_ptr;
-
-               /* escape sequence for '_' is '_1' */
-
-               if (name[i] == '_')
-                       name[++i] = '1';
-
-               /* replace '/' with '_' */
-
-               if (name[i] == '/')
-                       name[i] = '_';
-       }
 
-       /* seperator between class and method */
-
-       name[i++] = '_';
-
-       utf_ptr = m->name->text;
-       utf_endptr = UTF_END(m->name);
-
-       for (; utf_ptr < utf_endptr; utf_ptr++, i++) {
-               name[i] = *utf_ptr;
-
-               /* escape sequence for '_' is '_1' */
-
-               if (name[i] == '_')
-                       name[++i] = '1';
-       }
-
-       /* close string */
-
-       name[i] = '\0';
+       /* generate method symbol string */
 
+       name = native_method_symbol(m->class->name, m->name);
 
        /* generate overloaded function (having the types in it's name)           */
 
@@ -743,26 +785,27 @@ functionptr native_resolve_function(methodinfo *m)
        /* check the library hash entries of the classloader of the
           methods's class  */
 
-       sym = NULL;
+       f = NULL;
 
+#if defined(ENABLE_LTDL)
        /* normally addresses are aligned to 4, 8 or 16 bytes */
 
-       key  = ((u4) (ptrint) m->class->classloader) >> 4;    /* align to 16-byte */
+       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) && (sym == NULL)) {
+       while ((le != NULL) && (f == NULL)) {
                /* iterate through names in this loader */
 
                ne = le->namelink;
                        
-               while ((ne != NULL) && (sym == NULL)) {
-                       sym = lt_dlsym(ne->handle, name);
+               while ((ne != NULL) && (f == NULL)) {
+                       f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
 
-                       if (sym == NULL)
-                               sym = lt_dlsym(ne->handle, newname);
+                       if (f == NULL)
+                               f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
 
                        ne = ne->hashlink;
                }
@@ -770,47 +813,71 @@ functionptr native_resolve_function(methodinfo *m)
                le = le->hashlink;
        }
 
-       if (sym != NULL)
+# 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 (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 (sym == NULL) {
-               sym = lt_dlsym(mainhandle, name);
-
-               if (sym == NULL)
-                       sym = lt_dlsym(mainhandle, newname);
+       if (f == NULL) {
+               f = native_method_find(m);
 
-               if (sym != NULL)
+               if (f != NULL)
                        if (opt_verbosejni)
                                printf("internal ]\n");
        }
 
-
 #if defined(ENABLE_JVMTI)
        /* fire Native Method Bind event */
-       jvmti_NativeMethodBind(m, sym, &sym);
+       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
 #endif
 
        /* no symbol found? throw exception */
 
-       if (sym == NULL) {
+       if (f == NULL) {
                if (opt_verbosejni)
                        printf("failed ]\n");
 
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
-                                                                        m->name);
+               exceptions_throw_unsatisfiedlinkerror(m->name);
        }
 
-       /* release memory */
-
-       dump_release(dumpsize);
-
-       return (functionptr) (ptrint) sym;
+       return f;
 }
 #endif /* !defined(WITH_STATIC_CLASSPATH) */
 
@@ -822,19 +889,19 @@ functionptr native_resolve_function(methodinfo *m)
                        
 *******************************************************************************/
 
-java_objectheader *native_new_and_init(classinfo *c)
+java_handle_t *native_new_and_init(classinfo *c)
 {
-       methodinfo *m;
-       java_objectheader *o;
+       methodinfo    *m;
+       java_handle_t *o;
 
-       if (!c)
-               return *exceptionptr;
+       if (c == NULL)
+               vm_abort("native_new_and_init: c == NULL");
 
        /* create object */
 
        o = builtin_new(c);
        
-       if (!o)
+       if (o == NULL)
                return NULL;
 
        /* try to find the initializer */
@@ -844,7 +911,7 @@ java_objectheader *native_new_and_init(classinfo *c)
        /* ATTENTION: returning the object here is ok, since the class may
        not have an initializer */
 
-       if (!m)
+       if (m == NULL)
                return o;
 
        /* call initializer */
@@ -855,32 +922,28 @@ java_objectheader *native_new_and_init(classinfo *c)
 }
 
 
-java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
+java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
 {
-       methodinfo *m;
-       java_objectheader *o;
+       methodinfo    *m;
+       java_handle_t *o;
 
-       if (!c)
-               return *exceptionptr;
+       if (c == NULL)
+               vm_abort("native_new_and_init_string: c == NULL");
 
        /* create object */
 
        o = builtin_new(c);
 
-       if (!o)
+       if (o == NULL)
                return NULL;
 
        /* find initializer */
 
-       m = class_resolveclassmethod(c,
-                                                                utf_init,
-                                                                utf_java_lang_String__void,
-                                                                NULL,
-                                                                true);
+       m = class_findmethod(c, utf_init, utf_java_lang_String__void);
 
        /* initializer not found */
 
-       if (!m)
+       if (m == NULL)
                return NULL;
 
        /* call initializer */
@@ -891,170 +954,6 @@ java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
 }
 
 
-java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
-{
-       methodinfo *m;
-       java_objectheader *o;
-
-       if (!c)
-               return *exceptionptr;
-
-       /* create object */
-
-       o = builtin_new(c);
-       
-       if (!o)
-               return NULL;
-
-       /* find initializer */
-
-       m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
-
-       /* initializer not found  */
-
-       if (!m)
-               return NULL;
-
-       /* call initializer */
-
-       (void) vm_call_method(m, o, i);
-
-       return o;
-}
-
-
-java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
-{
-       methodinfo *m;
-       java_objectheader *o;
-
-       if (!c)
-               return *exceptionptr;
-
-       /* create object */
-
-       o = builtin_new(c);
-       
-       if (!o)
-               return NULL;
-
-       /* find initializer */
-
-       m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
-                                                     
-       /* initializer not found */
-
-       if (!m)
-               return NULL;
-
-       /* call initializer */
-
-       (void) vm_call_method(m, o, t);
-
-       return o;
-}
-
-
-/* native_get_parametertypes ***************************************************
-
-   Use the descriptor of a method to generate a java/lang/Class array
-   which contains the classes of the parametertypes of the method.
-
-*******************************************************************************/
-
-java_objectarray *native_get_parametertypes(methodinfo *m)
-{
-       methoddesc       *md;
-       typedesc         *paramtypes;
-       s4                paramcount;
-    java_objectarray *oa;
-       s4                i;
-
-       md = m->parseddesc;
-
-       /* is the descriptor fully parsed? */
-
-       if (!m->parseddesc->params)
-               if (!descriptor_params_from_paramtypes(md, m->flags))
-                       return NULL;
-
-       paramtypes = md->paramtypes;
-       paramcount = md->paramcount;
-
-       /* skip `this' pointer */
-
-       if (!(m->flags & ACC_STATIC)) {
-               paramtypes++;
-               paramcount--;
-       }
-
-       /* create class-array */
-
-       oa = builtin_anewarray(paramcount, class_java_lang_Class);
-
-       if (!oa)
-               return NULL;
-
-    /* get classes */
-
-       for (i = 0; i < paramcount; i++)
-               if (!resolve_class_from_typedesc(&paramtypes[i], true, false,
-                                                                                (classinfo **) &oa->data[i]))
-                       return NULL;
-
-       return oa;
-}
-
-
-/* native_get_exceptiontypes ***************************************************
-
-   Get the exceptions which can be thrown by a method.
-
-*******************************************************************************/
-
-java_objectarray *native_get_exceptiontypes(methodinfo *m)
-{
-       java_objectarray *oa;
-       classinfo        *c;
-       u2                i;
-
-       /* create class-array */
-
-       oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
-
-       if (!oa)
-               return NULL;
-
-       for (i = 0; i < m->thrownexceptionscount; i++) {
-               if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i],
-                                                                                  resolveEager, true, false, &c))
-                       return NULL;
-
-               oa->data[i] = (java_objectheader *) c;
-       }
-
-       return oa;
-}
-
-
-/* native_get_returntype *******************************************************
-
-   Get the returntype class of a method.
-
-*******************************************************************************/
-
-classinfo *native_get_returntype(methodinfo *m)
-{
-       classinfo *c;
-
-       if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false,
-                                                                        &c))
-               return NULL;
-
-       return c;
-}
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where