* src/vm/exceptions.c (exceptions_throw_unsatisfiedlinkerror)
[cacao.git] / src / native / native.c
index ef54cef40df0de23b09162e8be9f4aa1abb406b5..a71c7383dcb9aced0ffe47822b26ab0bd54fa61f 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 4900 2006-05-11 09:18:28Z twisti $
+   $Id: native.c 7305 2007-02-09 11:08:14Z twisti $
 
 */
 
@@ -38,6 +30,7 @@
 #include "config.h"
 
 #include <assert.h>
+#include <ctype.h>
 
 #if !defined(WITH_STATIC_CLASSPATH)
 # include <ltdl.h>
 #include "mm/memory.h"
 #include "native/jni.h"
 #include "native/native.h"
+#include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#else
+# include "threads/none/lock.h"
+#endif
+
+#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 "vmcore/resolve.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
 
 /* include table of native functions ******************************************/
 
-#include "native/include/java_lang_Cloneable.h"
-#include "native/include/java_util_Properties.h"
+#if defined(ENABLE_JAVASE)
+
 #include "native/include/java_io_InputStream.h"
 #include "native/include/java_io_PrintStream.h"
 
+#include "native/include/java_lang_Cloneable.h"
+#include "native/include/java_util_Properties.h"
+
+#include "native/include/java_lang_Object.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/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
+#include "native/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
+#include "native/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
 #include "native/include/java_lang_VMClass.h"
+#include "native/include/java_security_ProtectionDomain.h"  /* required by... */
 #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_VMSystem.h"
 #include "native/include/java_lang_VMThread.h"
 #include "native/include/java_lang_VMThrowable.h"
+#include "native/include/java_lang_management_VMManagementFactory.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_VMMethod.h"
 #endif
 
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+#include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_Float.h"
+#include "native/include/java_lang_Math.h"
+#include "native/include/java_lang_Runtime.h"
+#include "native/include/java_lang_System.h"
+#include "native/include/java_lang_Thread.h"
+
+#endif
+
 #if defined(WITH_STATIC_CLASSPATH)
 
 /* these are required to prevent compiler warnings */
 
 #include "native/nativetable.inc"
 
-#else /* defined(WITH_STATIC_CLASSPATH) */
+#elif !defined(ENABLE_LIBJVM)
 
-/* Ensure that symbols for functions implemented within CACAO are used
-   and exported to dlopen. */
+/* dummynativetable ************************************************************
+
+   Ensure that symbols for functions implemented within CACAO are used
+   and exported to dlopen.
+
+   ATTENTION: Don't make this table static!!!  Otherwise the compiler
+   may optimize it away!
+
+*******************************************************************************/
 
-static functionptr dummynativetable[] = {
+functionptr dummynativetable[] = {
+#if defined(ENABLE_JAVASE)
        (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext,
+       (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClass,
+       (functionptr) Java_gnu_classpath_VMStackWalker_getCallingClassLoader,
+       (functionptr) Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader,
 
        (functionptr) Java_gnu_classpath_VMSystemProperties_preInit,
 
+       (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount,
+       (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount,
+       (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose,
+       (functionptr) Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose,
+
+       (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage,
+       (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage,
+       (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount,
+       (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose,
+       (functionptr) Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose,
+
+       (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments,
+       (functionptr) Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime,
+
        (functionptr) Java_java_lang_VMClass_isInstance,
        (functionptr) Java_java_lang_VMClass_isAssignableFrom,
        (functionptr) Java_java_lang_VMClass_isInterface,
@@ -193,6 +248,10 @@ static functionptr dummynativetable[] = {
        (functionptr) Java_java_lang_VMThrowable_fillInStackTrace,
        (functionptr) Java_java_lang_VMThrowable_getStackTrace,
 
+       (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryPoolNames,
+       (functionptr) Java_java_lang_management_VMManagementFactory_getMemoryManagerNames,
+       (functionptr) Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames,
+
        (functionptr) Java_java_lang_reflect_Constructor_getModifiersInternal,
        (functionptr) Java_java_lang_reflect_Constructor_constructNative,
 
@@ -228,6 +287,7 @@ static functionptr dummynativetable[] = {
        (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,
@@ -256,9 +316,62 @@ static functionptr dummynativetable[] = {
        (functionptr) Java_gnu_classpath_jdwp_VMMethod_getVariableTable
 #endif
 
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+       (functionptr) Java_com_sun_cldc_io_ResourceInputStream_open,
+
+       (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_open0,
+       (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf,
+       (functionptr) Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte,
+
+       (functionptr) Java_com_sun_cldchi_io_ConsoleOutputStream_write,
+
+       (functionptr) Java_java_lang_Class_forName,
+       (functionptr) Java_java_lang_Class_newInstance,
+       (functionptr) Java_java_lang_Class_isInstance,
+       (functionptr) Java_java_lang_Class_isAssignableFrom,
+       (functionptr) Java_java_lang_Class_isInterface,
+       (functionptr) Java_java_lang_Class_isArray,
+       (functionptr) Java_java_lang_Class_getName,
+
+       (functionptr) Java_java_lang_Double_doubleToLongBits,
+
+       (functionptr) Java_java_lang_Float_floatToIntBits,
+
+       (functionptr) Java_java_lang_Math_ceil,
+       (functionptr) Java_java_lang_Math_cos,
+       (functionptr) Java_java_lang_Math_floor,
+       (functionptr) Java_java_lang_Math_sin,
+       (functionptr) Java_java_lang_Math_sqrt,
+       (functionptr) Java_java_lang_Math_tan,
+
+       (functionptr) Java_java_lang_Object_hashCode,
+       (functionptr) Java_java_lang_Object_notify,
+       (functionptr) Java_java_lang_Object_wait,
+
+       (functionptr) Java_java_lang_Runtime_exitInternal,
+       (functionptr) Java_java_lang_Runtime_freeMemory,
+       (functionptr) Java_java_lang_Runtime_totalMemory,
+       (functionptr) Java_java_lang_Runtime_gc,
+
+       (functionptr) Java_java_lang_String_hashCode,
+       (functionptr) Java_java_lang_String_indexOf__I,
+       (functionptr) Java_java_lang_String_indexOf__II,
+       (functionptr) Java_java_lang_String_lastIndexOf__II,
+       (functionptr) Java_java_lang_String_intern,
+
+       (functionptr) Java_java_lang_System_getProperty0,
+
+       (functionptr) Java_java_lang_Thread_currentThread,
+       (functionptr) Java_java_lang_Thread_setPriority0,
+       (functionptr) Java_java_lang_Thread_start0,
+       (functionptr) Java_java_lang_Thread_yield,
+
+       (functionptr) Java_java_lang_Throwable_printStackTrace,
+       (functionptr) Java_java_lang_Throwable_fillInStackTrace
+#endif
 };
 
-#endif /* defined(WITH_STATIC_CLASSPATH) */
+#endif /* defined(ENABLE_LIBJVM) */
 
 
 /* tables for methods *********************************************************/
@@ -282,36 +395,34 @@ static lt_dlhandle mainhandle;
 #endif
 
 
-/* native_loadclasses **********************************************************
+/* native_init *****************************************************************
 
-   Load classes required for native methods.
+   Initializes the native subsystem.
 
 *******************************************************************************/
 
 bool native_init(void)
 {
 #if !defined(WITH_STATIC_CLASSPATH)
-       void *p;
-
-       /* 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). */
-
-       p = &dummynativetable;
-
        /* initialize libltdl */
 
-       if (lt_dlinit()) {
-               /* XXX how can we throw an exception here? */
-               log_text(lt_dlerror());
+       if (lt_dlinit())
+               vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror());
 
-               return false;
-       }
+       /* Get the handle for the main program or for the libjvm.so,
+          depends on the configuration. */
 
-       /* get the handle for the main program */
+# if defined(ENABLE_LIBJVM)
+       /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
+          If not found, try the absolute path. */
 
+       if (!(mainhandle = lt_dlopenext("libjvm")))
+               if (!(mainhandle = lt_dlopenext(cacao_libjvm)))
+                       vm_abort("native_init: lt_dlopenext failed: %s\n", lt_dlerror());
+# else
        if (!(mainhandle = lt_dlopen(NULL)))
-               return false;
+               vm_abort("native_init: lt_dlopen failed: %s\n", lt_dlerror());
+# endif
 
        /* initialize library hashtable, 10 entries should be enough */
 
@@ -341,9 +452,7 @@ void native_hashtable_library_add(utf *filename, java_objectheader *loader,
        u4   key;                           /* hashkey                            */
        u4   slot;                          /* slot in hashtable                  */
 
-#if defined(USE_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 +495,7 @@ void native_hashtable_library_add(utf *filename, java_objectheader *loader,
 
        while (ne) {
                if (ne->name == filename) {
-#if defined(USE_THREADS)
-                       builtin_monitorexit(hashtable_library->header);
-#endif
+                       LOCK_MONITOR_EXIT(hashtable_library->header);
 
                        return;
                }
@@ -408,9 +515,7 @@ void native_hashtable_library_add(utf *filename, java_objectheader *loader,
        ne->hashlink = le->namelink;
        le->namelink = ne;
 
-#if defined(USE_THREADS)
-       builtin_monitorexit(hashtable_library->header);
-#endif
+       LOCK_MONITOR_EXIT(hashtable_library->header);
 }
 #endif /* !defined(WITH_STATIC_CLASSPATH) */
 
@@ -515,7 +620,6 @@ functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
                        return n->func;
        }
 
-               
        /* no function was found, throw exception */
 
        *exceptionptr =
@@ -631,6 +735,68 @@ static char *native_make_overloaded_function(char *name, utf *desc)
 }
 
 
+/* 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_resolve_function *****************************************************
 
    Resolves a native function, maybe from a dynamic library.
@@ -639,19 +805,19 @@ 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;
+       lt_ptr                          sym;
+       char                           *name;
+       char                           *newname;
+       s4                              namelen;
+       char                           *utf_ptr;
+       char                           *utf_endptr;
+       u2                              c;
+       u4                              pos;
+       s4                              dumpsize;
        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              */
 
        /* verbose output */
 
@@ -663,28 +829,15 @@ functionptr native_resolve_function(methodinfo *m)
                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 */
+       /* 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). */
 
-       utf_ptr = m->name->text;
-       utf_endptr = UTF_END(m->name);
-
-       while (utf_ptr < utf_endptr)
-               if (utf_nextu2(&utf_ptr) == '_')
-                       namelen++;
+       namelen = strlen("Java_") +
+               utf_get_number_of_u2s(m->class->name) * 6 +
+               strlen("_") +
+               utf_get_number_of_u2s(m->name) * 6 +
+               strlen("0");
 
        /* allocate memory */
 
@@ -692,49 +845,38 @@ functionptr native_resolve_function(methodinfo *m)
 
        name = DMNEW(char, namelen);
 
-
        /* generate name of native functions */
 
        strcpy(name, "Java_");
-       i = strlen("Java_");
+       pos = strlen("Java_");
 
-       utf_ptr = m->class->name->text;
+       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] = '_';
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
        }
 
        /* seperator between class and method */
 
-       name[i++] = '_';
+       name[pos++] = '_';
 
-       utf_ptr = m->name->text;
+       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';
+       for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+               c   = *utf_ptr;
+               pos = native_insert_char(name, pos, c);
        }
 
        /* close string */
 
-       name[i] = '\0';
+       name[pos] = '\0';
 
+       /* check for an buffer overflow */
+
+       assert(pos <= namelen);
 
        /* generate overloaded function (having the types in it's name)           */
 
@@ -790,15 +932,18 @@ functionptr native_resolve_function(methodinfo *m)
        }
 
 
+#if defined(ENABLE_JVMTI)
+       /* fire Native Method Bind event */
+       if (jvmti) jvmti_NativeMethodBind(m, sym, &sym);
+#endif
+
        /* no symbol found? throw exception */
 
        if (sym == NULL) {
                if (opt_verbosejni)
                        printf("failed ]\n");
 
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
-                                                                        m->name);
+               exceptions_throw_unsatisfiedlinkerror(m->name);
        }
 
        /* release memory */
@@ -822,14 +967,14 @@ java_objectheader *native_new_and_init(classinfo *c)
        methodinfo *m;
        java_objectheader *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 */
@@ -839,7 +984,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 */
@@ -850,19 +995,19 @@ java_objectheader *native_new_and_init(classinfo *c)
 }
 
 
-java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
+java_objectheader *native_new_and_init_string(classinfo *c, java_objectheader *s)
 {
-       methodinfo *m;
+       methodinfo        *m;
        java_objectheader *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 */
@@ -875,7 +1020,7 @@ java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
 
        /* initializer not found */
 
-       if (!m)
+       if (m == NULL)
                return NULL;
 
        /* call initializer */
@@ -891,14 +1036,14 @@ java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
        methodinfo *m;
        java_objectheader *o;
 
-       if (!c)
-               return *exceptionptr;
+       if (c == NULL)
+               vm_abort("native_new_and_init_int: c == NULL");
 
        /* create object */
 
        o = builtin_new(c);
        
-       if (!o)
+       if (o == NULL)
                return NULL;
 
        /* find initializer */
@@ -907,7 +1052,7 @@ java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
 
        /* initializer not found  */
 
-       if (!m)
+       if (m == NULL)
                return NULL;
 
        /* call initializer */
@@ -918,19 +1063,19 @@ java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
 }
 
 
-java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
+java_objectheader *native_new_and_init_throwable(classinfo *c, java_objectheader *t)
 {
-       methodinfo *m;
        java_objectheader *o;
+       methodinfo        *m;
 
-       if (!c)
-               return *exceptionptr;
+       if (c == NULL)
+               vm_abort("native_new_and_init_throwable: c == NULL");
 
        /* create object */
 
        o = builtin_new(c);
        
-       if (!o)
+       if (o == NULL)
                return NULL;
 
        /* find initializer */
@@ -939,7 +1084,7 @@ java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwab
                                                      
        /* initializer not found */
 
-       if (!m)
+       if (m == NULL)
                return NULL;
 
        /* call initializer */
@@ -950,6 +1095,46 @@ java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwab
 }
 
 
+/* native_class_getdeclaredannotations *****************************************
+
+   Implementation for
+   java.lang.Class.getDeclaredAnnotations(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_objectarray *native_class_getdeclaredannotations(classinfo *c)
+{
+       java_objectarray *oa;
+       s4                count;
+       s4                i;
+
+       classinfo *class_java_lang_annotation_Annotation;
+
+       /* create Annotation-array */
+
+       /* XXX should we cache that class? */
+       if (!(class_java_lang_annotation_Annotation =
+                 load_class_bootstrap(utf_new_char("java/lang/annotation/Annotation"))))
+               return NULL;
+
+       count = c->runtimevisibleannotationscount;
+
+       oa = builtin_anewarray(count, class_java_lang_annotation_Annotation);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* fill the annotations */
+
+       for (i = 0; i < count; i++) {
+       }
+
+       return oa;
+}
+#endif
+
+
 /* native_get_parametertypes ***************************************************
 
    Use the descriptor of a method to generate a java/lang/Class array