* 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.
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.
} \
} 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
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();
}
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();
}
/* 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.
#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.
if (h == NULL)
return NULL;
-
+
// Call initializer.
(void) Reflection::invoke(m, h, args);
/* 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.
}
+/**
+ * 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<java_handle_t*>(_handle, offset_parent);
+}
+
+
/**
* GNU Classpath java/lang/StackTraceElement
*
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.
}
+/**
+ * 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<java_handle_t*>(_handle, offset_parent);
+}
+
+
/**
* OpenJDK java/lang/StackTraceElement
*
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.
#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;
}
+/**
+ * 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.
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);
#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"
*******************************************************************************/
+#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 *************************************************
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();