From: Michael Starzinger Date: Wed, 15 Apr 2009 09:39:14 +0000 (+0200) Subject: * src/native/vm/openjdk/jvm.cpp (JVM_CurrentClassLoader): Implemented. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=b6fac998138b04cbb49a787bf6d673cc6480719c * src/native/vm/openjdk/jvm.cpp (JVM_CurrentClassLoader): Implemented. * src/vm/javaobjects.hpp [ENABLE_JAVASE] (java_lang_ClassLoader): Added. * src/vm/javaobjects.cpp (java_lang_ClassLoader::invoke_getSystemClassLoader): Implemented new invocation wrapper method. * src/vm/loader.cpp (load_class_from_sysloader): Use above invocation wrapper. * src/vm/jit/stacktrace.cpp (stacktrace_first_nonsystem_classloader): Added. * src/vm/jit/stacktrace.hpp: Likewise. * src/vm/vm.cpp (vm_get_mainclass_from_jar): Added workaround to make it compile with CLDC. We have to look into this at some point. --- diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index f35668635..596b3df83 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -2,6 +2,7 @@ Copyright (C) 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -129,12 +130,12 @@ } \ } while (0) -# define PRINTJVMWARNINGS(x) -/* do { \ */ -/* if (opt_PrintJVMWarnings) { \ */ -/* log_println x; \ */ -/* } \ */ -/* } while (0) */ +# define PRINTJVMWARNINGS(x) \ + do { \ + if (opt_PrintWarnings) { \ + log_println x; \ + } \ + } while (0) #else @@ -2316,12 +2317,10 @@ jclass JVM_CurrentLoadedClass(JNIEnv *env) jobject JVM_CurrentClassLoader(JNIEnv *env) { - /* XXX if a method in a class in a trusted loader is in a - doPrivileged, return NULL */ - - log_println("JVM_CurrentClassLoader: IMPLEMENT ME!"); + TRACEJVMCALLS(("JVM_CurrentClassLoader(env=%p)", env)); + PRINTJVMWARNINGS(("JVM_CurrentClassLoader is deprecated, do not use it.")); - return NULL; + return stacktrace_first_nonsystem_classloader(); } @@ -2413,13 +2412,9 @@ jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint le jobject JVM_LatestUserDefinedLoader(JNIEnv *env) { - classloader_t *cl; - TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env)); - cl = stacktrace_first_nonnull_classloader(); - - return (jobject) cl; + return stacktrace_first_nonnull_classloader(); } diff --git a/src/vm/javaobjects.cpp b/src/vm/javaobjects.cpp index b8a0d6013..901756534 100644 --- a/src/vm/javaobjects.cpp +++ b/src/vm/javaobjects.cpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.cpp - functions to create and access Java objects - Copyright (C) 2008 Theobroma Systems Ltd. + Copyright (C) 2008, 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -38,6 +38,42 @@ #if defined(ENABLE_JAVASE) +/** + * Invokes the static Java method getSystemClassLoader(). + * + * @return Return value of the invocation or NULL in + * case of an exception. + */ +java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader() +{ + methodinfo *m; + java_handle_t *clo; + classloader_t *cl; + + assert(class_java_lang_Object); + assert(class_java_lang_ClassLoader); + assert(class_java_lang_ClassLoader->state & CLASS_LINKED); + + m = class_resolveclassmethod(class_java_lang_ClassLoader, + utf_getSystemClassLoader, + utf_void__java_lang_ClassLoader, + class_java_lang_Object, + false); + + if (m == NULL) + return NULL; + + clo = vm_call_method(m, NULL); + + if (clo == NULL) + return NULL; + + cl = loader_hashtable_classloader_add(clo); + + return cl; +} + + /** * Constructs a Java object with the given * java.lang.reflect.Constructor. @@ -67,7 +103,7 @@ java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarr if (h == NULL) return NULL; - + // Call initializer. (void) Reflection::invoke(m, h, args); diff --git a/src/vm/javaobjects.hpp b/src/vm/javaobjects.hpp index b8ee1215a..71f58abb1 100644 --- a/src/vm/javaobjects.hpp +++ b/src/vm/javaobjects.hpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.hpp - functions to create and access Java objects - Copyright (C) 2008 Theobroma Systems Ltd. + Copyright (C) 2008, 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -590,6 +590,39 @@ inline void java_lang_Class::set_pd(java_handle_t* value) } +/** + * GNU Classpath java/lang/ClassLoader + * + * Object layout: + * + * 0. object header + * 1. java.util.HashMap definedPackages + * 2. java.lang.ClassLoader parent + * [other fields are not used] + */ +class java_lang_ClassLoader : public java_lang_Object, private FieldAccess { +private: + // Static offsets of the object's instance fields. + // TODO These offsets need to be checked on VM startup. + static const off_t offset_definedPackages = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P); + static const off_t offset_parent = MEMORY_ALIGN(offset_definedPackages + SIZEOF_VOID_P, SIZEOF_VOID_P); + +public: + java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {} + + // Getters. + java_handle_t* get_parent() const; + + // Invocation wrappers for static methods. + static java_handle_t* invoke_getSystemClassLoader(); +}; + +inline java_handle_t* java_lang_ClassLoader::get_parent() const +{ + return get(_handle, offset_parent); +} + + /** * GNU Classpath java/lang/StackTraceElement * @@ -1715,7 +1748,7 @@ public: gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {} gnu_classpath_Pointer(java_handle_t* h, void* data); - // Setters. + // Getters. void* get_data() const; // Setters. @@ -1788,6 +1821,39 @@ inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives( } +/** + * OpenJDK java/lang/ClassLoader + * + * Object layout: + * + * 0. object header + * 1. boolean initialized + * 2. java.lang.ClassLoader parent + * [other fields are not used] + */ +class java_lang_ClassLoader : public java_lang_Object, private FieldAccess { +private: + // Static offsets of the object's instance fields. + // TODO These offsets need to be checked on VM startup. + static const off_t offset_initialized = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t)); + static const off_t offset_parent = MEMORY_ALIGN(offset_initialized + sizeof(int32_t), SIZEOF_VOID_P); + +public: + java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {} + + // Getters. + java_handle_t* get_parent() const; + + // Invocation wrappers for static methods. + static java_handle_t* invoke_getSystemClassLoader(); +}; + +inline java_handle_t* java_lang_ClassLoader::get_parent() const +{ + return get(_handle, offset_parent); +} + + /** * OpenJDK java/lang/StackTraceElement * diff --git a/src/vm/jit/stacktrace.cpp b/src/vm/jit/stacktrace.cpp index e3389e4ac..b51154ed2 100644 --- a/src/vm/jit/stacktrace.cpp +++ b/src/vm/jit/stacktrace.cpp @@ -2,6 +2,7 @@ Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -872,17 +873,12 @@ classinfo *stacktrace_get_caller_class(int depth) #endif -/* stacktrace_first_nonnull_classloader **************************************** - - Returns the first non-null (user-defined) classloader on the stack. - If none is found NULL is returned. - - RETURN: - classloader - -*******************************************************************************/ - -classloader_t *stacktrace_first_nonnull_classloader(void) +/** + * Returns the first non-null (user-defined) classloader on the stack. + * + * @return The first non-null classloader or NULL if none is found. + */ +classloader_t* stacktrace_first_nonnull_classloader(void) { stackframeinfo_t *sfi; stackframeinfo_t tmpsfi; @@ -915,6 +911,82 @@ classloader_t *stacktrace_first_nonnull_classloader(void) } +/** + * Checks if a given classloader is equal to the the second classloader + * or one of its ancestors (parents). + * + * XXX: This helper method should be moved to java_lang_Classloader. + */ +#if defined(ENABLE_JAVASE) +static bool is_ancestor_of(classloader_t* loader, classloader_t* parent) +{ + // Iterate over chain of possible parents. + while (parent != NULL) { + + // Check if given loader is parent. + if (loader == parent) + return true; + + // Jump to next parent. + java_lang_ClassLoader jlcl(parent); + parent = jlcl.get_parent(); + } + + return false; +} +#endif /* defined(ENABLE_JAVASE) */ + + +/** + * Returns the first non-system (user-defined) classloader on the stack. + * A non-system classloader is a non-null classloader being not equal to + * the system classloader (or one of its ancestors). + * + * @return The first non-system classloader or NULL if none is found. + */ +#if defined(ENABLE_JAVASE) +classloader_t* stacktrace_first_nonsystem_classloader(void) +{ + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + methodinfo *m; + classloader_t *cl; + classloader_t *syscl; + +#if !defined(NDEBUG) + if (opt_DebugStackTrace) + log_println("[stacktrace_first_nonsystem_classloader]"); +#endif + + // Get the stackframeinfo of the current thread. + sfi = threads_get_current_stackframeinfo(); + + // Get the system class class loader. + syscl = java_lang_ClassLoader::invoke_getSystemClassLoader(); + + // Iterate over the whole stack. + for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi); + stacktrace_stackframeinfo_end_check(&tmpsfi) == false; + stacktrace_stackframeinfo_next(&tmpsfi)) { + + m = tmpsfi.code->m; + cl = class_get_classloader(m->clazz); + + if (cl == NULL) + continue; + + // XXX if a method in a class in a trusted loader is in a + // doPrivileged, return NULL (or break) here. + + if (!is_ancestor_of(cl, syscl)) + return cl; + } + + return NULL; +} +#endif /* defined(ENABLE_JAVASE) */ + + /* stacktrace_getClassContext ************************************************** Creates a Class context array. diff --git a/src/vm/jit/stacktrace.hpp b/src/vm/jit/stacktrace.hpp index 2c2920c82..ee032b2a2 100644 --- a/src/vm/jit/stacktrace.hpp +++ b/src/vm/jit/stacktrace.hpp @@ -110,6 +110,7 @@ java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t *st, in java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t *st); classinfo *stacktrace_get_caller_class(int depth); classloader_t *stacktrace_first_nonnull_classloader(void); +classloader_t *stacktrace_first_nonsystem_classloader(void); java_handle_objectarray_t *stacktrace_getClassContext(void); classinfo *stacktrace_get_current_class(void); java_handle_objectarray_t *stacktrace_get_stack(void); diff --git a/src/vm/loader.cpp b/src/vm/loader.cpp index 2dd8dac9f..e697a97dd 100644 --- a/src/vm/loader.cpp +++ b/src/vm/loader.cpp @@ -48,6 +48,7 @@ #include "vm/field.hpp" #include "vm/global.h" #include "vm/globals.hpp" +#include "vm/javaobjects.hpp" #include "vm/linker.hpp" #include "vm/loader.hpp" #include "vm/method.hpp" @@ -992,37 +993,22 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature) *******************************************************************************/ +#if defined(ENABLE_JAVASE) classinfo *load_class_from_sysloader(utf *name) { - methodinfo *m; - java_handle_t *clo; classloader_t *cl; classinfo *c; - assert(class_java_lang_Object); - assert(class_java_lang_ClassLoader); - assert(class_java_lang_ClassLoader->state & CLASS_LINKED); - - m = class_resolveclassmethod(class_java_lang_ClassLoader, - utf_getSystemClassLoader, - utf_void__java_lang_ClassLoader, - class_java_lang_Object, - false); - - if (!m) - return false; + cl = java_lang_ClassLoader::invoke_getSystemClassLoader(); - clo = vm_call_method(m, NULL); - - if (!clo) + if (cl == NULL) return false; - cl = loader_hashtable_classloader_add(clo); - c = load_class_from_classloader(name, cl); return c; } +#endif /* defined(ENABLE_JAVASE) */ /* load_class_from_classloader ************************************************* diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 23518fd85..1239da685 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -2011,7 +2011,11 @@ static char *vm_get_mainclass_from_jar(char *mainname) methodinfo *m; java_handle_t *s; +#if defined(ENABLE_JAVAME_CLDC1_1) + c = load_class_bootstrap(utf_new_char("java/util/jar/JarFile")); +#else c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile")); +#endif if (c == NULL) { exceptions_print_stacktrace();