Index: gcv4/src/gc_for_vm.cpp
===================================================================
--- gcv4/src/gc_for_vm.cpp (revision 454089)
+++ gcv4/src/gc_for_vm.cpp (working copy)
@@ -439,7 +439,7 @@
p_global_gc->gc_v4_init();
// create a nursery for the main thread
- gc_thread_init(vm_get_gc_thread_local());
+ // gc_thread_init(vm_get_gc_thread_local());
assert (sizeof(block_info) <= 4096);
// If we hit this we should take a close look at our defines. While it is possible
Index: gcv4/src/gc_utils.cpp
===================================================================
--- gcv4/src/gc_utils.cpp (revision 454089)
+++ gcv4/src/gc_utils.cpp (working copy)
@@ -166,8 +166,7 @@
get_num_consecutive_similar_bits(uint8 *p_byte_start, unsigned int bit_index_to_search_from, unsigned int *num_consec_bits, uint8 *p_ceil)
{
if (p_ceil <= p_byte_start) {
- ASSERT(0, "Unexpected values of input prameters");
- vm_exit(-7520);
+ DIE("Unexpected values of input prameters");
}
bool is_zero_str = ((*p_byte_start) & (1 << bit_index_to_search_from)) ? false : true;
Index: include/interpreter_imports.h
===================================================================
--- include/interpreter_imports.h (revision 454089)
+++ include/interpreter_imports.h (working copy)
@@ -31,7 +31,7 @@
VMEXPORT void class_throw_linking_error_for_interpreter(Class_Handle ch,
unsigned cp_index, unsigned opcode);
-VMEXPORT struct JNIEnv_Internal* get_jni_native_intf();
+VMEXPORT JNIEnv * get_jni_native_intf();
VMEXPORT jbyte jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation loc);
VMEXPORT void jvmti_process_single_step_event(jmethodID method, jlocation location);
Index: include/jni.h
===================================================================
--- include/jni.h (revision 454089)
+++ include/jni.h (working copy)
@@ -1,4 +1,4 @@
-/*
+/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -38,7 +38,6 @@
#define JNI_VERSION_1_2 0x00010002
#define JNI_VERSION_1_4 0x00010004
-
/*
* JNI Native Method Interface - C
*/
@@ -1688,12 +1687,18 @@
jboolean ignoreUnrecognized;
} JavaVMInitArgs;
+typedef struct JavaVMAttachArgs {
+ jint version;
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
struct JNIInvokeInterface_ {
void* reserved0;
void* reserved1;
void* reserved2;
- jint (JNICALL *DestroyVM)(JavaVM*);
+ jint (JNICALL *DestroyJavaVM)(JavaVM*);
jint (JNICALL *AttachCurrentThread)(JavaVM*, void** penv, void* args);
jint (JNICALL *DetachCurrentThread)(JavaVM*);
@@ -1707,13 +1712,14 @@
const struct JNIInvokeInterface_* functions;
#ifdef __cplusplus
- jint DestroyVM() {
- return functions->DestroyVM(this);
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
}
jint AttachCurrentThread(void** penv, void* args) {
return functions->AttachCurrentThread(this, penv, args);
}
+
jint DetachCurrentThread() {
return functions->DetachCurrentThread(this);
}
@@ -1725,20 +1731,32 @@
jint AttachCurrentThreadAsDaemon(void** penv, void* args) {
return functions->AttachCurrentThreadAsDaemon(this, penv, args);
}
+
#endif
};
-
#ifdef __cplusplus
extern "C" {
#endif
-JNIEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args);
+#ifdef BUILDING_VM
+#define _JNI_EXPORT_ JNIEXPORT
+#else
+#define _JNI_EXPORT_ JNIIMPORT
+#endif
+_JNI_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * vm_args);
+
+_JNI_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf,
+ jsize bufLen,
+ jsize * nVMs);
+
+_JNI_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM ** p_vm, JNIEnv ** p_env,
+ void * vm_args);
+
#ifdef __cplusplus
}
#endif
-
#endif /* _JNI_H_ */
Index: include/open/hythread_ext.h
===================================================================
--- include/open/hythread_ext.h (revision 454089)
+++ include/open/hythread_ext.h (working copy)
@@ -148,15 +148,19 @@
IDATA VMCALL hythread_global_lock();
IDATA VMCALL hythread_global_unlock();
-void VMCALL hythread_init (hythread_library_t lib);
+void VMCALL hythread_init(hythread_library_t lib);
+void VMCALL hythread_shutdown();
+IDATA VMCALL hythread_lib_create(hythread_library_t * lib);
+void VMCALL hythread_lib_destroy(hythread_library_t lib);
//@}
/** @name Basic manipulation
*/
//@{
-IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_group_t group);
- IDATA hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data);
+IDATA VMCALL hythread_attach_ex(hythread_t *handle, hythread_library_t lib);
+IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_library_t lib, hythread_group_t group);
+IDATA hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data);
UDATA VMCALL hythread_clear_interrupted_other(hythread_t thread);
IDATA VMCALL hythread_join(hythread_t t);
IDATA VMCALL hythread_join_timed(hythread_t t, I_64 millis, IDATA nanos);
@@ -164,9 +168,8 @@
IDATA VMCALL hythread_get_self_id();
IDATA VMCALL hythread_get_id(hythread_t t);
hythread_t VMCALL hythread_get_thread(IDATA id);
-IDATA VMCALL hythread_struct_init(hythread_t *ret_thread, hythread_group_t group);
+IDATA VMCALL hythread_struct_init(hythread_t *ret_thread);
IDATA VMCALL hythread_cancel_all(hythread_group_t group);
-IDATA VMCALL hythread_wait_for_all_nondaemon_threads();
IDATA hythread_group_create(hythread_group_t *group);
IDATA VMCALL hythread_group_release(hythread_group_t group);
IDATA VMCALL hythread_group_get_list(hythread_group_t **list, int* size);
@@ -191,11 +194,11 @@
*/
//@{
- IDATA hythread_is_suspend_enabled();
- void hythread_suspend_enable();
- void hythread_suspend_disable();
- void hythread_safe_point();
- IDATA VMCALL hythread_suspend_other(hythread_t thread);
+IDATA hythread_is_suspend_enabled();
+void hythread_suspend_enable();
+void hythread_suspend_disable();
+void hythread_safe_point();
+IDATA VMCALL hythread_suspend_other(hythread_t thread);
IDATA VMCALL hythread_set_safepoint_callback(hythread_t thread, hythread_event_callback_proc callback);
hythread_event_callback_proc VMCALL hythread_get_safepoint_callback(hythread_t t);
@@ -233,22 +236,22 @@
*/
//@{
- IDATA hysem_create(hysem_t *sem, UDATA initial_count, UDATA max_count);
+IDATA hysem_create(hysem_t *sem, UDATA initial_count, UDATA max_count);
IDATA VMCALL hysem_wait_timed(hysem_t sem, I_64 ms, IDATA nano);
IDATA VMCALL hysem_wait_interruptable(hysem_t sem, I_64 ms, IDATA nano);
IDATA VMCALL hysem_getvalue(IDATA *count, hysem_t sem);
- IDATA hysem_set(hysem_t sem, IDATA count);
+IDATA hysem_set(hysem_t sem, IDATA count);
//@}
/** @name Mutex
*/
//@{
- IDATA hymutex_create (hymutex_t *mutex, UDATA flags);
- IDATA hymutex_lock(hymutex_t mutex);
- IDATA hymutex_trylock (hymutex_t mutex);
- IDATA hymutex_unlock (hymutex_t mutex);
- IDATA hymutex_destroy (hymutex_t mutex);
+IDATA hymutex_create (hymutex_t *mutex, UDATA flags);
+IDATA hymutex_lock(hymutex_t mutex);
+IDATA hymutex_trylock (hymutex_t mutex);
+IDATA hymutex_unlock (hymutex_t mutex);
+IDATA hymutex_destroy (hymutex_t mutex);
//@}
/** @name Thin monitors support
@@ -284,14 +287,9 @@
int VMCALL hythread_is_in_monitor_wait(hythread_t thread) ;
int VMCALL hythread_is_parked(hythread_t thread) ;
int VMCALL hythread_is_suspended(hythread_t thread) ;
-
-/**
- * Returns non-zero if thread is interrupted.
- *
- * @param[in] thread those attribute is read
- */
int VMCALL hythread_is_interrupted(hythread_t thread) ;
int VMCALL hythread_is_in_native(hythread_t thread) ;
+int VMCALL hythread_is_daemon(hythread_t thread) ;
/**
@@ -317,7 +315,6 @@
#define TM_THREAD_STATE_RESERVED1 JVMTI_THREAD_STATE_VENDOR_2 // 0x20000000 Defined by VM vendor.
#define TM_THREAD_STATE_RESERVED2 JVMTI_THREAD_STATE_VENDOR_3 // 0x40000000 Defined by VM vendor
-
#define TM_MUTEX_DEFAULT 0
#define TM_MUTEX_NESTED 1
#define TM_MUTEX_UNNESTED 2
Index: include/open/jthread.h
===================================================================
--- include/open/jthread.h (revision 454089)
+++ include/open/jthread.h (working copy)
@@ -81,9 +81,9 @@
} jthread_threadattr_t;
jlong jthread_thread_init(jvmti_thread_t *ret_thread, JNIEnv* env, jthread java_thread, jobject weak_ref, jlong old_thread);
- IDATA jthread_create(JNIEnv *env, jthread thread, jthread_threadattr_t *attrs);
- IDATA jthread_create_with_function(JNIEnv *env, jthread thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg);
- IDATA jthread_attach(JNIEnv* env, jthread thread);
+IDATA jthread_create(JNIEnv * jni_env, jthread thread, jthread_threadattr_t *attrs);
+IDATA jthread_create_with_function(JNIEnv * jni_env, jthread thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg);
+IDATA jthread_attach(JNIEnv * jni_env, jthread thread, jboolean daemon);
IDATA jthread_detach(jthread thread);
IDATA jthread_join(jthread thread);
IDATA jthread_timed_join(jthread thread, jlong millis, jint nanos);
@@ -92,6 +92,7 @@
IDATA jthread_exception_stop(jthread thread, jobject throwable);
IDATA jthread_sleep(jlong millis, jint nanos);
JNIEnv *jthread_get_JNI_env(jthread thread);
+IDATA jthread_wait_for_all_nondaemon_threads();
@@ -122,27 +123,9 @@
//@{
-/**
- * Sets the daemon attribute for the thread.
- *
- * JVM exits when the only threads running are all daemon threads.
- *
- * @param[in] thread those attribute is set
- * @param[in] on daemon off or on
- * @sa java.lang.Thread.setDaemon()
- */
-IDATA jthread_set_daemon(jthread thread, jboolean on);
-
-/**
- * Returns true if the threadis daemon.
- *
- * @param[in] thread those attribute is read
- * @sa java.lang.Thread.isDaemon()
- */
-jboolean jthread_is_daemon(jthread thread);
-
IDATA jthread_set_priority(jthread thread, int priority);
int jthread_get_priority(jthread thread);
+jboolean jthread_is_daemon(jthread thread);
/**
* Sets the name for the thread.
Index: include/open/thread_externals.h
===================================================================
--- include/open/thread_externals.h (revision 454089)
+++ include/open/thread_externals.h (working copy)
@@ -1,9 +1,9 @@
- /* Licensed to the Apache Software Foundation (ASF) under one or more
- /* contributor license agreements. See the NOTICE file distributed with
- /* this work for additional information regarding copyright ownership.
- /* The ASF licenses this file to You under the Apache License, Version 2.0
- /* (the "License"); you may not use this file except in compliance with
- /* the License. You may obtain a copy of the License at
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
@@ -72,13 +72,17 @@
VMEXPORT void *vm_jthread_get_tm_data(jthread thread);
/**
- * registtrate thread in VM, so it could execute Java
- */
-VMEXPORT IDATA vm_attach();
+ * Registrates current thread in VM, so it could execute Java
+ *
+ * @param[in] java_vm current thread will be attached to the specified VM
+ * @param[out] p_jni_env will point to JNI environment assocciated with the thread
+ */
+VMEXPORT jint vm_attach(JavaVM * java_vm, JNIEnv ** p_jni_env);
+
/**
- * free java related resources before thread exit
- */
-VMEXPORT IDATA vm_detach();
+ * Frees java related resources before thread exit.
+ */
+VMEXPORT jint vm_detach(jthread java_thread);
/**
* creates exception object using given class name and message and throws it
@@ -115,19 +119,12 @@
*/
VMEXPORT int ti_is_enabled();
-/**
- * get JNIEnv *
- * @return JNIEnv *
- */
-VMEXPORT JNIEnv * get_jnienv(void);
-
-
#ifdef __cplusplus
}
/**
- * all folowing entries is requiried for VM helpers only
- */
+ * all folowing entries is requiried for VM helpers only
+ */
#include "encoder.h"
Index: include/open/vm.h
===================================================================
--- include/open/vm.h (revision 454089)
+++ include/open/vm.h (working copy)
@@ -716,9 +716,6 @@
VMEXPORT Boolean vm_get_boolean_property_value_with_default(const char *property_name);
-// Exit and perform the necessary cleanup.
-VMEXPORT void vm_exit(int exit_code);
-
// end miscellaneous functions.
/////////////////////////////////////////////////////////////////
Index: include/open/vm_util.h
===================================================================
--- include/open/vm_util.h (revision 454089)
+++ include/open/vm_util.h (working copy)
@@ -46,8 +46,6 @@
// #include "object_layout.h"
#include "vm_threads.h"
-VMEXPORT void vm_exit(int exit_code);
-
unsigned sizeof_java_lang_class();
@@ -59,7 +57,7 @@
}; //VM_Global_State
-extern struct JNIEnv_Internal *jni_native_intf;
+extern JNIEnv * jni_native_intf;
extern VTable *cached_object_array_vtable_ptr;
@@ -162,17 +160,6 @@
long m_nInc;
};
-class StaticInitializer {
-public:
- StaticInitializer() {
- apr_initialize();
- }
- ~StaticInitializer() {
- apr_terminate2();
- }
-};
-
-
/**
* @brief Generates an VM's helper to invoke the provided function.
*
Index: interpreter/src/interpreter_ti.cpp
===================================================================
--- interpreter/src/interpreter_ti.cpp (revision 454089)
+++ interpreter/src/interpreter_ti.cpp (working copy)
@@ -270,7 +270,7 @@
/*
* Looks like no way to get JNIEnv from jvmtiEnv, strange.
*/
-static JNIEnv_Internal * UNUSED jvmti_test_jenv = get_jni_native_intf();
+static JNIEnv * UNUSED jvmti_test_jenv = get_jni_native_intf();
jvmtiError
interpreter_ti_getStackTrace(
Index: jitrino/src/vm/drl/DrlVMInterface.cpp
===================================================================
--- jitrino/src/vm/drl/DrlVMInterface.cpp (revision 454089)
+++ jitrino/src/vm/drl/DrlVMInterface.cpp (working copy)
@@ -480,7 +480,7 @@
DrlVMCompilationInterface::hardAssert(const char *message, int line, const char *file)
{
::std::cerr << message << " at line " << line << " of file " << file << ::std::endl;
- vm_exit(1);
+ exit(1);
}
Type*
Index: port/src/encoder/ia32_em64t/encoder.inl
===================================================================
--- port/src/encoder/ia32_em64t/encoder.inl (revision 454089)
+++ port/src/encoder/ia32_em64t/encoder.inl (working copy)
@@ -597,14 +597,14 @@
ENCODER_DECLARE_EXPORT char * jump(char * stream, char * target) {
#ifdef _EM64T_
int64 offset = target - stream;
+ // sub 2 bytes for the short version
+ offset -= 2;
if (fit8(offset)) {
- // sub 2 bytes for the short version
- offset -= 2;
// use 8-bit signed relative form
return jump8(stream, Imm_Opnd(size_8, offset));
} else if (fit32(offset)) {
- // sub 5 bytes for the long version
- offset -= 5;
+ // sub 5 (3 + 2)bytes for the long version
+ offset -= 3;
// use 32-bit signed relative form
return jump32(stream, Imm_Opnd(size_32, offset));
}
@@ -613,14 +613,14 @@
return jump(stream, rax_opnd, size_64);
#else
int32 offset = target - stream;
+ // sub 2 bytes for the short version
+ offset -= 2;
if (fit8(offset)) {
- // sub 2 bytes for the short version
- offset -= 2;
// use 8-bit signed relative form
return jump8(stream, Imm_Opnd(size_8, offset));
}
- // sub 5 bytes for the long version
- offset -= 5;
+ // sub 5 (3 + 2) bytes for the long version
+ offset -= 3;
// use 32-bit signed relative form
return jump32(stream, Imm_Opnd(size_32, offset));
#endif
Index: port/src/lil/em64t/pim/stack_iterator_em64t.cpp
===================================================================
--- port/src/lil/em64t/pim/stack_iterator_em64t.cpp (revision 454089)
+++ port/src/lil/em64t/pim/stack_iterator_em64t.cpp (working copy)
@@ -216,8 +216,9 @@
StackIterator * si = (StackIterator *)STD_MALLOC(sizeof(StackIterator));
memset(si, 0, sizeof(StackIterator));
+ Global_Env *env = VM_Global_State::loader_env;
// Setup current frame
- si->cci = vm_methods->find((NativeCodePtr)regs->rip, is_ip_past);
+ si->cci = env->vm_methods->find((NativeCodePtr)regs->rip, is_ip_past);
assert(si->cci);
init_context_from_registers(si->jit_frame_context, *regs, is_ip_past);
@@ -257,7 +258,9 @@
si->cci->get_jit()->unwind_stack_frame(si->cci->get_method(), si_get_jit_context(si));
si->jit_frame_context.is_ip_past = TRUE;
}
- si->cci = vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past);
+
+ Global_Env *vm_env = VM_Global_State::loader_env;
+ si->cci = vm_env->vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past);
#ifndef NDEBUG
if (si_is_native(si)) {
TRACE2("si", "si_goto_previous to ip = " << (void*)si_get_ip(si)
Index: port/src/lil/ia32/pim/stack_iterator_ia32.cpp
===================================================================
--- port/src/lil/ia32/pim/stack_iterator_ia32.cpp (revision 454089)
+++ port/src/lil/ia32/pim/stack_iterator_ia32.cpp (working copy)
@@ -20,7 +20,7 @@
* @version $Revision$
*/
-
+#include "environment.h"
#include "jit_intf_cpp.h"
#include "m2n.h"
#include "m2n_ia32_internal.h"
@@ -268,9 +268,9 @@
memset(res, 0, sizeof(StackIterator));
// Setup current frame
+ Global_Env *env = VM_Global_State::loader_env;
// It's possible that registers represent native code and res->cci==NULL
- res->cci = vm_methods->find((NativeCodePtr)regs->eip, is_ip_past);
-
+ res->cci = env->vm_methods->find((NativeCodePtr)regs->eip, is_ip_past);
res->c.esp = regs->esp;
res->c.p_eip = ®s->eip;
res->c.p_ebp = ®s->ebp;
@@ -316,7 +316,8 @@
if (!si->m2nfl) return;
si_unwind_from_m2n(si, over_popped);
}
- si->cci = vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past);
+ Global_Env *vm_env = VM_Global_State::loader_env;
+ si->cci = vm_env->vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past);
if (si->cci) {
TRACE2("si", ("si_goto_previous to ip = %p (%s%s)",
(void*)si_get_ip(si),
@@ -519,7 +520,6 @@
inline static uint32 unref_reg(uint32* p_reg) {
return p_reg ? *p_reg : 0;
}
-
void si_copy_to_registers(StackIterator* si, Registers* regs)
{
ASSERT_NO_INTERPRETER
Index: port/src/lil/ipf/pim/lil_code_generator_ipf.cpp
===================================================================
--- port/src/lil/ipf/pim/lil_code_generator_ipf.cpp (revision 454089)
+++ port/src/lil/ipf/pim/lil_code_generator_ipf.cpp (working copy)
@@ -2089,7 +2089,7 @@
// initialization of static members
-static StaticInitializer lil_initializer;
+// TODO: we have to get rid of memory pool in static area due to initialization problems
static tl::MemoryPool loc_mem;
const LcgIpfLoc* LcgIpfCodeGen::gp = new(loc_mem) LcgIpfLoc(LLK_Gr, 1);
const LcgIpfLoc* LcgIpfCodeGen::sp = new(loc_mem) LcgIpfLoc(LLK_Gr, 12);
Index: port/src/lil/ipf/pim/stack_iterator_ipf.cpp
===================================================================
--- port/src/lil/ipf/pim/stack_iterator_ipf.cpp (revision 454089)
+++ port/src/lil/ipf/pim/stack_iterator_ipf.cpp (working copy)
@@ -511,8 +511,9 @@
if (!si->m2nfl) return;
si_unwind_from_m2n(si);
}
+ Global_Env *env = VM_Global_State::loader_env;
si->c.is_ip_past = TRUE;
- si->cci = vm_methods->find(si_get_ip(si));
+ si->cci = env->vm_methods->find(si_get_ip(si));
si_unwind_bsp(si);
si_setup_stacked_registers(si);
}
Index: port/src/lil/lil.cpp
===================================================================
--- port/src/lil/lil.cpp (revision 454089)
+++ port/src/lil/lil.cpp (working copy)
@@ -1309,7 +1309,7 @@
break;
case LIT_StdPlaces:
c->num_std_places = i->u.std_places;
- for(j=0; jnum_locals; j++) c->std_place_types[j] = LT_Void;
+ for(j=0; jnum_std_places; j++) c->std_place_types[j] = LT_Void;
break;
case LIT_Alloc:
c->amt_alloced += i->u.alloc.num_bytes;
Index: thread/src/hythr.def
===================================================================
--- thread/src/hythr.def (revision 454089)
+++ thread/src/hythr.def (working copy)
@@ -9,6 +9,7 @@
hythread_monitor_enter
hythread_monitor_notify_all
hythread_attach
+hythread_attach_ex
hythread_monitor_destroy
hythread_monitor_num_waiting
hythread_interrupted
@@ -110,12 +111,14 @@
hymutex_destroy
-hythread_wait_for_all_nondaemon_threads
hythread_is_alive
hythread_is_terminated
hythread_init
-countdown_nondaemon_threads
-increase_nondaemon_threads_count
+hythread_shutdown
+hythread_lib_create
+hythread_lib_destroy
+hythread_lib_lock
+hythread_lib_unlock
release_start_lock
acquire_start_lock
Index: thread/src/hythr.exp
===================================================================
--- thread/src/hythr.exp (revision 454089)
+++ thread/src/hythr.exp (working copy)
@@ -8,6 +8,7 @@
hythread_monitor_enter;
hythread_monitor_notify_all;
hythread_attach;
+hythread_attach_ex;
hythread_monitor_destroy;
hythread_monitor_num_waiting;
hythread_interrupted;
@@ -121,11 +122,13 @@
hymutex_destroy;
hythread_exit;
-hythread_wait_for_all_nondaemon_threads;
hythread_is_alive;
hythread_init;
-countdown_nondaemon_threads;
-increase_nondaemon_threads_count;
+hythread_shutdown;
+hythread_lib_create;
+hythread_lib_destroy;
+hythread_lib_lock;
+hythread_lib_unlock;
set_safepoint_callback;
release_start_lock;
Index: thread/src/thread_init.c
===================================================================
--- thread/src/thread_init.c (revision 454089)
+++ thread/src/thread_init.c (working copy)
@@ -33,11 +33,10 @@
//global constants:
-//library instance
-hythread_library_t hythread_lib;
+// Global pointer to the threading library
+hythread_library_t TM_LIBRARY = NULL;
-
//Thread manager memory pool
apr_pool_t *TM_POOL = NULL;
@@ -45,7 +44,6 @@
apr_threadkey_t *TM_THREAD_KEY;
//Thread manager global lock
-hymutex_t TM_LOCK = NULL;
hymutex_t TM_START_LOCK = NULL;
hymutex_t FAT_MONITOR_TABLE_LOCK = NULL;
#define GLOBAL_MONITOR_NAME "global_monitor"
@@ -60,9 +58,6 @@
IDATA groups_count;
-IDATA nondaemon_thread_count;
-hycond_t nondaemon_thread_cond;
-
static IDATA init_group_list();
static IDATA destroy_group_list();
@@ -70,18 +65,60 @@
#include
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpres) {
if (dwReason == DLL_PROCESS_ATTACH) {
- hythread_init (NULL);
+ hythread_lib_create(&TM_LIBRARY);
}
return TRUE;
}
#else
void hythread_library_init(void) {
- hythread_init(NULL);
-
+ hythread_lib_create(&TM_LIBRARY);
}
#endif
/**
+ * Creates and initializes a threading library.
+ *
+ * @param[out] lib pointer to the created thread library
+ * @return The thead library's initStatus will be set to 0 on success or
+ * a negative value on failure.
+ *
+ * @see hythread_attach, hythread_shutdown
+ */
+IDATA VMCALL hythread_lib_create(hythread_library_t * lib) {
+ apr_status_t apr_status;
+
+ // Current implementation doesn't support more than one library instance.
+ if (TM_LIBRARY) {
+ *lib = TM_LIBRARY;
+ return TM_ERROR_NONE;
+ }
+
+ apr_status = apr_initialize();
+ assert(apr_status == APR_SUCCESS);
+
+ apr_status = apr_pool_create(&TM_POOL, NULL);
+ if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
+
+ *lib = (hythread_library_t) apr_palloc(TM_POOL, sizeof(HyThreadLibrary));
+ if (*lib == NULL) return TM_ERROR_OUT_OF_MEMORY;
+
+ hythread_init(*lib);
+ return TM_ERROR_NONE;
+}
+
+/**
+ * Shut down the threading library.
+ *
+ * @param lib the library
+ * @return none
+ *
+ * @see hythread_lib_create
+ */
+void VMCALL hythread_lib_destroy(hythread_library_t lib) {
+ apr_pool_destroy(TM_POOL);
+}
+
+/**
* Initialize a threading library.
*
* @note This must only be called once.
@@ -96,23 +133,33 @@
* @see hythread_attach, hythread_shutdown
*/
void VMCALL hythread_init(hythread_library_t lib){
- apr_status_t apr_status;
+ apr_status_t apr_status;
IDATA status;
hythread_monitor_t *mon;
- // check the someone already init the library
- if(TM_LOCK) {
- return;
- }
+
+ // Current implementation doesn't support more than one library instance.
+ if (TM_LIBRARY == NULL) {
+ TM_LIBRARY = lib;
+ }
+ assert(TM_LIBRARY == lib);
+
+ // Check if someone already initialized the library.
+ if (TM_START_LOCK != NULL) {
+ return;
+ }
apr_status = apr_initialize();
assert(apr_status == APR_SUCCESS);
- apr_status = apr_pool_create(&TM_POOL, NULL);
- assert(apr_status == APR_SUCCESS);
+ // TM_POOL will be NULL if hythread_lib_create was not used to create the library
+ if (TM_POOL == NULL) {
+ apr_status = apr_pool_create(&TM_POOL, NULL);
+ assert(apr_status == APR_SUCCESS);
+ }
apr_status = apr_threadkey_private_create(&TM_THREAD_KEY, NULL, TM_POOL);
assert(apr_status == APR_SUCCESS);
- status = hymutex_create(&TM_LOCK, TM_MUTEX_NESTED);
+ status = hymutex_create(&lib->TM_LOCK, TM_MUTEX_NESTED);
assert (status == TM_ERROR_NONE);
status = hymutex_create(&TM_START_LOCK, TM_MUTEX_NESTED);
assert (status == TM_ERROR_NONE);
@@ -128,8 +175,8 @@
//nondaemon thread barrier
////
- nondaemon_thread_count = 0;
- status = hycond_create(&nondaemon_thread_cond);
+ lib->nondaemon_thread_count = 0;
+ status = hycond_create(&lib->nondaemon_thread_cond);
assert (status == TM_ERROR_NONE);
lock_table = (hythread_monitor_t *)malloc(sizeof(hythread_monitor_t)*table_size);
@@ -152,96 +199,51 @@
*
* @see hythread_init
*/
-IDATA VMCALL hythread_shutdown(){
- IDATA status;
- apr_status_t apr_status;
- if (destroy_group_list() == TM_ERROR_NONE) {
- status=hymutex_destroy(TM_LOCK);
- if (status != TM_ERROR_NONE) return status;
- status=hymutex_destroy(TM_START_LOCK);
- if (status != TM_ERROR_NONE) return status;
- apr_status=apr_threadkey_private_delete(TM_THREAD_KEY);
- if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
- apr_pool_destroy(TM_POOL);
- return TM_ERROR_NONE;
- }
- return TM_ERROR_RUNNING_THREADS;
+void VMCALL hythread_shutdown() {
+ hythread_lib_destroy(hythread_self()->library);
}
+
/**
- * Acquires the lock over threading subsystem.
- *
- * The lock blocks new thread creation and thread exit operations.
+ * Acquires global lock of the library assocciated with the current thread.
+ *
+ * @param[in] self current thread
*/
-IDATA VMCALL hythread_global_lock() {
- return hymutex_lock(TM_LOCK);
+void VMCALL hythread_lib_lock(hythread_t self) {
+ IDATA status;
+
+ assert(self == hythread_self());
+ status = hymutex_lock(self->library->TM_LOCK);
+ assert(status == TM_ERROR_NONE);
}
/**
- * Releases the lock over threading subsystem.
- *
+ * Releases global lock of the library assocciated with the current thread.
+ *
+ * @param[in] self current thread
*/
-IDATA VMCALL hythread_global_unlock() {
- return hymutex_unlock(TM_LOCK);
-}
-
-
-IDATA increase_nondaemon_threads_count() {
+void VMCALL hythread_lib_unlock(hythread_t self) {
IDATA status;
-
- status = hymutex_lock(TM_LOCK);
- if (status != TM_ERROR_NONE) return status;
- nondaemon_thread_count++;
- status = hymutex_unlock(TM_LOCK);
- return status;
+ assert(self == hythread_self());
+ status = hymutex_unlock(self->library->TM_LOCK);
+ assert(status == TM_ERROR_NONE);
}
-IDATA countdown_nondaemon_threads() {
- IDATA status;
-
- status = hymutex_lock(TM_LOCK);
- if (status != TM_ERROR_NONE) return status;
-
- if(nondaemon_thread_count <= 0) {
- status = hymutex_unlock(TM_LOCK);
- if (status != TM_ERROR_NONE) return status;
- return TM_ERROR_ILLEGAL_STATE;
- }
- TRACE(("TM: nondaemons decreased, thread: %p count: %d", tm_self_tls, nondaemon_thread_count));
- nondaemon_thread_count--;
- if(nondaemon_thread_count == 0) {
- status = hycond_notify_all(nondaemon_thread_cond);
- TRACE(("TM: nondaemons all dead, thread: %p count: %d", tm_self_tls, nondaemon_thread_count));
- if (status != TM_ERROR_NONE){
- hymutex_unlock(TM_LOCK);
- return status;
- }
- }
-
- status = hymutex_unlock(TM_LOCK);
- return status;
+/**
+ * Acquires the lock over threading subsystem.
+ *
+ * The lock blocks new thread creation and thread exit operations.
+ */
+IDATA VMCALL hythread_global_lock() {
+ return hymutex_lock(TM_LIBRARY->TM_LOCK);
}
+
/**
- * waiting all nondaemon thread's
+ * Releases the lock over threading subsystem.
*
*/
-IDATA VMCALL hythread_wait_for_all_nondaemon_threads() {
- IDATA status;
-
- status = hymutex_lock(TM_LOCK);
- if (status != TM_ERROR_NONE) return status;
-
- while (nondaemon_thread_count) {
- status = hycond_wait(nondaemon_thread_cond, TM_LOCK);
- //check interruption and other problems
- TRACE(("TM wait for nondaemons notified, count: %d", nondaemon_thread_count));
- if(status != TM_ERROR_NONE) {
- hymutex_unlock(TM_LOCK);
- return status;
- }
- }
- status = hymutex_unlock(TM_LOCK);
- return status;
+IDATA VMCALL hythread_global_unlock() {
+ return hymutex_unlock(TM_LIBRARY->TM_LOCK);;
}
hythread_group_t get_java_thread_group(void){
@@ -297,7 +299,6 @@
return hymutex_unlock(TM_START_LOCK);
}
-
/*
// very simple Map implementation
// current scenario use only one global so it works well
@@ -350,8 +351,7 @@
* 0 on failure.
*
*/
-UDATA*
-VMCALL hythread_global (char* name) {
+UDATA* VMCALL hythread_global (char* name) {
//hythread_monitor_enter(*p_global_monitor);
int index = find_entry(name);
if(index == -1) {
Index: thread/src/thread_java_attrs.c
===================================================================
--- thread/src/thread_java_attrs.c (revision 454089)
+++ thread/src/thread_java_attrs.c (working copy)
@@ -51,3 +51,15 @@
hythread_t tm_native_thread = jthread_get_native_thread(java_thread);
return hythread_set_priority(tm_native_thread, priority);
}
+
+/**
+ * Returns daemon status for the specified thread.
+ *
+ * @param[in] java_thread thread those attribute is read
+ */
+jboolean jthread_is_daemon(jthread thread) {
+ jvmti_thread_t jvmti_thread;
+
+ jvmti_thread = hythread_get_private_data(hythread_self());
+ return jvmti_thread->daemon;
+}
Index: thread/src/thread_java_basic.c
===================================================================
--- thread/src/thread_java_basic.c (revision 454089)
+++ thread/src/thread_java_basic.c (working copy)
@@ -27,6 +27,7 @@
#include
#include
+#include "open/thread_externals.h"
#include "thread_private.h"
#include "jni.h"
@@ -35,18 +36,19 @@
void stop_callback(void);
jmethodID getRunMethod(JNIEnv *env);
+IDATA increase_nondaemon_threads_count(hythread_t self);
+IDATA countdown_nondaemon_threads(hythread_t self);
typedef struct {
- JNIEnv *jenv;
- jthread thread;
+ JavaVM * java_vm;
jboolean daemon;
- jvmtiEnv *tiEnv;
- jvmtiStartFunction tiProc;
- void *tiProcArgs;
+ jvmtiEnv *tiEnv;
+ jvmtiStartFunction tiProc;
+ void *tiProcArgs;
} wrapper_proc_data;
-IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref);
+IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref);
/**
* Creates new Java thread.
@@ -54,70 +56,60 @@
* The newly created thread will immediately start to execute the run()
* method of the appropriate thread object.
*
- * @param[in] env JNI environment that will be associated with the created Java thread
+ * @param[in] jni_env jni environment for the current thread.
* @param[in] java_thread Java thread object with which new thread must be associated.
* @param[in] attrs thread attributes.
* @sa java.lang.Thread.run()
*/
-IDATA jthread_create(JNIEnv* env, jthread java_thread, jthread_threadattr_t *attrs) {
+IDATA jthread_create(JNIEnv * jni_env, jthread java_thread, jthread_threadattr_t *attrs) {
- IDATA status;
- status = jthread_create_with_function(env,java_thread,attrs,NULL,NULL);
- return status;
+ return jthread_create_with_function(jni_env, java_thread, attrs, NULL, NULL);
}
int wrapper_proc(void *arg) {
-
- IDATA status,status1;
+ IDATA status;
+ JNIEnv * jni_env;
+ hythread_t native_thread;
+ jvmti_thread_t jvmti_thread;
+ jthread java_thread;
wrapper_proc_data *data = (wrapper_proc_data *)arg;
- JNIEnv *env = data->jenv;
- jvmtiEnv *tiEnv = data->tiEnv;
- jvmtiStartFunction tiProc = data->tiProc;
- void *tiProcArgs = data->tiProcArgs;
+
+ // Assocciation should be already done.
+ native_thread = hythread_self();
+ jvmti_thread = hythread_get_private_data(native_thread);
+ assert(jvmti_thread);
+ java_thread = jvmti_thread->thread_object;
- TRACE(("TM: Java thread started: id=%d OS_handle=%p", hythread_self()->thread_id, apr_os_thread_current()));
- //status = hythread_global_lock();
- //assert (status == TM_ERROR_NONE);
- status=vm_attach();
- if(status!=TM_ERROR_NONE)
- {
- if (!data->daemon){
- status1 = countdown_nondaemon_threads();
- assert (status1 == TM_ERROR_NONE);
- }
- return status;
+ status = vm_attach(data->java_vm, &jni_env);
+ if (status != JNI_OK) return TM_ERROR_INTERNAL;
+
+ jvmti_thread->jenv = jni_env;
+ jvmti_thread->daemon = data->daemon;
+
+ if (!jvmti_thread->daemon) {
+ increase_nondaemon_threads_count(native_thread);
}
+
+ TRACE(("TM: Java thread started: id=%d OS_handle=%p", native_thread->thread_id, apr_os_thread_current()));
+
+ // Send Thread Start event.
jvmti_send_thread_start_end_event(1);
- //status = hythread_global_unlock();
- // assert (status == TM_ERROR_NONE);
- if(tiProc!=NULL)
- {
- tiProc(tiEnv, env, tiProcArgs);
- }
- else
- {
- (*env) -> CallVoidMethodA(env, data->thread, getRunMethod(env), NULL);//for jthread_create();
- }
- jvmti_send_thread_start_end_event(0);
- (*env) -> DeleteGlobalRef(env, data->thread);
- TRACE(("TM: Java thread finished: id=%d OS_handle=%p", hythread_self()->thread_id, apr_os_thread_current()));
- assert(hythread_is_suspend_enabled());
- status=vm_detach();
- if(status!=TM_ERROR_NONE)
+ if(data->tiProc != NULL)
{
- if (!data->daemon){
- status1 = countdown_nondaemon_threads();
- assert (status1 == TM_ERROR_NONE);
- }
- return status;
+ data->tiProc(data->tiEnv, jni_env, data->tiProcArgs);
}
- assert(hythread_is_suspend_enabled());
- if (!data->daemon){
- status = countdown_nondaemon_threads();
- assert (status == TM_ERROR_NONE);
- }
- return TM_ERROR_NONE;
+ else
+ {
+ // for jthread_create();
+ (*jni_env) -> CallVoidMethodA(jni_env, java_thread, getRunMethod(jni_env), NULL);
+ }
+
+ status = jthread_detach(java_thread);
+
+ TRACE(("TM: Java thread finished: id=%d OS_handle=%p", native_thread->thread_id, apr_os_thread_current()));
+
+ return status;
}
/**
@@ -129,72 +121,57 @@
* This method of thread creation would be useful for creating TI agent threads (i.e. Java threads
* which always execute only native code).
*
- * @param[in] env JNI environment that will be associated with the created Java thread
+ * @param[in] jni_env jni environment for the current thread.
* @param[in] java_thread Java thread object with which new thread must be associated.
* @param[in] attrs thread attributes.
* @param[in] proc the start function to be executed in this thread.
* @param[in] arg The argument to the start function. Is passed as an array.
* @sa JVMTI::RunAgentThread()
*/
-IDATA jthread_create_with_function(JNIEnv *env, jthread java_thread, jthread_threadattr_t *attrs,jvmtiStartFunction proc, const void* arg)
+IDATA jthread_create_with_function(JNIEnv * jni_env, jthread java_thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg)
{
- hythread_t tm_native_thread = NULL;
- jvmti_thread_t tm_java_thread = NULL;
- wrapper_proc_data *data;
- IDATA status;
- apr_status_t apr_status;
- apr_pool_t * pool;
-
- if (env == NULL || java_thread == NULL || attrs == NULL){
- return TM_ERROR_NULL_POINTER;
+ hythread_t tm_native_thread = NULL;
+ jvmti_thread_t tm_java_thread;
+ wrapper_proc_data * data;
+ IDATA status;
+
+ if (jni_env == NULL || java_thread == NULL || attrs == NULL) {
+ return TM_ERROR_NULL_POINTER;
+ }
+ tm_native_thread = vm_jthread_get_tm_data(java_thread);
+
+ // This is for irregular use. In ordinary live valid jthread instance
+ // contains weak reference associated with it and native thread to reuse.
+ if (tm_native_thread == NULL) {
+ if( !jthread_thread_init(NULL, jni_env, java_thread, NULL, 0)) {
+ return TM_ERROR_OUT_OF_MEMORY;
}
- tm_native_thread = vm_jthread_get_tm_data(java_thread);
-
- //This is for irregular use. In ordinary live valid jthread instance
- //contains weak reference associated with it and native thread to reuse
- //if any
- ////
+ tm_native_thread = vm_jthread_get_tm_data(java_thread);
+ }
- if (tm_native_thread==NULL)
- {
- if(!jthread_thread_init(NULL,env,java_thread, NULL, 0))
- {
- return TM_ERROR_OUT_OF_MEMORY;
- }
- tm_native_thread = vm_jthread_get_tm_data(java_thread);
- }
tm_java_thread = hythread_get_private_data(tm_native_thread);
- assert(tm_java_thread);
- apr_status = apr_pool_create(&pool, 0);
- if (apr_status != APR_SUCCESS) {
- return CONVERT_ERROR(apr_status);
- }
- data = apr_palloc(pool, sizeof(wrapper_proc_data));
- if(data == NULL) {
- return TM_ERROR_OUT_OF_MEMORY;
- }
+ assert(tm_java_thread);
+ data = apr_palloc(tm_java_thread->pool, sizeof(wrapper_proc_data));
+ if (data == NULL) {
+ return TM_ERROR_OUT_OF_MEMORY;
+ }
+
// Prepare argumets for wrapper proc
- data->jenv = env;
- data->thread = tm_java_thread->thread_object;
+ status = (*jni_env) -> GetJavaVM(jni_env, &data->java_vm);
+ if (status != JNI_OK) return TM_ERROR_INTERNAL;
+
data->daemon = attrs->daemon;
- data->tiEnv = attrs->jvmti_env;
+ data->tiEnv = attrs->jvmti_env;
data->tiProc = proc;
data->tiProcArgs = (void *)arg;
- // create native thread with wrapper_proc
- if (!attrs->daemon){
- status = increase_nondaemon_threads_count();
- if (status != TM_ERROR_NONE) return status;
- }
- status = hythread_create(&tm_native_thread, (attrs->stacksize)?attrs->stacksize:1024000,
- attrs->priority, 0, wrapper_proc, data);
- if ((!attrs->daemon)&&(status != TM_ERROR_NONE)){
- countdown_nondaemon_threads();
- }
+ status = hythread_create(&tm_native_thread, (attrs->stacksize)?attrs->stacksize:1024000,
+ attrs->priority, 0, wrapper_proc, data);
+
TRACE(("TM: Created thread: id=%d", tm_native_thread->thread_id));
- return status;
+ return status;
}
/**
@@ -204,30 +181,39 @@
* and associate it with the current native thread. Nothing happens
* if this thread is already attached.
*
- * @param[in] env JNI environment that will be associated with the attached Java thread
- * @param[in] java_thread Java thread object with which the current native thread must be associated.
+ * @param[in] jni_env JNI environment for cuurent thread
+ * @param[in] java_thread j.l.Thread instance to associate with current thread
+ * @param[in] daemon JNI_TRUE if attaching thread is a daemon thread, JNI_FALSE overwise
* @sa JNI::AttachCurrentThread ()
*/
-IDATA jthread_attach(JNIEnv* env, jthread java_thread) {
-
+IDATA jthread_attach(JNIEnv * jni_env, jthread java_thread, jboolean daemon) {
hythread_t tm_native_thread;
+ jvmti_thread_t jvmti_thread;
IDATA status;
- status = hythread_attach(NULL);
- if (status != TM_ERROR_NONE){
- return status;
+
+ // Do nothing if thread already attached.
+ if (jthread_self() != NULL) return TM_ERROR_NONE;
+
+ tm_native_thread = hythread_self();
+ assert(tm_native_thread);
+
+ status = associate_native_and_java_thread(jni_env, java_thread, tm_native_thread, NULL);
+ if (status != TM_ERROR_NONE) return status;
+
+ jvmti_thread = hythread_get_private_data(tm_native_thread);
+ assert(jvmti_thread);
+ jvmti_thread->jenv = jni_env;
+ jvmti_thread->daemon = daemon;
+
+ if (!jvmti_thread->daemon) {
+ increase_nondaemon_threads_count(tm_native_thread);
}
- tm_native_thread = hythread_self();
- //I wonder if we need it.
- //since jthread already created, thus association is already done,
- //see jthread_init
- //VVVVVVVVVVVVVVVVVVVVVV
- status=associate_native_and_java_thread(env, java_thread, tm_native_thread, NULL);
- if (status != TM_ERROR_NONE){
- return status;
- }
+
+ // Send Thread Start event.
+ jvmti_send_thread_start_end_event(1);
+
TRACE(("TM: Current thread attached to jthread=%p", java_thread));
- status=vm_attach();
- return status;
+ return TM_ERROR_NONE;
}
/**
@@ -243,25 +229,24 @@
jlong jthread_thread_init(jvmti_thread_t *ret_thread, JNIEnv* env, jthread java_thread, jobject weak_ref, jlong old_thread) {
hythread_t tm_native_thread = NULL;
jvmti_thread_t tmj_thread;
- IDATA status;
+ IDATA status;
if (old_thread) {
tm_native_thread = (hythread_t)((IDATA)old_thread);
tmj_thread = (jvmti_thread_t)hythread_get_private_data(tm_native_thread);
//delete used weak reference
- if (tmj_thread->thread_ref) (*env)->DeleteGlobalRef(env, tmj_thread->thread_ref);
-
+ if (tmj_thread->thread_ref) (*env)->DeleteGlobalRef(env, tmj_thread->thread_ref);
}
- status = hythread_struct_init(&tm_native_thread, NULL);
- if(status != TM_ERROR_NONE)
- {
- return 0;
- }
- status=associate_native_and_java_thread(env, java_thread, tm_native_thread, weak_ref);
- if(status != TM_ERROR_NONE)
- {
- return 0;
- }
+
+ status = hythread_struct_init(&tm_native_thread);
+ if (status != TM_ERROR_NONE) {
+ return 0;
+ }
+
+ status = associate_native_and_java_thread(env, java_thread, tm_native_thread, weak_ref);
+ if (status != TM_ERROR_NONE) {
+ return 0;
+ }
return (jlong)((IDATA)tm_native_thread);
}
@@ -273,66 +258,73 @@
* @param[in] java_thread Java thread to be detached
*/
IDATA jthread_detach(jthread java_thread) {
- jvmti_thread_t tm_java_thread;
+ IDATA status;
hythread_t tm_native_thread;
+ jvmti_thread_t tm_jvmti_thread;
+ JNIEnv * jni_env;
+
+ assert(hythread_is_suspend_enabled());
- // Check input arg
+ // Check input arg
assert(java_thread);
- TRACE(("TM: jthread_detach %x", hythread_self()));
+ TRACE(("TM: jthread_detach %x", hythread_self()));
- tm_native_thread = vm_jthread_get_tm_data(java_thread);
- tm_java_thread = hythread_get_private_data(tm_native_thread);
+ tm_native_thread = jthread_get_native_thread(java_thread);
+ tm_jvmti_thread = hythread_get_private_data(tm_native_thread);
+ jni_env = tm_jvmti_thread->jenv;
- // Remove tm_thread_t pointer from java.lang.Thread object
- vm_jthread_set_tm_data(java_thread, NULL);
-
- vm_detach();
+ if (!tm_jvmti_thread->daemon){
+ countdown_nondaemon_threads(tm_native_thread);
+ }
- // Deallocate tm_java_thread
- apr_pool_destroy(tm_java_thread->pool);
+ // Send Thread End event
+ jvmti_send_thread_start_end_event(0);
- // Remove tm_jthread_t pointer from *tm_native_thread
- /*
- status = hythread_set_private_data(tm_native_thread, NULL);
- if (status != TM_ERROR_NONE){
- return status;
- }*/
- assert(hythread_is_suspend_enabled());
+ // Detach from VM.
+ status = vm_detach(java_thread);
+ if (status != JNI_OK) return TM_ERROR_INTERNAL;
+
+ // Delete global reference to current thread object.
+ (*jni_env)->DeleteGlobalRef(jni_env, tm_jvmti_thread->thread_object);
+ // jthread_self() will return NULL now.
+ tm_jvmti_thread->thread_object = NULL;
+
+
+ // Deallocate tm_jvmti_thread
+ //apr_pool_destroy(tm_jvmti_thread->pool);
+
+ assert(hythread_is_suspend_enabled());
return TM_ERROR_NONE;
}
-IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref)
+IDATA associate_native_and_java_thread(JNIEnv * jni_env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref)
{
- IDATA status;
+ IDATA status;
apr_status_t apr_status;
apr_pool_t *pool;
- jvmti_thread_t tm_java_thread;
- if ((env == NULL) || (java_thread == NULL)||(tm_native_thread==NULL)){
+ jvmti_thread_t tm_java_thread;
+
+ if ((jni_env == NULL) || (java_thread == NULL) || (tm_native_thread == NULL)) {
return TM_ERROR_NULL_POINTER;
}
-
tm_java_thread = hythread_get_private_data(tm_native_thread);
if (!tm_java_thread) {
apr_status = apr_pool_create(&pool, 0);
- if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
- if (pool==NULL) return TM_ERROR_OUT_OF_MEMORY;
+ if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
+ if (pool == NULL) return TM_ERROR_OUT_OF_MEMORY;
tm_java_thread = apr_palloc(pool, sizeof(JVMTIThread));
- if(tm_java_thread == NULL) {
- return TM_ERROR_OUT_OF_MEMORY;
- }
+ if (tm_java_thread == NULL) return TM_ERROR_OUT_OF_MEMORY;
tm_java_thread->pool = pool;
status = hythread_set_private_data(tm_native_thread, tm_java_thread);
- if (status != TM_ERROR_NONE){
- return status;
- }
+ if (status != TM_ERROR_NONE) return status;
}
-
- tm_java_thread->jenv = env;
- tm_java_thread->thread_object = (*env)->NewGlobalRef(env,java_thread);
- tm_java_thread->thread_ref = (thread_ref)?(*env)->NewGlobalRef(env, thread_ref):NULL;
+ // JNI environment is created when this thread attaches to VM.
+ tm_java_thread->jenv = NULL;
+ tm_java_thread->thread_object = (*jni_env)->NewGlobalRef(jni_env, java_thread);
+ tm_java_thread->thread_ref = (thread_ref) ? (*jni_env)->NewGlobalRef(jni_env, thread_ref) : NULL;
tm_java_thread->contended_monitor = 0;
tm_java_thread->wait_monitor = 0;
tm_java_thread->owned_monitors = 0;
@@ -343,7 +335,7 @@
// Associate java_thread with tm_thread
vm_jthread_set_tm_data(java_thread, tm_native_thread);
- return TM_ERROR_NONE;
+ return TM_ERROR_NONE;
}
/**
@@ -355,18 +347,17 @@
* @sa java.lang.Thread.join()
*/
IDATA jthread_join(jthread java_thread) {
-
+ IDATA status;
hythread_t tm_native_thread;
- IDATA status;
-
- if (java_thread == NULL){
- return TM_ERROR_NULL_POINTER;
- }
+
+ if (java_thread == NULL) {
+ return TM_ERROR_NULL_POINTER;
+ }
tm_native_thread = jthread_get_native_thread(java_thread);
status = hythread_join_interruptable(tm_native_thread, 0, 0);
TRACE(("TM: jthread %d joined %d", hythread_self()->thread_id, tm_native_thread->thread_id));
-
- return status;
+
+ return status;
}
/**
@@ -488,17 +479,20 @@
IDATA status;
tm_native_thread->state &= ~TM_THREAD_STATE_RUNNABLE;
- tm_native_thread->state |= TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING |
- TM_THREAD_STATE_WAITING_WITH_TIMEOUT;
+ tm_native_thread->state |= TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING |
+ TM_THREAD_STATE_WAITING_WITH_TIMEOUT;
status = hythread_sleep_interruptable(millis, nanos);
+#ifndef NDEBUG
+ if (status == TM_ERROR_INTERRUPT) {
+ TRACE(("TM: sleep interrupted status received, thread: %p", hythread_self()));
+ }
+#endif
+
+ tm_native_thread->state &= ~(TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING |
+ TM_THREAD_STATE_WAITING_WITH_TIMEOUT);
- tm_native_thread->state &= ~(TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING |
- TM_THREAD_STATE_WAITING_WITH_TIMEOUT);
tm_native_thread->state |= TM_THREAD_STATE_RUNNABLE;
- if (status == TM_ERROR_INTERRUPT) {
- TRACE(("TM: sleep interrupted status received, thread: %p", hythread_self()));
- }
return status;
}
@@ -511,21 +505,20 @@
* @param[in] java_thread java.lang.Thread object
*/
JNIEnv *jthread_get_JNI_env(jthread java_thread) {
+ hythread_t tm_native_thread;
+ jvmti_thread_t tm_java_thread;
- hythread_t tm_native_thread;
- jvmti_thread_t tm_java_thread;
-
- if (java_thread == NULL){
+ if (java_thread == NULL) {
return NULL;
- }
- tm_native_thread = jthread_get_native_thread(java_thread);
- if (tm_native_thread == NULL){
+ }
+ tm_native_thread = jthread_get_native_thread(java_thread);
+ if (tm_native_thread == NULL) {
return NULL;
- }
- tm_java_thread = hythread_get_private_data(tm_native_thread);
- if (tm_java_thread == NULL){
+ }
+ tm_java_thread = hythread_get_private_data(tm_native_thread);
+ if (tm_java_thread == NULL) {
return NULL;
- }
+ }
return tm_java_thread->jenv;
}
/**
@@ -540,11 +533,11 @@
jlong jthread_get_id(jthread java_thread) {
hythread_t tm_native_thread;
-
- tm_native_thread = jthread_get_native_thread(java_thread);
+
+ tm_native_thread = jthread_get_native_thread(java_thread);
assert(tm_native_thread);
-
- return hythread_get_id(tm_native_thread);
+
+ return hythread_get_id(tm_native_thread);
}
/**
@@ -554,19 +547,19 @@
* @return jthread for the given ID, or NULL if there are no such.
*/
jthread jthread_get_thread(jlong thread_id) {
-
- hythread_t tm_native_thread;
- jvmti_thread_t tm_java_thread;
- jthread java_thread;
+ hythread_t tm_native_thread;
+ jvmti_thread_t tm_java_thread;
+ jthread java_thread;
+
tm_native_thread = hythread_get_thread((jint)thread_id);
- if (tm_native_thread == NULL){
+ if (tm_native_thread == NULL) {
return NULL;
- }
- tm_java_thread = hythread_get_private_data(tm_native_thread);
- java_thread = tm_java_thread->thread_object;
+ }
+ tm_java_thread = hythread_get_private_data(tm_native_thread);
+ java_thread = tm_java_thread->thread_object;
assert(java_thread);
- return java_thread;
+ return java_thread;
}
/**
@@ -575,9 +568,8 @@
* @return native thread
*/
hythread_t jthread_get_native_thread(jthread thread) {
-
- assert(thread);
-
+
+ assert(thread);
return vm_jthread_get_tm_data(thread);
}
@@ -587,19 +579,19 @@
* @return Java thread
*/
jthread jthread_get_java_thread(hythread_t tm_native_thread) {
+
+ jvmti_thread_t tm_java_thread;
- jvmti_thread_t tm_java_thread;
-
- if (tm_native_thread == NULL){
+ if (tm_native_thread == NULL) {
TRACE(("TM: native thread is NULL"));
return NULL;
- }
- tm_java_thread = hythread_get_private_data(tm_native_thread);
+ }
+ tm_java_thread = hythread_get_private_data(tm_native_thread);
- if (tm_java_thread == NULL){
+ if (tm_java_thread == NULL) {
TRACE(("TM: tmj thread is NULL"));
return NULL;
- }
+ }
return tm_java_thread->thread_object;
}
@@ -610,7 +602,6 @@
* or NULL if the current native thread is not attached to JVM.
*/
jthread jthread_self(void) {
-
return jthread_get_java_thread(hythread_self());
}
@@ -622,6 +613,42 @@
return hythread_cancel_all(NULL);
}
+/**
+ * waiting all nondaemon thread's
+ *
+ */
+IDATA VMCALL jthread_wait_for_all_nondaemon_threads() {
+ hythread_t native_thread;
+ jvmti_thread_t jvmti_thread;
+ hythread_library_t lib;
+ IDATA status;
+
+ native_thread = hythread_self();
+ jvmti_thread = hythread_get_private_data(native_thread);
+ lib = native_thread->library;
+
+ status = hymutex_lock(lib->TM_LOCK);
+ if (status != TM_ERROR_NONE) return status;
+
+ if (lib->nondaemon_thread_count == 1 && !jvmti_thread->daemon) {
+ status = hymutex_unlock(lib->TM_LOCK);
+ return status;
+ }
+
+ while (lib->nondaemon_thread_count) {
+ status = hycond_wait(lib->nondaemon_thread_cond, lib->TM_LOCK);
+ //check interruption and other problems
+ TRACE(("TM wait for nondaemons notified, count: %d", nondaemon_thread_count));
+ if(status != TM_ERROR_NONE) {
+ hymutex_unlock(lib->TM_LOCK);
+ return status;
+ }
+ }
+
+ status = hymutex_unlock(lib->TM_LOCK);
+ return status;
+}
+
/*
* Auxiliary function to throw java.lang.InterruptedException
*/
@@ -631,29 +658,74 @@
jvmti_thread_t tm_java_thread;
hythread_t tm_native_thread;
jclass clazz;
- JNIEnv *env;
- TRACE(("interrupted_exception thrown"));
+ JNIEnv *env;
+
+ TRACE(("interrupted_exception thrown"));
tm_native_thread = hythread_self();
tm_java_thread = hythread_get_private_data(tm_native_thread);
- env = tm_java_thread->jenv;
- clazz = (*env) -> FindClass(env, "java/lang/InterruptedException");
- (*env) -> ThrowNew(env, clazz, "Park() is interrupted");
+ env = tm_java_thread->jenv;
+ clazz = (*env) -> FindClass(env, "java/lang/InterruptedException");
+ (*env) -> ThrowNew(env, clazz, "Park() is interrupted");
}
jmethodID getRunMethod(JNIEnv *env) {
jclass clazz;
static jmethodID run_method = NULL;
- IDATA status;
+ IDATA status;
status=acquire_start_lock();
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
//printf("run method find enter\n");
if (!run_method) {
clazz = (*env) -> FindClass(env, "java/lang/Thread");
- run_method = (*env) -> GetMethodID(env, clazz, "runImpl", "()V");
+ run_method = (*env) -> GetMethodID(env, clazz, "run", "()V");
}
status=release_start_lock();
//printf("run method find exit\n");
assert (status == TM_ERROR_NONE);
return run_method;
}
+
+IDATA increase_nondaemon_threads_count(hythread_t self) {
+ hythread_library_t lib;
+ IDATA status;
+
+ lib = self->library;
+
+ status = hymutex_lock(lib->TM_LOCK);
+ if (status != TM_ERROR_NONE) return status;
+
+ lib->nondaemon_thread_count++;
+ status = hymutex_unlock(lib->TM_LOCK);
+ return status;
+}
+
+IDATA countdown_nondaemon_threads(hythread_t self) {
+ hythread_library_t lib;
+ IDATA status;
+
+ lib = self->library;
+
+ status = hymutex_lock(lib->TM_LOCK);
+ if (status != TM_ERROR_NONE) return status;
+
+ if(lib->nondaemon_thread_count <= 0) {
+ status = hymutex_unlock(lib->TM_LOCK);
+ if (status != TM_ERROR_NONE) return status;
+ return TM_ERROR_ILLEGAL_STATE;
+ }
+
+ TRACE(("TM: nondaemons decreased, thread: %p count: %d", self, lib->nondaemon_thread_count));
+ lib->nondaemon_thread_count--;
+ if(lib->nondaemon_thread_count == 0) {
+ status = hycond_notify_all(lib->nondaemon_thread_cond);
+ TRACE(("TM: nondaemons all dead, thread: %p count: %d", self, lib->nondaemon_thread_count));
+ if (status != TM_ERROR_NONE){
+ hymutex_unlock(lib->TM_LOCK);
+ return status;
+ }
+ }
+
+ status = hymutex_unlock(lib->TM_LOCK);
+ return status;
+}
Index: thread/src/thread_native_attrs.c
===================================================================
--- thread/src/thread_native_attrs.c (revision 454089)
+++ thread/src/thread_native_attrs.c (working copy)
@@ -46,7 +46,7 @@
*/
IDATA VMCALL hythread_set_priority(hythread_t thread, UDATA priority){
apr_status_t apr_status = apr_thread_set_priority(thread->os_handle, priority);
- if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
+ if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
thread->priority = priority;
return TM_ERROR_NONE;
}
Index: thread/src/thread_native_basic.c
===================================================================
--- thread/src/thread_native_basic.c (revision 454089)
+++ thread/src/thread_native_basic.c (working copy)
@@ -31,10 +31,19 @@
#include
#include "thread_private.h"
+typedef struct {
+ hythread_t thread;
+ hythread_group_t group;
+ hythread_entrypoint_t start_proc;
+ void * start_proc_args;
+} thread_start_proc_data;
+
extern hythread_group_t TM_DEFAULT_GROUP;
+extern hythread_library_t TM_LIBRARY;
static void* APR_THREAD_FUNC thread_start_proc(apr_thread_t* thd, void *p_args);
-static hythread_t init_thread(hythread_group_t group);
+static hythread_t allocate_thread();
static void reset_thread(hythread_t thread);
+static IDATA register_to_group(hythread_t thread, hythread_group_t group);
//#define APR_TLS_USE 1
#define NAKED __declspec( naked )
@@ -51,6 +60,7 @@
#define MAX_ID 1000000
hythread_t fast_thread_array[MAX_ID];
int next_id = 1;
+
/*
IDATA add_to_fast_thread_array(hythread_t thread,int id)
{
@@ -87,18 +97,21 @@
IDATA VMCALL hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data) {
apr_threadattr_t *apr_attrs;
hythread_t new_thread;
+ thread_start_proc_data * start_proc_data;
apr_status_t apr_status;
- if (!ret_thread || !(*ret_thread)) {
- // Allocate & init thread structure
- new_thread = init_thread(group);
- if(new_thread==NULL){
- return TM_ERROR_OUT_OF_MEMORY;
- }
+ if (ret_thread) {
+ hythread_struct_init(ret_thread);
+ new_thread = *ret_thread;
} else {
- new_thread = (*ret_thread);
+ new_thread = allocate_thread();
}
+
+ if (new_thread == NULL) {
+ return TM_ERROR_OUT_OF_MEMORY;
+ }
+ new_thread->library = hythread_self()->library;
if (stacksize) {
apr_threadattr_create(&apr_attrs, new_thread->pool);
apr_threadattr_stacksize_set(apr_attrs, stacksize);
@@ -108,23 +121,27 @@
}
new_thread->priority = priority ? priority : HYTHREAD_PRIORITY_NORMAL;
+ new_thread->state = TM_THREAD_STATE_ALIVE;
//new_thread->suspend_request = suspend ? 1 : 0;
+ start_proc_data = (thread_start_proc_data *) apr_palloc(new_thread->pool, sizeof(thread_start_proc_data));
+ if (start_proc_data == NULL) {
+ return TM_ERROR_OUT_OF_MEMORY;
+ }
+
// Set up thread body procedure
- new_thread->start_proc = func;
- new_thread->start_proc_args = data;
- new_thread->state = TM_THREAD_STATE_ALIVE;
+ start_proc_data->thread = new_thread;
+ start_proc_data->group = group == NULL ? TM_DEFAULT_GROUP : group;
+ start_proc_data->start_proc = func;
+ start_proc_data->start_proc_args = data;
+
// Create APR thread using the given attributes;
- apr_status = apr_thread_create(&(new_thread->os_handle), // new thread OS handle
- new_thread->apr_attrs, // thread attr created here
- thread_start_proc, //
- (void *)new_thread, //thread_proc attrs
+ apr_status = apr_thread_create(&(new_thread->os_handle), // new thread OS handle
+ new_thread->apr_attrs, // thread attr created here
+ thread_start_proc, //
+ (void *)start_proc_data, //thread_proc attrs
new_thread->pool);
- // Store the pointer to the resulting thread
- if(ret_thread) {
- *ret_thread = new_thread;
- }
return CONVERT_ERROR(apr_status);
}
@@ -157,14 +174,19 @@
* Registers the current OS thread with the threading subsystem.
*
* @param[in] handle thread to register
+ * @param[in] lib thread library to attach to
* @param[in] group thread group, or NULL; in case of NULL this thread will go to the default group
*/
-IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_group_t group) {
+IDATA hythread_attach_to_group(hythread_t * handle, hythread_library_t lib, hythread_group_t group) {
hythread_t thread;
apr_thread_t *os_handle = NULL;
apr_os_thread_t *os_thread;
- apr_status_t apr_status;
+ apr_status_t apr_status;
+ if (lib == NULL) {
+ lib = TM_LIBRARY;
+ }
+
// Do nothing and return if the thread is already attached
thread = tm_self_tls;
if (thread) {
@@ -173,30 +195,29 @@
}
return TM_ERROR_NONE;
}
- thread = init_thread(group); // allocate & init thread structure
- if (thread==NULL){
- return TM_ERROR_OUT_OF_MEMORY;
- }
+ if (handle) {
+ hythread_struct_init(handle);
+ thread = *handle;
+ } else {
+ thread = allocate_thread();
+ }
+ if (thread == NULL) {
+ return TM_ERROR_OUT_OF_MEMORY;
+ }
+ thread->library = lib;
os_thread = apr_palloc(thread->pool, sizeof(apr_os_thread_t));
- if(os_thread == NULL) {
+ if (os_thread == NULL) {
return TM_ERROR_OUT_OF_MEMORY;
- }
+ }
*os_thread = apr_os_thread_current();
apr_status = apr_os_thread_put(&os_handle, os_thread, thread->pool);
- if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
+ if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status);
thread->os_handle = os_handle;
- thread_set_self(thread);
-
- thread->state = TM_THREAD_STATE_ALIVE | TM_THREAD_STATE_RUNNABLE;
- assert(thread == tm_self_tls);
+
TRACE(("TM: native attached: native: %p ", tm_self_tls));
-
- if (handle) {
- *handle = thread;
- }
- return TM_ERROR_NONE;
+ return register_to_group(thread, group == NULL ? TM_DEFAULT_GROUP : group);
}
/**
@@ -213,13 +234,28 @@
* @param[out] handle pointer to a hythread_t to be set (will be ignored if null)
* @return 0 on success or negative value on failure
*
+ * @note (*handle) should be NULL or point to hythread_t structure
* @see hythread_detach
*/
IDATA VMCALL hythread_attach(hythread_t *handle) {
- return hythread_attach_to_group(handle, NULL);
+ return hythread_attach_to_group(handle, TM_LIBRARY, NULL);
}
/**
+ * Attach an OS thread to the threading library.
+ *
+ * @param[out] handle pointer to a hythread_t to be set (will be ignored if null)
+ * @param[in] lib thread library to attach thread to
+ * @return 0 on success or negative value on failure
+ *
+ * @note (*handle) should be NULL or point to hythread_t structure
+ * @see hythread_detach
+ */
+IDATA VMCALL hythread_attach_ex(hythread_t *handle, hythread_library_t lib) {
+ return hythread_attach_to_group(handle, lib, NULL);
+}
+
+/**
* Detaches a thread from the threading library.
*
* @note Assumes that the thread being detached is already attached.
@@ -237,22 +273,23 @@
*/
void VMCALL hythread_detach(hythread_t thread) {
// Acquire global TM lock to prevent concurrent acccess to thread list
- IDATA status;
+ IDATA status;
+
+ assert(thread == tm_self_tls);
status = hythread_global_lock(NULL);
- assert (status == TM_ERROR_NONE);
-
- if (!(thread = tm_self_tls)) {
- status = hythread_global_unlock(NULL);
- assert (status == TM_ERROR_NONE);
- return;
- }
-
- status = thread_destroy(thread); // Remove thread from the list of thread
assert (status == TM_ERROR_NONE);
- thread_set_self(NULL);
- status = hythread_global_unlock(NULL);
- assert (status == TM_ERROR_NONE);
+
+ thread_set_self(NULL);
+ fast_thread_array[thread->thread_id] = NULL;
+
+ thread->prev->next = thread->next;
+ thread->next->prev = thread->prev;
+ thread->group->threads_count--;
+
+ hythread_global_unlock(NULL);
+ assert(status == TM_ERROR_NONE);
}
+
/**
* Waits until the selected thread finishes execution.
*
@@ -481,66 +518,6 @@
return TM_ERROR_NONE;
}
-//==============================================================================
-// Private functions
-/*
- */
-IDATA thread_destroy(hythread_t thread) {
-
- // Acquire global TM lock to prevent concurrent acccess to thread list
- IDATA status;
- status =hythread_global_lock(NULL);
- if (status != TM_ERROR_NONE) return status;
- thread->prev->next = thread->next;
- thread->next->prev = thread->prev;
- thread->group->threads_count--;
-
- //fast_thread_array[thread->thread_id] = NULL;
-
- status =hythread_global_unlock(NULL);
- if (status != TM_ERROR_NONE) return status;
- return TM_ERROR_NONE;
-}
-/*
- */
-IDATA allocate_thread(hythread_t thread, hythread_group_t group) {
- int id = 0;
- hythread_t cur, prev;
- IDATA status;
- //thread_list points to the dummy thread, which is not actual thread, just
- //a auxiliary thread structure to maintain the thread list
- /////
-
- // Acquire global TM lock to prevent concurrent acccess to thread list
- status =hythread_global_lock(NULL);
- if (status != TM_ERROR_NONE) return status;
-
- // Append the thread to the list of threads
- cur = group->thread_list->next;
- if (thread->thread_id) {
- id = thread->thread_id;
- } else {
- id = ++next_id;
- }
- if (id>=MAX_ID){
- hythread_global_unlock(NULL);
- return TM_ERROR_OUT_OF_MEMORY;
- }
- prev = cur->prev;
-
- thread->next = cur;
- thread->prev = prev;
- prev->next = cur->prev = thread;
- thread->thread_id = id;
- fast_thread_array[id] = thread;
- /*status=add_to_fast_thread_array(thread,id);
- if (status != TM_ERROR_NONE) return status;*/
- status=hythread_global_unlock(NULL);
- if (status != TM_ERROR_NONE) return status;
- return TM_ERROR_NONE;
-
-}
-
/**
* Terminates a running thread.
*
@@ -570,14 +547,14 @@
group = TM_DEFAULT_GROUP;
}
- iter = hythread_iterator_create (group);
+ iter = hythread_iterator_create(group);
while((next = hythread_iterator_next (&iter)) != NULL) {
- if(next != self) {
- hythread_cancel(next);
+ if(next != self) {
+ hythread_cancel(next);
//since this method being used at shutdown it does not
//males any sence to exit on error, but continue terminating threads
- }
- }
+ }
+ }
return TM_ERROR_NONE;
}
@@ -586,44 +563,75 @@
* Allocates and initializes a new thread_t structure.
*
*/
-IDATA VMCALL hythread_struct_init(hythread_t *ret_thread, hythread_group_t group) {
+IDATA VMCALL hythread_struct_init(hythread_t *ret_thread) {
if (*ret_thread) {
reset_thread(*ret_thread);
- } else {
- (*ret_thread) = init_thread(group);
+ return TM_ERROR_NONE;
}
- if ((*ret_thread)==NULL)
- {
- return TM_ERROR_OUT_OF_MEMORY;
- }
- return TM_ERROR_NONE;
+ (*ret_thread) = allocate_thread();
+ return (*ret_thread) == NULL ? TM_ERROR_OUT_OF_MEMORY : TM_ERROR_NONE;
}
+//==============================================================================
+// Private functions
/*
+ */
+static IDATA register_to_group(hythread_t thread, hythread_group_t group) {
+ IDATA status;
+ hythread_t cur, prev;
+
+ assert(thread);
+ assert(group);
+
+ // Acquire global TM lock to prevent concurrent acccess to thread list
+ status = hythread_global_lock(NULL);
+ if (status != TM_ERROR_NONE) return status;
+
+ thread_set_self(thread);
+ assert(thread == tm_self_tls);
+
+ thread->state = TM_THREAD_STATE_ALIVE | TM_THREAD_STATE_RUNNABLE;
+
+ if (!thread->thread_id) {
+ ++next_id;
+ thread->thread_id = next_id;
+ if (next_id >= MAX_ID) {
+ hythread_global_unlock(NULL);
+ return TM_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ fast_thread_array[thread->thread_id] = thread;
+
+ thread->group = group;
+ group->threads_count++;
+ cur = group->thread_list->next;
+ prev = cur->prev;
+ thread->next = cur;
+ thread->prev = prev;
+ prev->next = cur->prev = thread;
+ return hythread_global_unlock(NULL);
+}
+
+/*
* Allocates and initializes a new thread_t structure
*
* @return created and initialized thread_t structure
*/
-static hythread_t init_thread(hythread_group_t group) {
+static hythread_t allocate_thread() {
apr_pool_t *pool;
- apr_status_t apr_status;
+ apr_status_t apr_status;
hythread_t ptr;
- IDATA status;
+ IDATA status;
- if (!group) {
- group = TM_DEFAULT_GROUP;
- }
+ apr_status = apr_pool_create(&pool, TM_POOL);
+ if((apr_status != APR_SUCCESS) || (pool == NULL)) return NULL;
- apr_status = apr_pool_create(&pool, group->pool);
- if((apr_status!=APR_SUCCESS)||(pool==NULL))
- return NULL;
ptr = (hythread_t )apr_pcalloc(pool, sizeof(HyThread));
- if (ptr==NULL)
- return NULL;
+ if (ptr == NULL) return NULL;
+
ptr->pool = pool;
- ptr->group = group;
ptr->os_handle = NULL;
- ptr->next = ptr->prev = ptr;
ptr->priority = HYTHREAD_PRIORITY_NORMAL;
// not implemented
//ptr->big_thread_local_storage = (void **)apr_pcalloc(pool, sizeof(void*)*tm_tls_capacity);
@@ -632,91 +640,94 @@
ptr->suspend_request = 0;
ptr->suspend_disable_count = 0;
status = hylatch_create(&ptr->join_event, 1);
- assert (status == TM_ERROR_NONE);
- status = hylatch_create(&ptr->safe_region_event, 1);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
+ status = hylatch_create(&ptr->safe_region_event, 1);
+ assert (status == TM_ERROR_NONE);
status = hysem_create(&ptr->resume_event, 0, 1);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
status = hysem_create(&ptr->park_event, 0, 1);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
status = hysem_create(&ptr->sleep_event, 0, 1);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
ptr->state = TM_THREAD_STATE_ALLOCATED;
- status = allocate_thread(ptr, group);
- if (status !=TM_ERROR_NONE)
- {
- return NULL;
- }
- group->threads_count++;
-
return ptr;
}
static void reset_thread(hythread_t thread) {
apr_status_t apr_status;
- IDATA status;
- apr_thread_join(&apr_status, thread->os_handle);
+ IDATA status;
+ if (thread->os_handle) {
+ apr_thread_join(&apr_status, thread->os_handle);
assert(!apr_status);
+ }
+
thread->os_handle = NULL;
thread->priority = HYTHREAD_PRIORITY_NORMAL;
// not implemented
//ptr->big_thread_local_storage = (void **)apr_pcalloc(pool, sizeof(void*)*tm_tls_capacity);
- thread->next = thread->prev = thread;
+
// Suspension
thread->suspend_request = 0;
thread->suspend_disable_count = 0;
status = hylatch_set(thread->join_event, 1);
- assert (status == TM_ERROR_NONE);
- status = hylatch_set(thread->safe_region_event, 1);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
+ status = hylatch_set(thread->safe_region_event, 1);
+ assert (status == TM_ERROR_NONE);
status = hysem_set(thread->resume_event, 0);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
status = hysem_set(thread->park_event, 0);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
status = hysem_set(thread->sleep_event, 0);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
thread->state = TM_THREAD_STATE_ALLOCATED;
- status =allocate_thread(thread, thread->group);
- if (status!=TM_ERROR_NONE)
- {
- thread=NULL;
- }
- thread->group->threads_count++;
}
// Wrapper around user thread start proc. Used to perform some duty jobs
// right after thread is started.
//////
static void* APR_THREAD_FUNC thread_start_proc(apr_thread_t* thd, void *p_args) {
- IDATA status;
- hythread_t thread = (hythread_t )p_args;
+ IDATA status;
+ hythread_t thread;
+ thread_start_proc_data * start_proc_data;
+
+ start_proc_data = (thread_start_proc_data *) p_args;
+ thread = start_proc_data->thread;
TRACE(("TM: native thread started: native: %p tm: %p", apr_os_thread_current(), thread));
+
+ status = register_to_group(thread, start_proc_data->group);
+ if (status != TM_ERROR_NONE) {
+ thread->exit_value = status;
+ return &thread->exit_value;
+ }
+
// Also, should it be executed under TM global lock?
thread->os_handle = thd; // DELETE?
- thread_set_self(thread);
status = hythread_set_priority(thread, thread->priority);
- //assert (status == TM_ERROR_NONE);//now we down - fixme
+ //assert (status == TM_ERROR_NONE);//now we down - fixme
thread->state |= TM_THREAD_STATE_RUNNABLE;
- // Do actual call of the thread body supplied by the user
- thread->start_proc(thread->start_proc_args);
+ // Do actual call of the thread body supplied by the user.
+ start_proc_data->start_proc(start_proc_data->start_proc_args);
- // shutdown sequence
+ // Shutdown sequence.
status = hythread_global_lock(NULL);
assert (status == TM_ERROR_NONE);
assert(hythread_is_suspend_enabled());
thread->state = TM_THREAD_STATE_TERMINATED | (TM_THREAD_STATE_INTERRUPTED & thread->state);
- // Send join event to those threads who called join on this thread
+ thread->exit_value = 0;
+
+ hythread_detach(thread);
+ // Send join event to those threads who called join on this thread.
hylatch_count_down(thread->join_event);
- status = thread_destroy(thread); // Remove thread from the list of thread
- assert (status == TM_ERROR_NONE);
- // Cleanup TLS after thread completes
- thread_set_self(NULL);
+
status = hythread_global_unlock(NULL);
- assert (status == TM_ERROR_NONE);
+ assert (status == TM_ERROR_NONE);
+
+ // TODO: It seems it is there is no need to call apr_thread_exit.
+ // Current thread should automatically exit upon returning from this function.
return (void *)(IDATA)apr_thread_exit(thd, APR_SUCCESS);
}
@@ -733,12 +744,8 @@
}
apr_pool_t* get_local_pool() {
- hythread_t self = tm_self_tls;
- if(self == NULL) {
- return TM_POOL;
- } else {
- return self->pool;
- }
+ hythread_t self = tm_self_tls;
+ return self == NULL ? TM_POOL : self->pool;
}
/**
Index: thread/src/thread_native_state.c
===================================================================
--- thread/src/thread_native_state.c (revision 454089)
+++ thread/src/thread_native_state.c (working copy)
@@ -33,9 +33,7 @@
*
* @param[in] thread those attribute is read
*/
-int VMCALL hythread_is_alive(hythread_t thread) {
- return thread->state & TM_THREAD_STATE_ALIVE;
-};
+int VMCALL hythread_is_alive(hythread_t thread) { return thread->state & TM_THREAD_STATE_ALIVE ; };
/**
* Returns non-zero if thread is blocked on monitor enter.
Index: thread/src/thread_native_suspend.c
===================================================================
--- thread/src/thread_native_suspend.c (revision 454089)
+++ thread/src/thread_native_suspend.c (working copy)
@@ -104,6 +104,11 @@
void VMCALL hythread_suspend_disable()
{
register hythread_t thread;
+#ifndef NDEBUG
+ // Check that current thread is in default thread group.
+ // Justification: GC suspends and enumerates threads from default group only.
+ assert(tm_self_tls->group == TM_DEFAULT_GROUP);
+#endif
#ifdef FS14_TLS_USE
__asm {
Index: thread/src/thread_private.h
===================================================================
--- thread/src/thread_private.h (revision 454089)
+++ thread/src/thread_private.h (working copy)
@@ -107,7 +107,7 @@
#endif
/**
- * get_local_pool() function return apr pool asociated with the current thread.
+ * get_local_pool() function return apr pool associated with the current thread.
* the memory could be allocated without lock using this pool
* dealocation should be done in the same thread, otherwise
* local_pool_cleanup_register() should be called
@@ -153,6 +153,9 @@
typedef struct HyThreadLibrary {
IDATA a;
+ hymutex_t TM_LOCK;
+ IDATA nondaemon_thread_count;
+ hycond_t nondaemon_thread_cond;
} HyThreadLibrary;
@@ -161,6 +164,12 @@
* Native thread control structure.
*/
typedef struct HyThread {
+
+ /**
+ * Each thread keeps a pointer to the libary it belongs to.
+ */
+ HyThreadLibrary * library;
+
// Suspension
/**
@@ -279,14 +288,8 @@
/**
* Hint for scheduler about thread priority
*/
- IDATA priority;
+ IDATA priority;
- /**
- * Is this thread daemon?
- */
- IDATA daemon;
-
-
// Monitors
/**
@@ -306,18 +309,7 @@
*/
apr_threadattr_t *apr_attrs;
-
/**
- * Procedure that describes thread body to be executed.
- */
- hythread_entrypoint_t start_proc;
-
- /**
- * Arguments to be passed to the thread body.
- */
- void *start_proc_args;
-
- /**
* Array representing thread local storage
*/
void *thread_local_storage[10];
@@ -400,6 +392,11 @@
*/
jobject thread_ref;
+ /**
+ * Is this thread daemon?
+ */
+ IDATA daemon;
+
} JVMTIThread;
@@ -603,19 +600,12 @@
* threads at shutdown.
*/
-IDATA countdown_nondaemon_threads();
-IDATA increase_nondaemon_threads_count();
-
-IDATA VMCALL hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data);
-
typedef void (*tm_thread_event_callback_proc)(void);
IDATA VMCALL set_safepoint_callback(hythread_t thread, tm_thread_event_callback_proc callback);
IDATA acquire_start_lock(void);
IDATA release_start_lock(void);
-IDATA thread_destroy(hythread_t thread);
-
IDATA thread_sleep_impl(I_64 millis, IDATA nanos, IDATA interruptable);
IDATA condvar_wait_impl(hycond_t cond, hymutex_t mutex, I_64 ms, IDATA nano, IDATA interruptable);
IDATA monitor_wait_impl(hythread_monitor_t mon_ptr, I_64 ms, IDATA nano, IDATA interruptable);
Index: vmcore/include/environment.h
===================================================================
--- vmcore/include/environment.h (revision 454089)
+++ vmcore/include/environment.h (working copy)
@@ -22,31 +22,40 @@
#ifndef _ENVIRONMENT_H
#define _ENVIRONMENT_H
-#include "tl/memory_pool.h"
+#include
+#include
+
+#include "open/hythread.h"
+#include "open/compmgr.h"
+#include "open/em_vm.h"
+
#include "String_Pool.h"
#include "vm_core_types.h"
#include "object_handles.h"
#include "jvmti_internal.h"
-#include "open/compmgr.h"
-#include "open/em_vm.h"
+#include "method_lookup.h"
typedef struct NSOTableItem NSOTableItem;
typedef struct DynamicCode DynamicCode;
typedef struct Assertion_Registry Assertion_Registry;
struct Global_Env {
- public:
- tl::MemoryPool& mem_pool; // memory pool
- String_Pool string_pool; // string table
+ public:
+ apr_pool_t* mem_pool; // memory pool
BootstrapClassLoader* bootstrap_class_loader;
- JavaVMInitArgs vm_arguments;
UserDefinedClassLoader* system_class_loader;
- Properties& properties;
+ Properties* properties;
DebugUtilsTI* TI;
NSOTableItem* nsoTable;
void* portLib; // Classlib's port library
DynamicCode* dcList;
Assertion_Registry* assert_reg;
+ Method_Lookup_Table* vm_methods;
+ hythread_library_t hythread_lib;
+ String_Pool string_pool; // string table
+ JavaVMInitArgs vm_arguments;
+
+
//
// globals
//
@@ -127,6 +136,7 @@
Class* java_lang_ExceptionInInitializerError_Class;
Class* java_lang_NullPointerException_Class;
Class* java_lang_StackOverflowError_Class;
+ Class* java_lang_ThreadDeathError_Class;
Class* java_lang_ClassNotFoundException_Class;
Class* java_lang_NoClassDefFoundError_Class;
@@ -137,7 +147,7 @@
Class* java_lang_ClassCastException_Class;
Class* java_lang_OutOfMemoryError_Class;
ObjectHandle java_lang_OutOfMemoryError;
-
+ ObjectHandle java_lang_ThreadDeathError;
// object of java.lang.Error class used for JVMTI JIT PopFrame support
ObjectHandle popFrameException;
@@ -163,8 +173,12 @@
VTable* JavaLangString_VTable;
Allocation_Handle JavaLangString_allocation_handle;
+ // Keeps uncaught exception for the thread which is destroying VM.
+ jthrowable uncaught_exception;
+
// Offset to the vm_class field in java.lang.Class;
unsigned vm_class_offset;
+
/**
* Shutting down state.
* 0 - working
@@ -172,7 +186,7 @@
* 2 - deadly errors in shutdown
*/
int shutting_down;
-
+
// FIXME
// The whole environemt will be refactored to VM instance
// The following contains a cached copy of EM interface table
@@ -180,13 +194,17 @@
OpenInstanceHandle em_instance;
OpenEmVmHandle em_interface;
- //
- // constructor
- //
- Global_Env(tl::MemoryPool& mm, Properties& prop);
- // function is used instead of destructor to uninitialize manually
- void EnvClearInternals();
+ Global_Env(apr_pool_t * pool);
+ ~Global_Env();
+ void * operator new(size_t size, apr_pool_t * pool) {
+ return apr_palloc(pool, sizeof(Global_Env));
+ }
+
+ void operator delete(void *) {}
+
+ void operator delete(void * mem, apr_pool_t * pool) {};
+
//
// determine bootstrapping of root classes
//
Index: vmcore/include/init.h
===================================================================
--- vmcore/include/init.h (revision 454089)
+++ vmcore/include/init.h (working copy)
@@ -25,24 +25,18 @@
#include "environment.h"
-bool vm_init(Global_Env *env);
-int run_java_main(char *classname, char **j_argv, int j_argc, Global_Env *p_env);
-int run_main_platform_specific(char *classname, char **j_argv, int j_argc, Global_Env *p_env);
+jint vm_attach_internal(JNIEnv ** p_jni_env, jthread * java_thread,
+ JavaVM * java_vm, jobject group,
+ char * name, jboolean daemon);
+jint vm_init1(JavaVM_Internal * java_vm, JavaVMInitArgs * vm_arguments);
+jint vm_init2(JNIEnv * jni_env);
+jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread);
+void vm_exit(int exit_code);
-JavaVMInitArgs* parse_cmd_arguments(int argc, char *argv[], char **class_name, char **jar_file, int *p_java_arg_num);
-void clear_vm_arguments(JavaVMInitArgs* vm_args);
void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments);
void set_log_levels_from_cmd(JavaVMInitArgs* vm_arguments);
void parse_vm_arguments(Global_Env *p_env);
void parse_jit_arguments(JavaVMInitArgs* vm_arguments);
void print_generic_help();
-void create_vm(Global_Env *p_env, JavaVMInitArgs* vm_arguments);
-void destroy_vm(Global_Env *p_env);
-
-/*
- * declared in vm_main.cpp
- */
-extern Global_Env env;
-
#endif //_INIT_H
Index: vmcore/include/jni_direct.h
===================================================================
--- vmcore/include/jni_direct.h (revision 454089)
+++ vmcore/include/jni_direct.h (working copy)
@@ -20,44 +20,34 @@
*/
-
-
-
#ifndef _JNI_DIRECT_H_
#define _JNI_DIRECT_H_
-#include "jni.h"
+#include
+#include
+
#include "open/types.h"
+
+#include "jni.h"
#include "Class.h"
-struct _jfieldID : public Field {
-};
+typedef struct JavaVM_Internal JavaVM_Internal;
+typedef struct JNIEnv_Internal JNIEnv_Internal;
-VMEXPORT jint JNICALL GetVersion(JNIEnv *env);
-
struct JavaVM_Internal : public JavaVM_External {
- JavaVM_Internal(const JNIInvokeInterface_ *_functions,
- Global_Env *_vm_env,
- void *_reserved) : vm_env(_vm_env), reserved(_reserved)
- {
- functions = _functions;
- }
- Global_Env* vm_env;
+ apr_pool_t * pool;
+ Global_Env * vm_env;
+ APR_RING_ENTRY(JavaVM_Internal) link;
void* reserved;
};
struct JNIEnv_Internal : public JNIEnv_External {
- JNIEnv_Internal(const JNINativeInterface_ *_functions,
- JavaVM_Internal *_vm,
- void *_reserved0) : vm(_vm), reserved0(_reserved0)
- {
- functions = _functions;
- }
JavaVM_Internal* vm;
void *reserved0;
};
-void jni_init();
+struct _jfieldID : public Field {
+};
jmethodID reflection_unreflect_method(JNIEnv *jenv, jobject ref_method);
jmethodID reflection_unreflect_constructor(JNIEnv *jenv, jobject ref_constructor);
@@ -606,7 +596,7 @@
VMEXPORT jlong JNICALL GetDirectBufferCapacity(JNIEnv* env, jobject buf);
-VMEXPORT jint JNICALL DestroyVM(JavaVM*);
+VMEXPORT jint JNICALL DestroyJavaVM(JavaVM*);
VMEXPORT jint JNICALL AttachCurrentThread(JavaVM*, void** penv, void* args);
VMEXPORT jint JNICALL DetachCurrentThread(JavaVM*);
Index: vmcore/include/jni_utils.h
===================================================================
--- vmcore/include/jni_utils.h (revision 454089)
+++ vmcore/include/jni_utils.h (working copy)
@@ -23,6 +23,7 @@
#ifndef _JNI_UTILS_H_
#define _JNI_UTILS_H_
+#include "environment.h"
#include "object_handles.h"
#include "platform.h"
#include "jni_direct.h"
@@ -39,7 +40,6 @@
VMEXPORT ClassLoaderHandle class_loader_lookup(jobject loader);
VMEXPORT void class_loader_load_native_lib(const char* lib, ClassLoaderHandle loader);
VMEXPORT ClassLoaderHandle class_loader_find_if_exists(jobject loader);
-VMEXPORT void class_loader_set_system_class_loader(ClassLoaderHandle);
VMEXPORT jvalue *get_jvalue_arg_array(Method *method, va_list args);
@@ -95,6 +95,9 @@
// String* parameter (instead of const char* in JNI FindClass)
jclass FindClass(JNIEnv* env_ext, String* name);
+JavaVM * jni_get_java_vm(JNIEnv * jni_env);
+Global_Env * jni_get_vm_env(JNIEnv * jni_env);
+
/* global handles */
extern ObjectHandle gh_jlc; //java.lang.Class
extern ObjectHandle gh_jls; //java.lang.String
Index: vmcore/include/method_lookup.h
===================================================================
--- vmcore/include/method_lookup.h (revision 454089)
+++ vmcore/include/method_lookup.h (working copy)
@@ -86,7 +86,4 @@
}; //class Method_Lookup_Table
-VMEXPORT extern Method_Lookup_Table *vm_methods;
-
-
#endif //_METHOD_LOOKUP_H_
Index: vmcore/include/natives_support.h
===================================================================
--- vmcore/include/natives_support.h (revision 454089)
+++ vmcore/include/natives_support.h (working copy)
@@ -60,9 +60,9 @@
/**
* Initializes natives_support module. Caller must provide thread safety.
*
- * @return Returns true if initialized successfully.
+ * @return Returns JNI_OK if initialized successfully.
*/
-bool
+jint
natives_init();
/**
Index: vmcore/include/properties.h
===================================================================
--- vmcore/include/properties.h (revision 454089)
+++ vmcore/include/properties.h (working copy)
@@ -279,21 +279,6 @@
bucket = (Prop_entry**)STD_CALLOC(sizeof(Prop_entry*), size_);
iterator = new Iterator(this);
}
-#ifdef USE_MEM_MANAGER_FOR_ALLOCATION
-public:
- void *operator new(size_t sz, tl::MemoryPool& m) {
- return m.alloc(sz);
- }
- void operator delete(void *obj, tl::MemoryPool& m){
- //do nothing
- };
- void *operator new(size_t sz) {
- return m_malloc(sz);
- }
- void operator delete(void *obj){
- m_free(obj);
- };
-#endif
};
typedef struct _properties* PropertiesHandle;
Index: vmcore/include/thread_manager.h
===================================================================
--- vmcore/include/thread_manager.h (revision 454089)
+++ vmcore/include/thread_manager.h (working copy)
@@ -28,15 +28,8 @@
extern "C" {
#endif
-
-void vm_thread_shutdown();
-void vm_thread_init(Global_Env *p_env);
-
-void vm_thread_attach();
-void vm_thread_detach();
-
void free_this_thread_block(VM_thread *);
-VM_thread * get_a_thread_block();
+VM_thread * get_a_thread_block(JavaVM_Internal * java_vm);
extern volatile VM_thread *p_the_safepoint_control_thread; // only set when a gc is happening
Index: vmcore/include/version_svn_tag.h
===================================================================
--- vmcore/include/version_svn_tag.h (revision 454089)
+++ vmcore/include/version_svn_tag.h (working copy)
@@ -18,6 +18,6 @@
#ifndef _VERSION_SVN_TAG_
#define _VERSION_SVN_TAG_
-#define VERSION_SVN_TAG "453599"
+#define VERSION_SVN_TAG "454089"
#endif // _VERSION_SVN_TAG_
Index: vmcore/include/vm_threads.h
===================================================================
--- vmcore/include/vm_threads.h (revision 454089)
+++ vmcore/include/vm_threads.h (working copy)
@@ -31,14 +31,18 @@
#include "vm_process.h"
#endif
+#include
+
#include "open/types.h"
#include "open/hythread.h"
#include "open/ti_thread.h"
+
#include "vm_core_types.h"
#include "object_layout.h"
#include "open/vm_gc.h"
#include "exceptions_type.h"
#include "jvmti.h"
+#include "jni_direct.h"
//
@@ -66,10 +70,17 @@
class VM_thread {
public:
- // FIXME: workaround for strange bug. If this line is removed Visual Stidio
- // has corrupted list of modules and no debug info at all.
- void* system_private_data;
+ /**
+ * Memory pool where this structure is allocated.
+ * This pool should be used by current thread for memory allocations.
+ */
+ apr_pool_t * pool;
+ /**
+ * JNI environment associated with this thread.
+ */
+ JNIEnv_Internal * jni_env;
+
// In case exception is thrown, Exception object is put here
// TODO: Needs to be replaced with jobject!
//volatile ManagedObject* p_exception_object;
Index: vmcore/src/class_support/Assertion_Registry.cpp
===================================================================
--- vmcore/src/class_support/Assertion_Registry.cpp (revision 454089)
+++ vmcore/src/class_support/Assertion_Registry.cpp (working copy)
@@ -22,11 +22,13 @@
#define LOG_DOMAIN "vm.core"
#include "cxxlog.h"
+#include
+
#include "assertion_registry.h"
void Assertion_Registry::add_class(const Global_Env* genv, const char* name, unsigned len, bool value) {
- Assertion_Record* rec = (Assertion_Record*)genv->mem_pool.alloc(
- sizeof(Assertion_Record) + len * sizeof(char));
+ Assertion_Record* rec = (Assertion_Record*)
+ apr_palloc(genv->mem_pool, sizeof(Assertion_Record) + len * sizeof(char));
rec->status = value;
rec->len = len;
strncpy(rec->name, name, len);
@@ -36,8 +38,8 @@
}
void Assertion_Registry::add_package(const Global_Env* genv, const char* name, unsigned len, bool value) {
- Assertion_Record* rec = (Assertion_Record*)genv->mem_pool.alloc(
- sizeof(Assertion_Record) + len * sizeof(char));
+ Assertion_Record* rec = (Assertion_Record*)
+ apr_palloc(genv->mem_pool, sizeof(Assertion_Record) + len * sizeof(char));
rec->status = value;
rec->len = len;
strncpy(rec->name, name, len);
Index: vmcore/src/class_support/C_Interface.cpp
===================================================================
--- vmcore/src/class_support/C_Interface.cpp (revision 454089)
+++ vmcore/src/class_support/C_Interface.cpp (working copy)
@@ -313,7 +313,8 @@
void method_set_relocatable(Method_Handle m, JIT_Handle j, NativeCodePtr code_address, Boolean is_relocatable)
{
- CodeChunkInfo *cci = vm_methods->find(code_address);
+ Global_Env *env = VM_Global_State::loader_env;
+ CodeChunkInfo *cci = env->vm_methods->find(code_address);
assert(cci);
assert(cci->get_jit() == j);
assert(cci->get_method() == m);
@@ -499,14 +500,16 @@
Method_Iterator method_get_first_method_jit(JIT_Handle j)
{
- return vm_methods->get_first_method_jit((JIT *)j);
+ Global_Env *env = VM_Global_State::loader_env;
+ return env->vm_methods->get_first_method_jit((JIT *)j);
} //method_get_first_method_jit
Method_Iterator method_get_next_method_jit(Method_Iterator i)
{
- return vm_methods->get_next_method_jit((CodeChunkInfo *)i);
+ Global_Env *env = VM_Global_State::loader_env;
+ return env->vm_methods->get_next_method_jit((CodeChunkInfo *)i);
} //method_get_next_method_jit
@@ -2421,7 +2424,7 @@
const char *vm_get_property_value(const char *property_name)
{
assert(property_name);
- PropertiesHandle props = (PropertiesHandle)&VM_Global_State::loader_env->properties;
+ PropertiesHandle props = (PropertiesHandle)VM_Global_State::loader_env->properties;
const char *result = properties_get_string_property(props, property_name);
if (result == NULL)
result = "";
@@ -2431,7 +2434,7 @@
Boolean vm_get_property_value_boolean(const char *property_name, Boolean default_value)
{
assert(property_name);
- PropertiesHandle props = (PropertiesHandle)&VM_Global_State::loader_env->properties;
+ PropertiesHandle props = (PropertiesHandle)VM_Global_State::loader_env->properties;
const char *value = properties_get_string_property(props, property_name);
// fall back to provided default if the property is not set
@@ -2510,10 +2513,10 @@
// a branch long. Note that this function does not synchronize the I- or D-caches.
// Run through list of active threads and suspend the other ones.
- hythread_suspend_all(NULL, NULL);
+ hythread_suspend_all(NULL, NULL);
patch_code_with_threads_suspended(code_block, new_code, size);
- hythread_resume_all(NULL);
+ hythread_resume_all(NULL);
} //vm_patch_code_block
@@ -2678,7 +2681,7 @@
void vm_properties_set_value(const char* name, const char* value)
{
- PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties;
+ PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties;
properties_set_string_property(ph, name, value);
}
@@ -2686,13 +2689,13 @@
// All iterators created with this method call
// must be destroyed with vm_properties_iterator_destroy
PropertiesIteratorHandle vm_properties_iterator_create() {
- PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties;
+ PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties;
return properties_iterator_create(ph);
}
// Destroy iterator created by vm_properties_iterator_create
void vm_properties_iterator_destroy(PropertiesIteratorHandle props_iter) {
- PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties;
+ PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties;
properties_iterator_destroy(ph, props_iter);
}
Index: vmcore/src/class_support/classloader.cpp
===================================================================
--- vmcore/src/class_support/classloader.cpp (revision 454089)
+++ vmcore/src/class_support/classloader.cpp (working copy)
@@ -1354,7 +1354,7 @@
{
// get property value
const char *bcp_value = properties_get_string_property(
- reinterpret_cast(&m_env->properties), prop_string);
+ reinterpret_cast(m_env->properties), prop_string);
assert(bcp_value);
size_t len = strlen(bcp_value) + 1;
@@ -1534,7 +1534,7 @@
// get list of natives libraries
const char *lib_list =
properties_get_string_property(
- reinterpret_cast(&m_env->properties),
+ reinterpret_cast(m_env->properties),
"vm.other_natives_dlls" );
size_t len = strlen( lib_list ) + 1;
char *libraries = (char*)STD_ALLOCA( len );
@@ -1567,7 +1567,7 @@
* the kernel
*/
- PropertiesHandle hProps = reinterpret_cast(&m_env->properties);
+ PropertiesHandle hProps = reinterpret_cast(m_env->properties);
/* strdup so that it's freeable w/o extra logic */
@@ -1636,8 +1636,8 @@
* that needs it
*/
- add_pair_to_properties(m_env->properties, VM_BOOT_CLASS_PATH, bcp_value);
- add_pair_to_properties(m_env->properties, SUN_BOOT_CLASS_PATH, bcp_value);
+ add_pair_to_properties(*m_env->properties, VM_BOOT_CLASS_PATH, bcp_value);
+ add_pair_to_properties(*m_env->properties, SUN_BOOT_CLASS_PATH, bcp_value);
free(bcp_value);
Index: vmcore/src/class_support/Environment.cpp
===================================================================
--- vmcore/src/class_support/Environment.cpp (revision 454089)
+++ vmcore/src/class_support/Environment.cpp (working copy)
@@ -33,14 +33,27 @@
#include "native_overrides.h"
#include "compile.h"
-Global_Env::Global_Env(tl::MemoryPool & mp, Properties & prop):
-mem_pool(mp),
+
+Global_Env::Global_Env(apr_pool_t * pool):
+mem_pool(pool),
bootstrap_class_loader(NULL),
system_class_loader(NULL),
-properties(prop),
+properties(NULL),
+TI(NULL),
+nsoTable(NULL),
+portLib(NULL),
+dcList(NULL),
+assert_reg(NULL),
+vm_methods(NULL),
bootstrapping(false),
ready_for_exceptions(false)
{
+ // TODO: Use proper MM.
+ properties = new Properties();
+ bootstrap_class_loader = new BootstrapClassLoader(this);
+
+ hythread_lib_create(&hythread_lib);
+
JavaLangString_String = string_pool.lookup("java/lang/String");
JavaLangStringBuffer_String = string_pool.lookup("java/lang/StringBuffer");
JavaLangObject_String = string_pool.lookup("java/lang/Object");
@@ -117,6 +130,7 @@
JavaLangClass_Class = NULL;
java_lang_Throwable_Class = NULL;
java_lang_Error_Class = NULL;
+ java_lang_ThreadDeathError_Class = NULL;
java_lang_ExceptionInInitializerError_Class = NULL;
java_lang_NullPointerException_Class = NULL;
java_lang_StackOverflowError_Class = NULL;
@@ -141,22 +155,20 @@
JavaLangString_VTable = NULL;
JavaLangString_allocation_handle = 0;
+ uncaught_exception = NULL;
+
vm_class_offset = 0;
shutting_down = 0;
- TI = NULL;
- portLib = NULL;
+ TI = new DebugUtilsTI;
+ vm_methods = new Method_Lookup_Table;
+ nsoTable = nso_init_lookup_table(&string_pool);
- nsoTable = nso_init_lookup_table(&this->string_pool);
+} //Global_Env::Global_Env
- dcList = NULL;
-} //Global_Env::Global_Env
-
-void Global_Env::EnvClearInternals()
+Global_Env::~Global_Env()
{
- // No GC should work during iteration
- tmn_suspend_disable();
GlobalClassLoaderIterator ClIterator;
ClassLoader *cl = ClIterator.first();
@@ -166,18 +178,28 @@
delete cltmp;
}
ClassLoader::DeleteClassLoaderTable();
- tmn_suspend_enable();
- if (TI)
- delete TI;
+ delete TI;
+ TI = NULL;
+ delete vm_methods;
+ vm_methods = NULL;
+
+ delete properties;
+ properties = NULL;
+
+ delete bootstrap_class_loader;
+ bootstrap_class_loader = NULL;
+
nso_clear_lookup_table(nsoTable);
nsoTable = NULL;
compile_clear_dynamic_code_list(dcList);
dcList = NULL;
-}
+ hythread_lib_destroy(hythread_lib);
+ }
+
Class* Global_Env::LoadCoreClass(const String* s)
{
Class* clss =
Index: vmcore/src/class_support/method.cpp
===================================================================
--- vmcore/src/class_support/method.cpp (revision 454089)
+++ vmcore/src/class_support/method.cpp (working copy)
@@ -354,7 +354,8 @@
jit_info->_code_block_alignment = alignment;
unlock();
- vm_methods->add(jit_info); // Method table is thread safe
+ Global_Env *env = VM_Global_State::loader_env;
+ env->vm_methods->add(jit_info); // Method table is thread safe
return addr;
} // Method::allocate_code_block
Index: vmcore/src/class_support/method_lookup.cpp
===================================================================
--- vmcore/src/class_support/method_lookup.cpp (revision 454089)
+++ vmcore/src/class_support/method_lookup.cpp (working copy)
@@ -24,6 +24,7 @@
#define LOG_DOMAIN "vm.methods"
#include "cxxlog.h"
+#include "environment.h"
#include "platform.h"
#include
#include "lock_manager.h"
@@ -36,10 +37,6 @@
#define EIP_CACHE_SIZE 1024
#define EIP_ALIGNMENT 4
-
-Method_Lookup_Table *vm_methods = NULL;
-
-
Method_Lookup_Table::Method_Lookup_Table()
{
_next_free_entry = 0;
@@ -402,7 +399,8 @@
VM_Code_Type vm_identify_eip(void *addr)
{
- CodeChunkInfo *m = vm_methods->find(addr);
+ Global_Env *env = VM_Global_State::loader_env;
+ CodeChunkInfo *m = env->vm_methods->find(addr);
if (m == NULL) {
return VM_TYPE_UNKNOWN;
}
@@ -418,7 +416,8 @@
VM_Code_Type vm_identify_eip_deadlock_free(void *addr)
{
- CodeChunkInfo *m = vm_methods->find_deadlock_free(addr);
+ Global_Env *env = VM_Global_State::loader_env;
+ CodeChunkInfo *m = env->vm_methods->find_deadlock_free(addr);
if (m == NULL) {
return VM_TYPE_UNKNOWN;
}
Index: vmcore/src/class_support/Resolve.cpp
===================================================================
--- vmcore/src/class_support/Resolve.cpp (revision 454089)
+++ vmcore/src/class_support/Resolve.cpp (working copy)
@@ -1059,7 +1059,7 @@
/**
* Resolve whole constant pool
*/
-unsigned resolve_const_pool(Global_Env& env, Class *clss) {
+int resolve_const_pool(Global_Env& env, Class *clss) {
Const_Pool *cp = clss->const_pool;
// It's possible that cp is null when defining class on the fly
@@ -1071,5 +1071,5 @@
return i;
}
}
- return 0xFFFFFFFF;
+ return 0;
} //resolve_const_pool
Index: vmcore/src/class_support/String_Pool.cpp
===================================================================
--- vmcore/src/class_support/String_Pool.cpp (revision 454089)
+++ vmcore/src/class_support/String_Pool.cpp (working copy)
@@ -80,6 +80,7 @@
index_interned = (Interned_Strings_Index *)memory_pool.alloc(sizeof(Interned_Strings_Index));
+ string_pool_lock = 0;
#ifdef VM_STATS
string_stat = apr_hash_make(VM_Statistics::get_vm_stats().vm_stats_pool);
num_ambiguity = 0;
Index: vmcore/src/exception/exceptions.cpp
===================================================================
--- vmcore/src/exception/exceptions.cpp (revision 454089)
+++ vmcore/src/exception/exceptions.cpp (working copy)
@@ -373,7 +373,7 @@
inline void exn_java_print_stack_trace(FILE * UNREF f, jthrowable exc)
{
// finds java environment
- JNIEnv_Internal *jenv = jni_native_intf;
+ JNIEnv *jenv = jni_native_intf;
// finds class of Throwable
jclass throwableClazz = FindClass(jenv, VM_Global_State::loader_env->JavaLangThrowable_String);
@@ -389,7 +389,7 @@
{
assert(hythread_is_suspend_enabled());
// finds java environment
- JNIEnv_Internal *jenv = jni_native_intf;
+ JNIEnv *jenv = jni_native_intf;
// finds class of Throwable
jclass throwableClazz = FindClass(jenv, VM_Global_State::loader_env->JavaLangThrowable_String);
Index: vmcore/src/gc/dll_gc.cpp
===================================================================
--- vmcore/src/gc/dll_gc.cpp (revision 454089)
+++ vmcore/src/gc/dll_gc.cpp (working copy)
@@ -397,8 +397,7 @@
static void default_gc_add_compressed_root_set_entry(uint32 * UNREF ref)
{
- printf("Fatal GC error: compressed references are not supported\n");
- vm_exit(1);
+ DIE("Fatal GC error: compressed references are not supported\n");
} //default_gc_add_compressed_root_set_entry
@@ -406,8 +405,7 @@
static void default_gc_add_root_set_entry_managed_pointer(void ** UNREF slot,
Boolean UNREF is_pinned)
{
- printf("Fatal GC error: managed pointers are not supported\n");
- vm_exit(1);
+ DIE("Fatal GC error: managed pointers are not supported\n");
} //default_gc_add_root_set_entry_managed_pointer
Index: vmcore/src/gc/stop_the_world_root_set_enum.cpp
===================================================================
--- vmcore/src/gc/stop_the_world_root_set_enum.cpp (revision 454089)
+++ vmcore/src/gc/stop_the_world_root_set_enum.cpp (working copy)
@@ -53,12 +53,13 @@
static void
-vm_enumerate_the_current_thread()
+vm_enumerate_the_current_thread(VM_thread * vm_thread)
{
+ assert(p_TLS_vmthread == vm_thread);
// Process roots for the current thread
//assert(p_TLS_vmthread->gc_status == zero);
//p_TLS_vmthread->gc_status = gc_at_safepoint;
- vm_enumerate_thread(p_TLS_vmthread);
+ vm_enumerate_thread(vm_thread);
// Enumeration for this thread is complete.
//p_TLS_vmthread->gc_status = gc_enumeration_done;
@@ -79,14 +80,16 @@
static void
stop_the_world_root_set_enumeration()
{
+ VM_thread * current_vm_thread;
+
TRACE2("vm.gc", "stop_the_world_root_set_enumeration()");
// Run through list of active threads and suspend each one of them.
INFO2("threads","Start thread suspension ");
vm_time_start_hook(&_start_time); //thread suspension time measurement
-
- hythread_iterator_t iterator;
+
+ hythread_iterator_t iterator;
hythread_suspend_all(&iterator, NULL);
thread_suspend_time = vm_time_end_hook(&_start_time, &_end_time);
@@ -94,13 +97,13 @@
class_unloading_clear_mark_bits();
+ current_vm_thread = p_TLS_vmthread;
// Run through list of active threads and enumerate each one of them.
- hythread_t tm_thread = hythread_iterator_next(&iterator);
-
- //VM_thread *thread = get_vm_thread (hythread_iterator_next(&iterator));
- while(tm_thread) {
+ hythread_t tm_thread = hythread_iterator_next(&iterator);
+ while (tm_thread) {
VM_thread *thread = get_vm_thread(tm_thread);
- if (thread && thread != p_TLS_vmthread) {
+ //assert(thread);
+ if (thread && thread != current_vm_thread) {
vm_enumerate_thread(thread);
// Enumeration for this thread is complete.
//thread->gc_status = gc_enumeration_done;
@@ -110,7 +113,7 @@
tm_thread = hythread_iterator_next(&iterator);
}
- vm_enumerate_the_current_thread();
+ vm_enumerate_the_current_thread(current_vm_thread);
// finally, process all the global refs
vm_enumerate_root_set_global_refs();
Index: vmcore/src/init/parse_arguments.cpp
===================================================================
--- vmcore/src/init/parse_arguments.cpp (revision 454091)
+++ vmcore/src/init/parse_arguments.cpp (working copy)
@@ -19,27 +19,20 @@
* @version $Revision: 1.1.2.4.4.7 $
*/
-
-#define LOG_DOMAIN "vm.core"
-#include "cxxlog.h"
-
-#include
-#include
-#include "port_filepath.h"
-
#include
#include
#include
+#include
+#include
+#include "open/gc.h"
+#include "open/vm_util.h"
#include "Class.h"
#include "properties.h"
#include "environment.h"
#include "assertion_registry.h"
-
-#include "open/gc.h"
-
-#include "open/vm_util.h"
+#include "port_filepath.h"
#include "compile.h"
#include "vm_stats.h"
#include "nogc.h"
@@ -52,6 +45,9 @@
#include "dll_jit_intf.h"
#include "dll_gc.h"
+#define LOG_DOMAIN "vm.core"
+#include "cxxlog.h"
+
//------ Begin DYNOPT support --------------------------------------
//
#ifndef PLATFORM_POSIX // for DYNOPT in Win64
@@ -134,7 +130,7 @@
static inline Assertion_Registry* get_assert_reg(Global_Env *p_env) {
if (!p_env->assert_reg) {
- void * mem = p_env->mem_pool.alloc(sizeof(Assertion_Registry));
+ void * mem = apr_palloc(p_env->mem_pool, sizeof(Assertion_Registry));
p_env->assert_reg = new (mem) Assertion_Registry();
}
return p_env->assert_reg;
@@ -177,7 +173,7 @@
* This is the directory where the virtual machine artifacts are located
* (vm.dll, etc) including the kernel.jar GEIR
*/
- add_pair_to_properties(p_env->properties, "org.apache.harmony.vm.vmdir",
+ add_pair_to_properties(*p_env->properties, "org.apache.harmony.vm.vmdir",
option + strlen("-Dorg.apache.harmony.vm.vmdir="));
}
else if (begins_with(option, XBOOTCLASSPATH)) {
@@ -187,7 +183,7 @@
* processing and setting up "vm.boot.class.path" and "sun.boot.class.path"
* Note that in the case of multiple arguments, the last one will be used
*/
- add_pair_to_properties(p_env->properties, XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH));
+ add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH));
}
else if (begins_with(option, XBOOTCLASSPATH_A)) {
/*
@@ -196,7 +192,7 @@
* Note that we accumulate if multiple, appending each time
*/
- const char *bcp_old = properties_get_string_property((PropertiesHandle)&p_env->properties,
+ const char *bcp_old = properties_get_string_property((PropertiesHandle)p_env->properties,
XBOOTCLASSPATH_A);
const char *value = option + strlen(XBOOTCLASSPATH_A);
@@ -213,7 +209,7 @@
bcp_new = tmp;
}
- add_pair_to_properties(p_env->properties, XBOOTCLASSPATH_A, bcp_old ? bcp_new : value);
+ add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH_A, bcp_old ? bcp_new : value);
if (bcp_new) {
free(bcp_new);
@@ -226,7 +222,7 @@
* Note that we accumulate if multiple, prepending each time
*/
- const char *bcp_old = properties_get_string_property((PropertiesHandle)&p_env->properties,
+ const char *bcp_old = properties_get_string_property((PropertiesHandle)p_env->properties,
XBOOTCLASSPATH_P);
const char *value = option + strlen(XBOOTCLASSPATH_P);
@@ -243,7 +239,7 @@
bcp_new = tmp;
}
- add_pair_to_properties(p_env->properties, XBOOTCLASSPATH_P, bcp_old ? bcp_new : value);
+ add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH_P, bcp_old ? bcp_new : value);
if (bcp_new) {
free(bcp_new);
@@ -262,7 +258,7 @@
} else if (begins_with(option, "-Xjit:")) {
// Do nothing here, just skip this option for later parsing
} else if (strcmp(option, "-Xint") == 0) {
- add_pair_to_properties(p_env->properties, "vm.use_interpreter", "true");
+ add_pair_to_properties(*p_env->properties, "vm.use_interpreter", "true");
#ifdef VM_STATS
} else if (begins_with(option, "-Xstats:")) {
vm_print_total_stats = true;
@@ -286,12 +282,12 @@
char* prop_key = strdup(option + strlen("-X"));
prop_key[2] = '.';
TRACE2("init", prop_key << " = 1");
- add_pair_to_properties(p_env->properties, prop_key, "1");
+ add_pair_to_properties(*p_env->properties, prop_key, "1");
free(prop_key);
} else if (begins_with(option, "-Xem:")) {
const char* arg = option + strlen("-Xem:");
- add_pair_to_properties(p_env->properties, "em.properties", arg);
+ add_pair_to_properties(*p_env->properties, "em.properties", arg);
} else if (begins_with(option, "-Xms")) {
// cut -Xms
@@ -300,7 +296,7 @@
if (atoi(arg) == 0) {
ECHO("Negative or invalid heap size. Default value will be used!");
}
- add_pair_to_properties(p_env->properties, "gc.ms", arg);
+ add_pair_to_properties(*p_env->properties, "gc.ms", arg);
} else if (begins_with(option, "-Xmx")) {
// cut -Xmx
@@ -309,7 +305,7 @@
if (atoi(arg) == 0) {
ECHO("Negative or invalid heap size. Default value will be used!");
}
- add_pair_to_properties(p_env->properties, "gc.mx", arg);
+ add_pair_to_properties(*p_env->properties, "gc.mx", arg);
}
else if (begins_with(option, "-agentlib:")) {
p_env->TI->addAgent(option);
@@ -372,7 +368,7 @@
dump_file_name = arg;
}
else if (strcmp(option, "-XcleanupOnExit") == 0) {
- add_pair_to_properties(p_env->properties, "vm.cleanupOnExit", "true");
+ add_pair_to_properties(*p_env->properties, "vm.cleanupOnExit", "true");
}
else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) {
// Store a pointer to the portlib
@@ -554,73 +550,6 @@
} // for (arg_num)
} //set_log_levels_from_cmd
-struct cmd_arg
-{
- bool substring;
- char *param;
- int length;
- int args;
-};
-
-static const cmd_arg supported_parameters[] =
-{
- {false, "-classpath", strlen("-classpath"), 1},
- {false, "-cp", strlen("-cp"), 1},
- {true, "-Xbootclasspath:", strlen("-Xbootclasspath:"), 0},
- {true, "-Xbootclasspath/a:", strlen("-Xbootclasspath/a:"), 0},
- {true, "-Xbootclasspath/p:", strlen("-Xbootclasspath/p:"), 0},
- {false, "-?", strlen("-?"), 0},
- {false, "-help", strlen("-help"), 1},
- {true, "-Xjit", strlen("-Xjit"), 1},
- {false, "-Xint", strlen("-Xint"), 0},
-#ifdef VM_STATS
- {false, "-Xstats", strlen("-Xstats"), 1},
-#endif
- {false, "-version", strlen("-version"), 0},
- {false, "-showversion", strlen("-showversion"), 0},
- {false, "-fullversion", strlen("-fullversion"), 0},
- {true, "-ea", strlen("-ea"), 0},
- {true, "-enableassertions", strlen("-enableassertions"), 0},
- {true, "-da", strlen("-da"), 0},
- {true, "-disableassertions", strlen("-disableassertions"), 0},
- {false, "-dsa", strlen("-esa"), 0},
- {false, "-esa", strlen("-dsa"), 0},
- {false, "-enablesystemassertions", strlen("-enablesystemassertions"), 0},
- {false, "-disablesystemassertions", strlen("-disablesystemassertions"), 0},
- {false, "-Xgc", strlen("-Xgc"), 1},
- {true, "-Xem", strlen("-Xem"), 1},
- {true, "-Xms", strlen("-Xms"), 0},
- {true, "-Xmx", strlen("-Xmx"), 0},
- {true, "-agentlib:", strlen("-agentlib:"), 0},
- {true, "-agentpath:", strlen("-agentpath:"), 0},
- {false, "-Xdebug", strlen("-Xdebug"), 0},
- {false, "-Xverify", strlen("-Xverify"), 0},
- {false, "-verify", strlen("-verify"), 0},
- {false, "-Xnoagent", strlen("-Xnoagent"), 0},
- {true, "-Xrun", strlen("-Xrun"), 0},
- {true, "-verbose", strlen("-verbose"), 0},
- {true, "-Xverbose", strlen("-Xverbose"), 0},
- {true, "-Xverboseconf:", strlen("-Xverboseconf:"), 0},
- {true, "-Xverboselog:", strlen("-Xverboselog:"), 0},
- {true, "-Xfileline", strlen("-Xfileline"), 0},
- {true, "-Xthread", strlen("-Xthread"), 0},
- {true, "-Xcategory", strlen("-Xcategory"), 0},
- {true, "-Xtimestamp", strlen("-Xtimestamp"), 0},
- {true, "-Xwarn", strlen("-Xwarn"), 0},
- {true, "-Xfunction", strlen("-Xfunction"), 0},
-#ifdef _DEBUG
- {true, "-Xtrace", strlen("-Xtrace"), 0},
- {true, "-Xlog", strlen("-Xlog"), 0},
-#endif //_DEBUG
- {true, "-D", strlen("-D"), 0},
- {false, "-Xdumpstubs", strlen("-Xdumpstubs"), 0},
- {false, "-Xparallel_jit", strlen("-Xparallel_jit"), 0},
- {false, "-Xno_parallel_jit", strlen("-Xno_parallel_jit"), 0},
- {false, "-Xdumpfile", strlen("-Xdumpfile"), 1},
- {false, "-XcleanupOnExit", strlen("-XcleanupOnExit"), 0},
- {false, "-jar", strlen("-jar"), 0}
-}; //supported_parameters
-
static void print_help_on_nonstandard_options()
{
#ifdef _DEBUG
@@ -702,217 +631,6 @@
" Excplicitly free VM resources before exit\n");
} //print_help_on_nonstandard_options
-static JavaVMInitArgs* create_vm_arguments(int options_capacity)
-{
- JavaVMInitArgs* vm_arguments = (JavaVMInitArgs*) STD_MALLOC(sizeof(JavaVMInitArgs));
- assert(vm_arguments);
- vm_arguments->version = JNI_VERSION_1_4;
- vm_arguments->nOptions = 0;
- vm_arguments->ignoreUnrecognized = JNI_FALSE;
- vm_arguments->options =
- (JavaVMOption*)STD_MALLOC(sizeof(JavaVMOption) * (options_capacity));
- assert(vm_arguments->options);
-
- return vm_arguments;
-} //create_vm_arguments
-
-void clear_vm_arguments(JavaVMInitArgs* vm_args)
-{
- STD_FREE(vm_args->options);
- STD_FREE(vm_args);
-}
-
-static void vm_arguments_append_classpath(JavaVMInitArgs* vm_arguments, const char* jar_file)
-{
- static const char prefix[] = "-Djava.class.path=";
-
- // search for the last java.class.path property declaration
- for (int i = vm_arguments->nOptions - 1; i >= 0 ; i--)
- {
- const char* option = vm_arguments->options[i].optionString;
- if (strncmp(option, prefix, strlen(prefix)) == 0)
- {
- // if found, append jar file name
- char* new_option = (char*) STD_MALLOC(strlen(option) +
- strlen(PORT_PATH_SEPARATOR_STR) + strlen(jar_file) + 1);
- assert(new_option);
-
- strcpy(new_option, option);
- strcat(new_option, PORT_PATH_SEPARATOR_STR);
- strcat(new_option, jar_file);
-
- vm_arguments->options[i].optionString = new_option;
- return;
- }
- }
-
- // if not found, define java.class.path with jar file name
- char* option = (char*) STD_MALLOC(strlen(prefix) + strlen(jar_file) + 1);
- assert(option);
-
- strcpy(option, prefix);
- strcat(option, jar_file);
-
- vm_arguments->options[vm_arguments->nOptions].optionString = option;
- vm_arguments->nOptions ++;
- return;
-} //vm_arguments_append_classpath
-
-static int parse_vm_option(JavaVMInitArgs* vm_arguments, int argc, char *argv[], int i)
-{
- // return 0, if arguments are over
- if (i >= argc)
- return 0;
-
- // if '-jar' met, thean vm options are over
- if (strcmp(argv[i], "-jar") == 0)
- return 0;
-
- const cmd_arg* supported_parameter;
- bool found = false;
- for (unsigned j = 0; j < sizeof(supported_parameters) / sizeof(cmd_arg); j++)
- {
- supported_parameter = &(supported_parameters[j]);
- if ((supported_parameters[j].substring &&
- strncmp(argv[i], supported_parameters[j].param,
- supported_parameters[j].length) == 0) ||
- (!supported_parameters[j].substring &&
- strcmp(argv[i], supported_parameters[j].param) == 0))
- {
- found = true;
- break;
- }
- }
-
- if (found)
- {
- char* option;
-
- if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0)
- {
- if (i + 1 >= argc) {
- ECHO("Classpath option "
- << argv[i]
- << " should be followed by classpath value"
- USE_JAVA_HELP);
- LOGGER_EXIT(1);
- }
-
- char* class_path = argv[i + 1];
- static const char prefix[] = "-Djava.class.path=";
-
- option = (char*) STD_MALLOC(strlen(prefix) + strlen(class_path) + 1);
- assert(option);
-
- strcpy(option, prefix);
- strcat(option, class_path);
- }
- else if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-?") == 0)
- {
- if (i + 1 >= argc)
- {
- // out a generic help message
- print_generic_help();
- LOGGER_EXIT(0);
- }
-
- const char* arg = argv[i + 1];
- if (strcmp(arg, "jit") != 0 && !begins_with(arg, "prop"))
- {
- // out a generic help message
- print_generic_help();
- LOGGER_EXIT(0);
- }
-
- static const char prefix[] = "-Xhelp:";
-
- option = (char*) STD_MALLOC(strlen(prefix) + strlen(arg) + 1);
- assert(option);
-
- strcpy(option, prefix);
- strcat(option, arg);
-
- }
- else if (supported_parameter->args == 1)
- {
- if (i + 1 >= argc)
- {
- ECHO("Option " << argv[i] << " should be followed by a additional parameter");
- LOGGER_EXIT(1);
- }
-
- option = (char*) STD_MALLOC(strlen(argv[i]) + 1 + strlen(argv[i + 1]) + 1);
- assert(option);
-
- strcpy(option, argv[i]);
- strcat(option, ":");
- strcat(option, argv[i + 1]);
- }
- else
- {
- option = argv[i];
- }
-
- vm_arguments->options[vm_arguments->nOptions].optionString = option;
- vm_arguments->nOptions ++;
-
- return 1 + supported_parameter->args;
- }
-
- if (argv[i][0] != '-')
- return 0;
-
- if (strcmp(argv[i], "-X") == 0)
- {
- print_help_on_nonstandard_options();
- LOGGER_EXIT(0);
- } else {
- ECHO("Unknown option " << argv[i] << USE_JAVA_HELP);
- LOGGER_EXIT(1);
- }
-
-} //parse_vm_option
-
-JavaVMInitArgs* parse_cmd_arguments(int argc, char *argv[],
- char **p_class_name, char **p_jar_file, int *p_java_arg_num)
-{
- *p_class_name = NULL;
- *p_jar_file = NULL;
-
- JavaVMInitArgs* vm_arguments = create_vm_arguments(argc);
-
- int i = 1; // skip argv[0], since it is a program name
- int inc = 0;
- do
- {
- inc = parse_vm_option(vm_arguments, argc, argv, i);
- i += inc;
- } while (inc > 0);
-
- if (i < argc)
- {
- if (strcmp(argv[i], "-jar") == 0)
- {
- i++;
- if (i >= argc) {
- ECHO("Option -jar must be followed by a jar file name");
- LOGGER_EXIT(1);
- }
-
- *p_jar_file = argv[i];
- vm_arguments_append_classpath(vm_arguments, *p_jar_file);
- }
- else
- {
- *p_class_name = argv[i];
- }
- }
-
- *p_java_arg_num = argc - i - 1;
-
- return vm_arguments;
-} //parse_cmd_arguments
-
void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments)
{
p_env->vm_arguments.version = arguments->version;
Index: vmcore/src/init/properties.cpp
===================================================================
--- vmcore/src/init/properties.cpp (revision 454089)
+++ vmcore/src/init/properties.cpp (working copy)
@@ -390,12 +390,12 @@
*/
- define_undefined_predefined_properties(p_env->properties);
+ define_undefined_predefined_properties(*p_env->properties);
char **pp = predefined_propeties;
while (NULL != *pp)
{
- p_env->properties.add(*pp);
+ p_env->properties->add(*pp);
pp++;
}
@@ -443,7 +443,7 @@
if (strncmp(option, "-D", 2) == 0)
{
TRACE("setting property " << option + 2);
- add_to_properties(p_env->properties, option + 2);
+ add_to_properties(*p_env->properties, option + 2);
}
}
apr_pool_clear(prop_pool);
Index: vmcore/src/init/vm.cpp
===================================================================
--- vmcore/src/init/vm.cpp (revision 454089)
+++ vmcore/src/init/vm.cpp (working copy)
@@ -158,75 +158,7 @@
/////////////////////////////////////////////////////////////////
-//==============================================================================================================
-// VM_EXIT
-//==============================================================================================================
-
-// this is a prototype of Invocation API DestroyJavaVM function
-// It should be updated to wait for all user threads to complite.
-// Current VM calls it if -XcleanOpOnExit flag specified
-
-void DestroyVM() {
- TRACE("cleanup started");
- if (vm_methods != NULL) {
- vm_methods->unload_all();
- }
- vm_thread_shutdown(); //move up here
-
- VM_Global_State::loader_env->shutting_down += 1;
-
- vm_delete_all_jits();
- CmFreeComponent("em");
- CmRelease();
-
- ClassLoader::PrintUnloadingStats();
-
-#ifdef VM_STATS
- VM_Statistics::get_vm_stats().print();
-#endif //VM_STATS
-
- // Unloads all system native libraries
- natives_cleanup();
-
- VM_Global_State::loader_env->EnvClearInternals();
- gc_thread_kill(&p_TLS_vmthread->_gc_private_information);
- gc_wrapup();
- vm_mem_dealloc();
- vm_uninitialize_critical_sections();
-
- // FIXME: vm_methods should be moved to Global_Env - then
- // call ~Method_Lookup_Table() in EnvClearInternals()
- vm_methods->~Method_Lookup_Table();
-
-#ifdef DUMP_IPF_STUBS
- extern FILE *ipf_stubs_out_file;
- if (ipf_stubs_out_file) {
- fclose(ipf_stubs_out_file);
- }
-#endif //DUMP_IPF_STUBS
-}
-void vm_exit(int exit_code)
-{
- // Send VM_Death event and switch phase to VM_Death
- jvmti_send_vm_death_event();
- if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit"))
- jthread_cancel_all();
- /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME *
- * gregory - JVMTI shutdown should be part of DestroyVM after current VM shutdown *
- * problems are fixed *
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
- // call Agent_OnUnload() for agents and unload agents
- VM_Global_State::loader_env->TI->Shutdown();
-
- if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit"))
- {
- DestroyVM();
- LOGGER_EXIT(exit_code);
- }
- _exit(exit_code);
-} //vm_exit
-
static struct VmStandardProperty {
const char *name; // Full name of the property
const char *docString; // Documentation of the property
Index: vmcore/src/init/vm_init.cpp
===================================================================
--- vmcore/src/init/vm_init.cpp (revision 454089)
+++ vmcore/src/init/vm_init.cpp (working copy)
@@ -19,455 +19,818 @@
* @version $Revision: 1.1.2.4.4.3 $
*/
+#include
+#include
-#define LOG_DOMAIN "vm.core"
-#include "cxxlog.h"
+#include "open/gc.h"
+#include "open/thread_externals.h"
+#include "init.h"
#include "classloader.h"
#include "jni_utils.h"
#include "mon_enter_exit.h"
#include "heap.h"
+#include "port_filepath.h"
+#include "component_manager.h"
+#include "dll_gc.h"
+#include "compile.h"
+#include "interpreter.h"
+#include "em_intf.h"
+#include "dll_jit_intf.h"
+#include "jni_utils.h"
+#include "platform_lowlevel.h"
+#include "verify_stack_enumeration.h"
+#include "nogc.h"
+#include "vm_strings.h"
#ifdef PLATFORM_NT
// 20040427 Used to turn on heap checking on every allocation
#include
-#endif //PLATFORM_NT
+#endif
-bool vm_is_initialized = false;
+#define LOG_DOMAIN "vm.core.init"
+#include "cxxlog.h"
-void vm_initialize_critical_sections()
-{
+VTable * cached_object_array_vtable_ptr;
+bool parallel_jit = true;
+VMEXPORT bool dump_stubs = false;
+JNIEnv * jni_native_intf;
+
+void vm_initialize_critical_sections() {
p_jit_a_method_lock = new Lock_Manager();
p_vtable_patch_lock = new Lock_Manager();
p_meth_addr_table_lock = new Lock_Manager();
p_handle_lock = new Lock_Manager();
-
- // 20040224 Support for recording which methods (actually, CodeChunkInfo's) call which other methods.
p_method_call_lock = new Lock_Manager();
-} //vm_initialize_critical_sections
+}
-void vm_uninitialize_critical_sections()
-{
+void vm_uninitialize_critical_sections() {
delete p_jit_a_method_lock;
delete p_vtable_patch_lock;
delete p_meth_addr_table_lock;
delete p_handle_lock;
-
delete p_method_call_lock;
-} //vm_uninitialize_critical_sections
+}
-Class* preload_class(Global_Env* env, const char* classname)
-{
- String* s = env->string_pool.lookup(classname);
- return env->LoadCoreClass(s);
+Class * preload_class(Global_Env * vm_env, const char * classname) {
+ String * s = vm_env->string_pool.lookup(classname);
+ return vm_env->LoadCoreClass(s);
}
-Class* preload_class(Global_Env* env, String* s)
-{
- return env->LoadCoreClass(s);
+Class * preload_class(Global_Env * vm_env, String* s) {
+ return vm_env->LoadCoreClass(s);
}
-
-static Class* preload_primitive_class(Global_Env* env, const char* classname)
-{
- String *s = env->string_pool.lookup(classname);
- ClassLoader* cl = env->bootstrap_class_loader;
- Class *clss = cl->NewClass(env, s);
+static Class * preload_primitive_class(Global_Env * vm_env, const char * classname) {
+ String * s = vm_env->string_pool.lookup(classname);
+ ClassLoader * cl = vm_env->bootstrap_class_loader;
+ Class *clss = cl->NewClass(vm_env, s);
clss->is_primitive = 1;
clss->class_loader = cl;
clss->access_flags = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC;
clss->is_verified = 2;
cl->InsertClass(clss);
- class_prepare(env, clss);
+ class_prepare(vm_env, clss);
return clss;
-} //preload_primitive_class
+}
-
-
#ifdef LIB_DEPENDENT_OPTS
-static Class *class_initialize_by_name(const char *classname)
-{
+static Class * class_initialize_by_name(Global_Env * vm_env, const char * classname) {
ASSERT_RAISE_AREA;
- Global_Env* env = VM_Global_State::loader_env;
- String *s = env->string_pool.lookup(classname);
- Class *clss = env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, s);
- if(clss == NULL) {
- DIE("Couldn't load class " << classname);
- } else {
+ String *s = vm_env->string_pool.lookup(classname);
+ Class *clss = vm_env->bootstrap_class_loader->LoadVerifyAndPrepareClass(vm_env, s);
+ if (clss != NULL) {
class_initialize(clss);
}
return clss;
-} //class_initialize_by_name
+}
-
-
-void lib_dependent_opts()
-{
+static jint lib_dependent_opts() {
ASSERT_RAISE_AREA;
- class_initialize_by_name("java/lang/Math");
-} //lib_dependent_opts
+ return class_initialize_by_name("java/lang/Math") != null ? JNI_OK : JNI_ERR;
+}
+#endif
-#endif // LIB_DEPENDENT_OPTS
-
// Create the java_lang_Class instance for a struct Class
// and set its "vm_class" field to point back to that structure.
-void create_instance_for_class(Global_Env *env, Class *clss)
+void create_instance_for_class(Global_Env * vm_env, Class *clss)
{
- clss->class_loader->AllocateAndReportInstance(env, clss);
-} //create_instance_for_class
+ clss->class_loader->AllocateAndReportInstance(vm_env, clss);
+}
+/**
+ * Loads DLLs.
+ */
+static jint process_properties_dlls(Global_Env * vm_env) {
+ jint status;
+ char * tok;
+ const char * dlls;
+ const char delimiters[] = {PORT_PATH_SEPARATOR, 0};
-VTable *cached_object_array_vtable_ptr;
+ post_initialize_ee_dlls((PropertiesHandle)vm_env->properties);
+ const char* dll = properties_get_string_property((PropertiesHandle)vm_env->properties, "vm.em_dll");
+ TRACE("analyzing em dll " << dll);
-static void bootstrap_initial_java_classes(Global_Env *env)
+ status = CmLoadComponent(dll, "EmInitialize");
+ if (status != JNI_OK) {
+ WARN("Cannot load EM component from " << dll);
+ return status;
+ }
+
+ status = vm_env->cm->CreateInstance(&(vm_env->em_instance), "em");
+ if (status != JNI_OK) {
+ WARN("Cannot instantiate EM");
+ return status;
+ }
+
+ status = vm_env->em_instance->intf->GetInterface(
+ (OpenInterfaceHandle*) &(vm_env->em_interface), OPEN_INTF_EM_VM);
+ if (status != JNI_OK) {
+ WARN("Cannot get EM_VM interface");
+ return status;
+ }
+
+ dlls = properties_get_string_property((PropertiesHandle)vm_env->properties, "vm.dlls");
+ if (!dlls) return JNI_OK;
+
+ dlls = strdup(dlls);
+ assert(dlls);
+
+ tok = strtok((char *)dlls, delimiters);
+ while (tok) {
+ TRACE("analyzing dll " << tok);
+#ifndef USE_GC_STATIC
+ if (vm_is_a_gc_dll(tok)) {
+ vm_add_gc(tok);
+ goto next_dll;
+ }
+#endif
+
+#ifdef USE_DISEM
+ if (vm_is_a_disem_dll(tok)) {
+ vm_add_disem(tok);
+ goto next_dll;
+ }
+#endif
+ WARN("Mandatory library cannot be loaded: " << tok);
+ return JNI_ERR;
+next_dll:
+ tok = strtok(NULL, delimiters);
+ }
+ STD_FREE((void*)dlls);
+
+ return JNI_OK;
+}
+
+/**
+ * Checks whether current platform is supported or not.
+ */
+static jint check_platform() {
+#if defined(PLATFORM_NT)
+ OSVERSIONINFO osvi;
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ BOOL ok = GetVersionEx(&osvi);
+ if(!ok) {
+ DWORD e = GetLastError();
+ printf("Windows error: %d\n", e);
+ return JNI_ERR;
+ }
+ if((osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) || // NT 4.0
+ (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) || // Windows 2000
+ (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) || // Windows XP
+ (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)) { // Windows.NET
+ return JNI_OK;
+ }
+ printf("Windows %d.%d is not supported\n", osvi.dwMajorVersion, osvi.dwMinorVersion);
+ return JNI_ERR;
+#else
+ return JNI_OK;
+#endif
+}
+
+/**
+ * Ensures that different VM components have consistent compression modes.
+ */
+static jint check_compression() {
+ // Check for a mismatch between whether the various VM components all compress references or not.
+ Boolean vm_compression = vm_references_are_compressed();
+ Boolean gc_compression = gc_supports_compressed_references();
+ if (vm_compression) {
+ if (!gc_compression) {
+ WARN("VM component mismatch: the VM compresses references but the GC doesn't.");
+ return JNI_ERR;
+ }
+
+ // We actually check the first element in the jit_compilers array, as current JIT
+ // always returns FALSE to the supports_compressed_references() call.
+ JIT **jit = &jit_compilers[0];
+ if (!interpreter_enabled()) {
+ Boolean jit_compression = (*jit)->supports_compressed_references();
+ if (!jit_compression) {
+ WARN("VM component mismatch: the VM compresses references but a JIT doesn't");
+ return JNI_ERR;
+ }
+ }
+ } else {
+ if (gc_compression) {
+ WARN("VM component mismatch: the VM doesn't compress references but the GC does.");
+ return JNI_ERR;
+ }
+ JIT **jit = &jit_compilers[0];
+ if (!interpreter_enabled()) {
+ Boolean jit_compression = (*jit)->supports_compressed_references();
+ if (jit_compression) {
+ WARN("VM component mismatch: the VM doesn't compress references but a JIT does");
+ return JNI_ERR;
+ }
+ }
+ }
+ return JNI_OK;
+}
+
+/**
+ * Loads initial classes. For example j.l.Object, j.l.Class, etc.
+ */
+static void bootstrap_initial_java_classes(Global_Env * vm_env)
{
assert(hythread_is_suspend_enabled());
- TRACE2("init", "bootstrapping initial java classes");
-
+ TRACE("bootstrapping initial java classes");
+
+ vm_env->bootstrap_class_loader->Initialize();
+
/*
* Bootstrap java.lang.Class class. This requires also loading the other classes
* it inherits/implements: java.io.Serializable and java.lang.Object, and
* j.l.reflect.AnnotatedElement, GenericDeclaration and Type as per Java 5
*/
- env->StartVMBootstrap();
- env->JavaLangObject_Class = preload_class(env, env->JavaLangObject_String);
- env->java_io_Serializable_Class = preload_class(env, env->Serializable_String);
- env->JavaLangClass_Class = preload_class(env, env->JavaLangClass_String);
- env->FinishVMBootstrap();
+ vm_env->StartVMBootstrap();
+ vm_env->JavaLangObject_Class = preload_class(vm_env, vm_env->JavaLangObject_String);
+ vm_env->java_io_Serializable_Class = preload_class(vm_env, vm_env->Serializable_String);
+ vm_env->JavaLangClass_Class = preload_class(vm_env, vm_env->JavaLangClass_String);
+ vm_env->FinishVMBootstrap();
// Now create the java_lang_Class instance.
- create_instance_for_class(env, env->JavaLangClass_Class);
+ create_instance_for_class(vm_env, vm_env->JavaLangClass_Class);
- ClassTable* table = env->bootstrap_class_loader->GetLoadedClasses();
+ ClassTable* table = vm_env->bootstrap_class_loader->GetLoadedClasses();
unsigned num = 0;
for (ClassTable::const_iterator it = table->begin(), end = table->end();
it != end; ++it, ++num)
{
Class* booted = (*it).second;
- if (booted != env->JavaLangClass_Class) {
- create_instance_for_class(env, booted);
+ if (booted != vm_env->JavaLangClass_Class) {
+ create_instance_for_class(vm_env, booted);
}
- jvmti_send_class_load_event(env, booted);
+ jvmti_send_class_load_event(vm_env, booted);
jvmti_send_class_prepare_event(booted);
}
- #ifdef VM_STATS
- // Account for the classes loaded before env->JavaLangObject_Class is set.
- env->JavaLangObject_Class->num_allocations += num;
- env->JavaLangObject_Class->num_bytes_allocated += (num * env->JavaLangClass_Class->instance_data_size);
+#ifdef VM_STATS
+ // Account for the classes loaded before vm_env->JavaLangObject_Class is set.
+ vm_env->JavaLangObject_Class->num_allocations += num;
+ vm_env->JavaLangObject_Class->num_bytes_allocated += (num * vm_env->JavaLangClass_Class->instance_data_size);
#endif //VM_STATS
- TRACE2("init", "bootstrapping initial java classes complete");
-} // bootstrap_initial_java_classes
+ TRACE("bootstrapping initial java classes complete");
+}
-/** Calls java.lang.ClassLoader.getSystemClassLoader() to obtein system class loader object
- * and pass it to class_loader_set_system_class_loader(..) function
- * @return success status
+/**
+ * Loads hot classes.
*/
-static bool initialize_system_class_loader(JNIEnv* jenv)
-{
- jclass cl = jenv->FindClass("java/lang/ClassLoader");
+static jint preload_classes(Global_Env * vm_env) {
+ // Bootstrap initial classes
+ bootstrap_initial_java_classes(vm_env);
+
+ TRACE2("init", "preloading primitive type classes");
+ vm_env->Boolean_Class = preload_primitive_class(vm_env, "boolean");
+ vm_env->Char_Class = preload_primitive_class(vm_env, "char");
+ vm_env->Float_Class = preload_primitive_class(vm_env, "float");
+ vm_env->Double_Class = preload_primitive_class(vm_env, "double");
+ vm_env->Byte_Class = preload_primitive_class(vm_env, "byte");
+ vm_env->Short_Class = preload_primitive_class(vm_env, "short");
+ vm_env->Int_Class = preload_primitive_class(vm_env, "int");
+ vm_env->Long_Class = preload_primitive_class(vm_env, "long");
+
+ vm_env->Void_Class = preload_primitive_class(vm_env, "void");
+
+ vm_env->ArrayOfBoolean_Class = preload_class(vm_env, "[Z");
+ vm_env->ArrayOfByte_Class = preload_class(vm_env, "[B");
+ vm_env->ArrayOfChar_Class = preload_class(vm_env, "[C");
+ vm_env->ArrayOfShort_Class = preload_class(vm_env, "[S");
+ vm_env->ArrayOfInt_Class = preload_class(vm_env, "[I");
+ vm_env->ArrayOfLong_Class = preload_class(vm_env, "[J");
+ vm_env->ArrayOfFloat_Class = preload_class(vm_env, "[F");
+ vm_env->ArrayOfDouble_Class = preload_class(vm_env, "[D");
+
+#ifndef POINTER64
+ // In IA32, Arrays of Doubles need to be eight byte aligned to improve
+ // performance. In IPF all objects (arrays, class data structures, heap objects)
+ // get aligned on eight byte boundaries. So, this special code is not needed.
+ vm_env->ArrayOfDouble_Class->alignment = ((GC_OBJECT_ALIGNMENT < 8) ? 8: GC_OBJECT_ALIGNMENT);
+ // The alignment is either 4 or it is a multiple of 8. Things like 12 aren't allowed.
+ assert ((GC_OBJECT_ALIGNMENT == 4) || ((GC_OBJECT_ALIGNMENT % 8) == 0));
+ // align doubles on 8, clear alignment field and put in 8.
+ set_prop_alignment_mask(vm_env->ArrayOfDouble_Class, 8);
+ // Set high bit in size so that gc knows there are constraints
+#endif
+
+ TRACE2("init", "preloading string class");
+ vm_env->JavaLangString_Class = preload_class(vm_env, vm_env->JavaLangString_String);
+ vm_env->strings_are_compressed =
+ (class_lookup_field_recursive(vm_env->JavaLangString_Class, "bvalue", "[B") != NULL);
+ vm_env->JavaLangString_VTable = vm_env->JavaLangString_Class->vtable;
+ vm_env->JavaLangString_allocation_handle = vm_env->JavaLangString_Class->allocation_handle;
+
+ TRACE2("init", "preloading exceptions");
+ vm_env->java_lang_Throwable_Class =
+ preload_class(vm_env, vm_env->JavaLangThrowable_String);
+ vm_env->java_lang_StackTraceElement_Class =
+ preload_class(vm_env, "java/lang/StackTraceElement");
+ vm_env->java_lang_Error_Class =
+ preload_class(vm_env, "java/lang/Error");
+ vm_env->java_lang_ThreadDeathError_Class =
+ preload_class(vm_env, "java/lang/ThreadDeath");
+ vm_env->java_lang_ExceptionInInitializerError_Class =
+ preload_class(vm_env, "java/lang/ExceptionInInitializerError");
+ vm_env->java_lang_NoClassDefFoundError_Class =
+ preload_class(vm_env, "java/lang/NoClassDefFoundError");
+ vm_env->java_lang_ClassNotFoundException_Class =
+ preload_class(vm_env, "java/lang/ClassNotFoundException");
+ vm_env->java_lang_NullPointerException_Class =
+ preload_class(vm_env, vm_env->JavaLangNullPointerException_String);
+ vm_env->java_lang_StackOverflowError_Class =
+ preload_class(vm_env, "java/lang/StackOverflowError");
+ vm_env->java_lang_ArrayIndexOutOfBoundsException_Class =
+ preload_class(vm_env, vm_env->JavaLangArrayIndexOutOfBoundsException_String);
+ vm_env->java_lang_ArrayStoreException_Class =
+ preload_class(vm_env, "java/lang/ArrayStoreException");
+ vm_env->java_lang_ArithmeticException_Class =
+ preload_class(vm_env, "java/lang/ArithmeticException");
+ vm_env->java_lang_ClassCastException_Class =
+ preload_class(vm_env, "java/lang/ClassCastException");
+ vm_env->java_lang_OutOfMemoryError_Class =
+ preload_class(vm_env, "java/lang/OutOfMemoryError");
+
+ vm_env->java_lang_Cloneable_Class =
+ preload_class(vm_env, vm_env->Clonable_String);
+ vm_env->java_lang_Thread_Class =
+ preload_class(vm_env, "java/lang/Thread");
+ vm_env->java_lang_ThreadGroup_Class =
+ preload_class(vm_env, "java/lang/ThreadGroup");
+ vm_env->java_util_Date_Class =
+ preload_class(vm_env, "java/util/Date");
+ vm_env->java_util_Properties_Class =
+ preload_class(vm_env, "java/util/Properties");
+ vm_env->java_lang_Runtime_Class =
+ preload_class(vm_env, "java/lang/Runtime");
+
+ vm_env->java_lang_reflect_Constructor_Class =
+ preload_class(vm_env, vm_env->JavaLangReflectConstructor_String);
+ vm_env->java_lang_reflect_Field_Class =
+ preload_class(vm_env, vm_env->JavaLangReflectField_String);
+ vm_env->java_lang_reflect_Method_Class =
+ preload_class(vm_env, vm_env->JavaLangReflectMethod_String);
+
+ return JNI_OK;
+}
+
+/**
+ * Calls java.lang.ClassLoader.getSystemClassLoader() to obtain system
+ * class loader object.
+ * @return JNI_OK on success.
+ */
+static jint initialize_system_class_loader(JNIEnv * jni_env) {
+ Global_Env * vm_env = jni_get_vm_env(jni_env);
+ jclass cl = jni_env->FindClass("java/lang/ClassLoader");
if (! cl)
- return false;
+ return JNI_ERR;
- jmethodID gcl = jenv->GetStaticMethodID(cl, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
+ jmethodID gcl = jni_env->GetStaticMethodID(cl, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
if (! gcl)
- return false;
+ return JNI_ERR;
- jobject scl = jenv->CallStaticObjectMethod(cl, gcl);
- if (exn_raised())
- return false;
+ jobject scl = jni_env->CallStaticObjectMethod(cl, gcl);
+ if (! scl)
+ return JNI_ERR;
- if(scl) {
- tmn_suspend_disable();
- class_loader_set_system_class_loader(ClassLoader::LookupLoader(((ObjectHandle)scl)->object));
- tmn_suspend_enable();
+ hythread_suspend_disable();
+ vm_env->system_class_loader = (UserDefinedClassLoader *)
+ ClassLoader::LookupLoader(((ObjectHandle)scl)->object);
+ hythread_suspend_enable();
+
+ return JNI_OK;
+}
+
+#define PROCESS_EXCEPTION(message) \
+{ \
+ ECHO("Internal error: " << message); \
+\
+ if (jni_env->ExceptionCheck()== JNI_TRUE) \
+ { \
+ jni_env->ExceptionDescribe(); \
+ jni_env->ExceptionClear(); \
+ } \
+\
+ return JNI_ERR; \
+} \
+
+/**
+ * Executes j.l.VMStart.initialize() method.
+ */
+static jint run_java_init(JNIEnv * jni_env) {
+ assert(hythread_is_suspend_enabled());
+
+ jclass start_class = jni_env->FindClass("java/lang/VMStart");
+ if (jni_env->ExceptionCheck()== JNI_TRUE || start_class == NULL) {
+ PROCESS_EXCEPTION("can't find starter class: java.lang.VMStart.");
}
- return true;
-} //initialize_system_class_loader
+ jmethodID init_method = jni_env->GetStaticMethodID(start_class, "initialize", "()V");
+ if (jni_env->ExceptionCheck()== JNI_TRUE || init_method == NULL) {
+ PROCESS_EXCEPTION("can't find java.lang.VMStart.initialize() method.");
+ }
-static bool init_thread_object(JNIEnv *);
+ jni_env->CallStaticVoidMethod(start_class, init_method);
+ if (jni_env->ExceptionCheck()== JNI_TRUE) {
+ PROCESS_EXCEPTION("java.lang.VMStart.initialize() method completed with an exception.");
+ }
+ return JNI_OK;
+}
-bool vm_init(Global_Env *env)
-{
- ASSERT_RAISE_AREA;
+/**
+ * Creates new j.l.Thread object
+ *
+ * @param[out] thread_object pointer to created thread object
+ * @param[in] jni_env JNI environment assocciated with the current thread
+ * @param[in] group thread group where new thread should be placed in
+ * @param[in] name thread's name
+ * @param[in] daemon JNI_TRUE if new thread is a daemon, JNI_FALSE overwise
+ */
+static jint vm_create_jthread(jthread * thread_object, JNIEnv * jni_env, jobject group, char * name, jboolean daemon) {
+ static Method * constructor = NULL;
+ const char * descriptor = "(Ljava/lang/ThreadGroup;Ljava/lang/String;JJIZ)V";
+ jvalue args[7];
+ Global_Env * vm_env;
+ Class * thread_class;
+ ObjectHandle thread_handle;
+ hythread_t native_thread;
- if(vm_is_initialized)
- return false;
+
+ assert(!hythread_is_suspend_enabled());
+
+ vm_env = jni_get_vm_env(jni_env);
+
+ thread_class = vm_env->java_lang_Thread_Class;
+ class_initialize(thread_class);
+ if (exn_raised()) return TM_ERROR_INTERNAL;
+
+ // Allocate new j.l.Thread object.
+ thread_handle = oh_allocate_global_handle();
+ thread_handle->object = class_alloc_new_object(thread_class);
+ if (thread_handle->object == NULL) {
+ assert(exn_get() == vm_env->java_lang_OutOfMemoryError);
+ return JNI_ENOMEM;
+ }
+ *thread_object = thread_handle;
+
+ if (constructor == NULL) {
+ // Initialize created thread object.
+ constructor = class_lookup_method_init(thread_class, descriptor);
+ if (constructor == NULL) {
+ TRACE("Failed to find thread's constructor " << descriptor << " , exception = " << exn_get());
+ return JNI_ERR;
+ }
+ }
+
+ args[0].l = thread_handle;
+ args[1].l = group;
+
+ if (name) {
+ args[2].l = oh_allocate_local_handle();
+ args[2].l->object = string_create_from_utf8(name, strlen(name));
+ } else {
+ args[2].l = NULL;
+ }
+ native_thread = hythread_self();
+ args[3].j = (POINTER_SIZE_INT) native_thread;
+ args[4].j = 0;
+ args[5].i = hythread_get_priority(native_thread);
+ args[6].z = daemon;
+
+ vm_execute_java_method_array((jmethodID) constructor, 0, args);
+ if (exn_raised()) {
+ TRACE("Failed to initialize new thread object, exception = " << exn_get_name());
+ return JNI_ERR;
+ }
+ return JNI_OK;
+}
+
+/**
+ * Attaches current thread to VM and creates j.l.Thread instance.
+ *
+ * @param[out] p_jni_env points to created JNI environment
+ * @param[out] java_thread global reference holding j.l.Thread object
+ * @param[in] java_vm VM to attach thread to
+ * @param[in] group thread group for attaching thread
+ * @param[in] name thread name
+ * @param[in] daemon JNI_TRUE if thread is daemon, JNI_FALSE overwise
+ * @return JNI_OK on success.
+ */
+jint vm_attach_internal(JNIEnv ** p_jni_env, jthread * java_thread, JavaVM * java_vm, jobject group, char * name, jboolean daemon) {
+ JNIEnv * jni_env;
+ hythread_t native_thread;
+ jint status;
+
+ native_thread = hythread_self();
+ if (!native_thread) {
+ status = hythread_attach_to_group(&native_thread,
+ ((JavaVM_Internal *)java_vm)->vm_env->hythread_lib, NULL);
+ if (status != TM_ERROR_NONE) return JNI_ERR;
+ }
+ assert(native_thread);
+
+ status = vm_attach(java_vm, &jni_env);
+ if (status != JNI_OK) return status;
+
+ *p_jni_env = jni_env;
+
+ hythread_suspend_disable();
+ // Global reference will be created for new thread object.
+ status = vm_create_jthread(java_thread, jni_env, group, name, daemon);
+ hythread_suspend_enable();
+
+ return status;
+}
+
+/**
+ * First VM initialization step. At that moment neither JNI is available
+ * nor main thread is attached to VM.
+ */
+int vm_init1(JavaVM_Internal * java_vm, JavaVMInitArgs * vm_arguments) {
+ jint status;
+ Global_Env * vm_env;
+ JNIEnv * jni_env;
+
+ TRACE("Initializing VM");
+
+ vm_env = java_vm->vm_env;
+
+ if (hythread_attach_ex(NULL, vm_env->hythread_lib) != TM_ERROR_NONE) {
+ return JNI_ERR;
+ }
+
assert(hythread_is_suspend_enabled());
- vm_is_initialized = true;
- TRACE2("init","Initializing VM");
+ status = check_platform();
+ if (status != JNI_OK) return status;
+ // TODO: global variables should be removed for multi-VM support
+ VM_Global_State::loader_env = vm_env;
+
+ // Initialize arguments
+ initialize_vm_cmd_state(vm_env, vm_arguments);
+
+ // Initialize logging system as soon as possible.
+ init_log_system();
+ set_log_levels_from_cmd(&vm_env->vm_arguments);
+
+ vm_initialize_critical_sections();
vm_monitor_init();
- env->bootstrap_class_loader = new BootstrapClassLoader(env); // !!! use proper MM
- env->bootstrap_class_loader->Initialize();
+ status = CmAcquire(&vm_env->cm);
+ if (status != JNI_OK) {
+ WARN("Faild to initialize a \"Component Manager\".");
+ return status;
+ }
-/////////////// Start bootstrap of initial classes ////////////////
+ /* BEGIN: Property processing. */
- bootstrap_initial_java_classes(env);
+ // 20030407 Note: property initialization must follow initialization of the default JITs to allow
+ // the command line to override those default JITs.
-/////////////// End bootstrap of initial classes ////////////////
+ initialize_properties(vm_env, *vm_env->properties);
- TRACE2("init", "preloading primitive type classes");
- env->Boolean_Class = preload_primitive_class(env, "boolean");
- env->Char_Class = preload_primitive_class(env, "char");
- env->Float_Class = preload_primitive_class(env, "float");
- env->Double_Class = preload_primitive_class(env, "double");
- env->Byte_Class = preload_primitive_class(env, "byte");
- env->Short_Class = preload_primitive_class(env, "short");
- env->Int_Class = preload_primitive_class(env, "int");
- env->Long_Class = preload_primitive_class(env, "long");
+ parse_vm_arguments(vm_env);
- env->Void_Class = preload_primitive_class(env, "void");
+ status = process_properties_dlls(vm_env);
+ if (status != JNI_OK) return status;
+
+ parse_jit_arguments(&vm_env->vm_arguments);
- env->ArrayOfBoolean_Class = preload_class(env, "[Z");
- env->ArrayOfByte_Class = preload_class(env, "[B");
- env->ArrayOfChar_Class = preload_class(env, "[C");
- env->ArrayOfShort_Class = preload_class(env, "[S");
- env->ArrayOfInt_Class = preload_class(env, "[I");
- env->ArrayOfLong_Class = preload_class(env, "[J");
- env->ArrayOfFloat_Class = preload_class(env, "[F");
- env->ArrayOfDouble_Class = preload_class(env, "[D");
+ vm_env->pin_interned_strings =
+ (bool)vm_get_property_value_boolean("vm.pin_interned_strings", FALSE);
-#ifndef POINTER64
- // In IA32, Arrays of Doubles need to be eight byte aligned to improve
- // performance. In IPF all objects (arrays, class data structures, heap objects)
- // get aligned on eight byte boundaries. So, this special code is not needed.
- env->ArrayOfDouble_Class->alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT);
- // The alignment is either 4 or it is a multiple of 8. Things like 12 aren't allowed.
- assert ((GC_OBJECT_ALIGNMENT==4) || ((GC_OBJECT_ALIGNMENT % 8) == 0));
- // align doubles on 8, clear alignment field and put in 8.
- set_prop_alignment_mask (env->ArrayOfDouble_Class, 8);
- // Set high bit in size so that gc knows there are constraints
-#endif // POINTER64
+ if (!vm_get_boolean_property_value_with_default("vm.assert_dialog")) {
+ TRACE("disabling assertion dialogs");
+ disable_assert_dialogs();
+ }
- TRACE2("init", "preloading string class");
- env->JavaLangString_Class = preload_class(env, env->JavaLangString_String);
- env->strings_are_compressed =
- (class_lookup_field_recursive(env->JavaLangString_Class, "bvalue", "[B") != NULL);
- env->JavaLangString_VTable = env->JavaLangString_Class->vtable;
- env->JavaLangString_allocation_handle = env->JavaLangString_Class->allocation_handle;
+ initialize_verify_stack_enumeration();
- TRACE2("init", "preloading exceptions");
- env->java_lang_Throwable_Class =
- preload_class(env, env->JavaLangThrowable_String);
- env->java_lang_StackTraceElement_Class =
- preload_class(env, "java/lang/StackTraceElement");
- env->java_lang_Error_Class =
- preload_class(env, "java/lang/Error");
- env->java_lang_ExceptionInInitializerError_Class =
- preload_class(env, "java/lang/ExceptionInInitializerError");
- env->java_lang_NoClassDefFoundError_Class =
- preload_class(env, "java/lang/NoClassDefFoundError");
- env->java_lang_ClassNotFoundException_Class =
- preload_class(env, "java/lang/ClassNotFoundException");
- env->java_lang_NullPointerException_Class =
- preload_class(env, env->JavaLangNullPointerException_String);
- env->java_lang_StackOverflowError_Class =
- preload_class(env, "java/lang/StackOverflowError");
- env->java_lang_ArrayIndexOutOfBoundsException_Class =
- preload_class(env, env->JavaLangArrayIndexOutOfBoundsException_String);
- env->java_lang_ArrayStoreException_Class =
- preload_class(env, "java/lang/ArrayStoreException");
- env->java_lang_ArithmeticException_Class =
- preload_class(env, "java/lang/ArithmeticException");
- env->java_lang_ClassCastException_Class =
- preload_class(env, "java/lang/ClassCastException");
- env->java_lang_OutOfMemoryError_Class =
- preload_class(env, "java/lang/OutOfMemoryError");
+ /* END: Property processing. */
- env->java_lang_OutOfMemoryError = oh_allocate_global_handle();
- env->popFrameException = oh_allocate_global_handle();
+ // Initialize memory allocation.
+ vm_init_mem_alloc();
+ gc_init();
- tmn_suspend_disable();
- // precompile StackOverflowError
- class_alloc_new_object_and_run_default_constructor(env->java_lang_StackOverflowError_Class);
- env->java_lang_OutOfMemoryError->object =
- class_alloc_new_object(env->java_lang_OutOfMemoryError_Class);
- env->popFrameException->object =
- class_alloc_new_object(env->java_lang_Error_Class);
- tmn_suspend_enable();
+ // TODO: find another way to initialize the following.
+ Class::heap_base = (Byte *)gc_heap_base_address();
+ Class::heap_end = (Byte *)gc_heap_ceiling_address();
+ Class::managed_null = (vm_references_are_compressed() ? Class::heap_base : NULL);
- env->java_lang_Cloneable_Class =
- preload_class(env, env->Clonable_String);
- env->java_lang_Thread_Class =
- preload_class(env, "java/lang/Thread");
- env->java_lang_ThreadGroup_Class =
- preload_class(env, "java/lang/ThreadGroup");
- env->java_util_Date_Class =
- preload_class(env, "java/util/Date");
- env->java_util_Properties_Class =
- preload_class(env, "java/util/Properties");
- env->java_lang_Runtime_Class =
- preload_class(env, "java/lang/Runtime");
+ // 20030404 This handshaking protocol isn't quite correct. It doesn't
+ // work at the moment because JIT has not yet been modified to support
+ // compressed references, so it never answers "true" to supports_compressed_references().
+ status = check_compression();
+ if (status != JNI_OK) return status;
- env->java_lang_reflect_Constructor_Class =
- preload_class(env, env->JavaLangReflectConstructor_String);
- env->java_lang_reflect_Field_Class =
- preload_class(env, env->JavaLangReflectField_String);
- env->java_lang_reflect_Method_Class =
- preload_class(env, env->JavaLangReflectMethod_String);
+ // Prepares to load natives
+ status = natives_init();
+ if (status != JNI_OK) return status;
- Method *m = class_lookup_method(env->java_lang_Throwable_Class,
- env->Init_String, env->VoidVoidDescriptor_String);
+ // "Tool Interface" initialization
+ status = vm_env->TI->Init();
+ if (status != JNI_OK) {
+ WARN("Failed to initialize JVMTI.");
+ return status;
+ }
+
+ // Enable interpreter by default if TI should be enabled.
+ vm_env->TI->setExecutionMode(vm_env);
+
+ extern void initialize_signals();
+ initialize_signals();
+
+ status = vm_attach(java_vm, &jni_env);
+ if (status != JNI_OK) return status;
+
+ // TODO: jni_native_intf should be removed from global namespace
+ jni_native_intf = jni_env;
+
+ status = preload_classes(vm_env);
+ if (status != JNI_OK) return status;
+
+ // Now the thread is attached to VM and it is valid to disable it.
+ hythread_suspend_disable();
+
+ // Create OutOfMemoryError.
+ vm_env->java_lang_OutOfMemoryError = oh_allocate_global_handle();
+ vm_env->java_lang_OutOfMemoryError->object =
+ class_alloc_new_object(vm_env->java_lang_OutOfMemoryError_Class);
+
+ // Create pop frame exception.
+ vm_env->popFrameException = oh_allocate_global_handle();
+ vm_env->popFrameException->object =
+ class_alloc_new_object(vm_env->java_lang_Error_Class);
+
+
+ // Precompile StackOverflowError.
+ class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_StackOverflowError_Class);
+ // Precompile ThreadDeathError.
+ class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeathError_Class);
+
+ hythread_suspend_enable();
+
+ // Mark j.l.Throwable() constructor as a side effects free.
+ Method * m = class_lookup_method(vm_env->java_lang_Throwable_Class,
+ vm_env->Init_String, vm_env->VoidVoidDescriptor_String);
assert(m);
- assert(hythread_is_suspend_enabled());
m->set_side_effects(MSE_False);
- m = class_lookup_method(env->java_lang_Throwable_Class,
- env->Init_String, env->FromStringConstructorDescriptor_String);
+ // Mark j.l.Throwable(j.l.String) constructor as a side effects free.
+ m = class_lookup_method(vm_env->java_lang_Throwable_Class,
+ vm_env->Init_String, vm_env->FromStringConstructorDescriptor_String);
assert(m);
m->set_side_effects(MSE_False);
+ void global_object_handles_init(JNIEnv *);
+ global_object_handles_init(jni_env);
- void global_object_handles_init();
- global_object_handles_init();
- Class *aoObjectArray = preload_class(env, "[Ljava/lang/Object;");
+ Class * aoObjectArray = preload_class(vm_env, "[Ljava/lang/Object;");
cached_object_array_vtable_ptr = aoObjectArray->vtable;
// the following is required for creating exceptions
- preload_class(env, "[Ljava/lang/VMClassRegistry;");
- extern unsigned resolve_const_pool(Global_Env& env, Class *clss);
- unsigned fail_idx = resolve_const_pool(*env, env->java_lang_Throwable_Class);
- if(fail_idx != 0xFFFFFFFF)
- {
+ preload_class(vm_env, "[Ljava/lang/VMClassRegistry;");
+ extern int resolve_const_pool(Global_Env& env, Class *clss);
+ status = resolve_const_pool(*vm_env, vm_env->java_lang_Throwable_Class);
+ if(status != 0) {
WARN("Failed to resolve class java/lang/Throwable");
- return false;
+ return JNI_ERR;
}
// We assume, that at this point VM supports exception objects creation.
- env->ReadyForExceptions();
+ vm_env->ReadyForExceptions();
- TRACE2("init", "initializing thread group");
+ return JNI_OK;
+}
+
+/**
+ * Second VM initialization stage. At that moment JNI services are available
+ * and main thread has been already attached to VM.
+ */
+jint vm_init2(JNIEnv * jni_env) {
+ jint status;
+ Global_Env * vm_env;
+
assert(hythread_is_suspend_enabled());
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
- if (! init_thread_object(jni_env))
- return false;
+ vm_env = jni_get_vm_env(jni_env);
- TRACE2("init", "Invoking the java.lang.Class constructor");
- Class *jlc = env->JavaLangClass_Class;
+ TRACE("Invoking the java.lang.Class constructor");
+ Class * jlc = vm_env->JavaLangClass_Class;
jobject jlo = struct_Class_to_java_lang_Class_Handle(jlc);
jmethodID java_lang_class_init = GetMethodID(jni_env, jlo, "", "()V");
jvalue args[1];
args[0].l = jlo;
- tmn_suspend_disable();
+
+ hythread_suspend_disable();
+
vm_execute_java_method_array(java_lang_class_init, 0, args);
-
assert(!exn_raised());
- void unsafe_global_object_handles_init();
- unsafe_global_object_handles_init();
+ void unsafe_global_object_handles_init(JNIEnv *);
+ unsafe_global_object_handles_init(jni_env);
- tmn_suspend_enable();
+ hythread_suspend_enable();
if (vm_get_boolean_property_value_with_default("vm.finalize")) {
- // load and initialize finalizer thread
- env->finalizer_thread = preload_class(env, "java/lang/FinalizerThread");
- assert(env->finalizer_thread);
+ // Load and initialize finalizer thread.
+ vm_env->finalizer_thread = preload_class(vm_env, "java/lang/FinalizerThread");
+ assert(vm_env->finalizer_thread);
- Field* finalizer_shutdown_field = class_lookup_field_recursive(env->finalizer_thread,
- "shutdown", "Z");
- Field* finalizer_on_exit_field = class_lookup_field_recursive(env->finalizer_thread,
- "onExit", "Z");
+ Field * finalizer_shutdown_field =
+ class_lookup_field_recursive(vm_env->finalizer_thread, "shutdown", "Z");
+ Field* finalizer_on_exit_field =
+ class_lookup_field_recursive(vm_env->finalizer_thread, "onExit", "Z");
assert(finalizer_shutdown_field);
assert(finalizer_on_exit_field);
- env->finalizer_shutdown = (jboolean*) finalizer_shutdown_field->get_address();
- env->finalizer_on_exit = (jboolean*) finalizer_on_exit_field->get_address();
- assert(env->finalizer_shutdown);
- assert(env->finalizer_on_exit);
- class_initialize_from_jni(env->finalizer_thread);
+ vm_env->finalizer_shutdown = (jboolean*) finalizer_shutdown_field->get_address();
+ vm_env->finalizer_on_exit = (jboolean*) finalizer_on_exit_field->get_address();
+ assert(vm_env->finalizer_shutdown);
+ assert(vm_env->finalizer_on_exit);
+ class_initialize_from_jni(vm_env->finalizer_thread);
} else {
- env->finalizer_thread = NULL;
+ vm_env->finalizer_thread = NULL;
}
- TRACE2("init", "initialization of system classes completed");
+ TRACE("initialization of system classes completed");
#ifdef WIN32
// Code to start up Networking on Win32
WORD wVersionRequested;
WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
-
- if ( err != 0 ) {
+ int err;
+ wVersionRequested = MAKEWORD(2, 2);
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
// Tell the user that we could not find a usable WinSock DLL.
WARN("Couldn't startup Winsock 2.0 dll ");
}
-#endif // WIN32
+#endif
#ifdef LIB_DEPENDENT_OPTS
lib_dependent_opts();
#endif
TRACE2("init", "initializing system class loader");
- //XXX NativeObjectHandles lhs;
- bool res = initialize_system_class_loader(jni_env);
- if(!res) {
- WARN("Fail to initialize system class loader.");
- }
- if(exn_raised()) {
- print_uncaught_exception_message(stderr,
+ status = initialize_system_class_loader(jni_env);
+ if (status != JNI_OK) {
+ WARN("Failed to initialize system class loader.");
+ if(exn_raised()) {
+ print_uncaught_exception_message(stderr,
"system class loader initialisation", exn_get());
+ }
+ return status;
}
- exn_clear(); // Ignore any exception that might have occured
- TRACE2("init", "system class loader initialized");
- jvmti_send_vm_start_event(env, jni_env);
+ TRACE("system class loader initialized");
+ status = run_java_init(jni_env);
+ if (status != JNI_OK) return status;
+
+ TRACE("VM initialization completed");
assert(!exn_raised());
- TRACE2("init", "VM initialization completed");
- return true;
-} //vm_init
+ return JNI_OK;
+}
-static bool init_thread_object(JNIEnv *jenv)
-{
- Global_Env *env = VM_Global_State::loader_env;
-
- assert(hythread_is_suspend_enabled());
-
- // Load, prepare and initialize the "Thread class"
- String *ss = env->string_pool.lookup("java/lang/VMStart");
- Class *thread_clss = env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, ss);
- assert(thread_clss);
- assert(hythread_is_suspend_enabled());
- tmn_suspend_disable();
- class_initialize(thread_clss);
- assert(!hythread_is_suspend_enabled());
-
- ObjectHandle jThreadClass = oh_allocate_local_handle();
- jThreadClass->object = struct_Class_to_java_lang_Class(thread_clss);
- tmn_suspend_enable();
-
- jmethodID main_method = jenv->GetStaticMethodID(jThreadClass, "mainThreadInit", "()V");
- if (ExceptionOccurred(jenv) || !main_method) {
- WARN("*** Error: exception occured in main Thread constructor.");
- ExceptionDescribe(jenv);
- ExceptionClear(jenv);
- return false;
- }
-
- jenv->CallStaticVoidMethod(jThreadClass, main_method);
-
- if (ExceptionOccurred(jenv)) {
- WARN("*** Error: exception occured in main Thread constructor.");
- ExceptionDescribe(jenv);
- ExceptionClear(jenv);
- return false;
- }
-
- return true;
-} //init_thread_object
+JIT_Handle vm_load_jit(const char* file_name, apr_dso_handle_t** handle) {
+ //if (vm_is_a_jit_dll(file_name)) {
+ Dll_JIT* jit = new Dll_JIT(file_name);
+ handle[0]=jit->get_lib_handle();
+ vm_add_jit(jit);
+ return (JIT_Handle)jit;
+
+ //}
+ //printf("not a jit\n");
+ //handle[0]=NULL;
+ //return 0;
+}
Index: vmcore/src/init/vm_main.cpp
===================================================================
--- vmcore/src/init/vm_main.cpp (revision 454089)
+++ vmcore/src/init/vm_main.cpp (working copy)
@@ -1,643 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- * @author Intel, Alexei Fedotov
- * @version $Revision: 1.1.2.5.4.3 $
- */
-
-#define LOG_DOMAIN "vm.core"
-#include "cxxlog.h"
-
-#include "thread_generic.h"
-#include "open/vm_util.h"
-#include "open/hythread_ext.h"
-#include "properties.h"
-#include
-#include "vm_synch.h"
-#include "init.h"
-#include "compile.h"
-#include "method_lookup.h"
-#include "nogc.h"
-#include "classloader.h"
-#include "thread_dump.h"
-#include "interpreter.h"
-#include "verify_stack_enumeration.h"
-
-// Multiple-JIT support.
-#include "component_manager.h"
-#include "jit_intf.h"
-#include "dll_jit_intf.h"
-#include "dll_gc.h"
-#include "em_intf.h"
-#include "port_filepath.h"
-
-union Scalar_Arg {
- int i;
- unsigned u;
- void *p;
-};
-
-#include "m2n.h"
-// FIXME Alexei
-// There should be no need to expose internal m2n strucutre here
-#ifdef _IPF_
-#include "../m2n_ipf_internal.h"
-#elif defined _EM64T_
-#include "../m2n_em64t_internal.h"
-#else
-#include "../m2n_ia32_internal.h"
-#endif
-
-static StaticInitializer vm_initializer;
-
-/*
- * The VM's global environment. Extern declared in init.h
- * @TODO - make this per-VM
- */
-tl::MemoryPool m;
-Properties properties;
-Global_Env env(m, properties);
-
-#include "jarfile_util.h"
-bool runjarfile = false;
-
-VMEXPORT bool instrumenting = false;
-
-VMEXPORT bool vtune_support = false;
-
-VMEXPORT bool dump_stubs = false;
-
-bool parallel_jit = true;
-
-static bool begin_shutdown_hooks = false;
-
-static M2nFrame* p_m2n = NULL;
-
-typedef union {
- ObjectHandlesOld old;
- ObjectHandlesNew nw;
-} HandlesUnion;
-
-static HandlesUnion* p_handles = NULL;
-
-hythread_library_t hythread_lib;
-
-static void initialize_javahome(Global_Env* p_env)
-{
- PropertiesHandle ph = (PropertiesHandle)&p_env->properties;
- // Determine java home
- const char* jh = properties_get_string_property(ph, "java.home");
- if (!jh) {
- if (apr_env_get((char**)&jh, "JAVA_HOME", 0) != APR_SUCCESS) {
- DIE("Failed to determine Java home directory");
- }
- p_env->properties.add(strdup("java.home"), new Prop_String(strdup(jh)));
- }
-} //initialize_javahome
-
-/**
- * Must be called after vm_arguments parsing.
- */
-static void initialize_classpath(Global_Env* p_env)
-{
- Properties* props = &p_env->properties;
- apr_pool_t *pool;
- apr_pool_create(&pool, 0);
-
- const char* class_path = properties_get_string_property((PropertiesHandle)props, "java.class.path");
-
- // if classpath was not defined by cmd line arguments, check environment
- if (!class_path)
- {
- apr_env_get((char**) &class_path, "CLASSPATH", pool);
- if (class_path)
- TRACE("No classpath specified, using \"CLASSPATH\" environment setting");
- }
-
- // if classpath not defined or empty string, use dafault "." value
- if (!class_path || !class_path[0]) {
- class_path = ".";
- }
-
- add_pair_to_properties(*props, "java.class.path", class_path);
- apr_pool_destroy(pool);
-} //initialize_classpath
-
-static void process_properties_dlls(Global_Env* p_env)
-{
- post_initialize_ee_dlls((PropertiesHandle)&p_env->properties);
-
- const char* dll = properties_get_string_property((PropertiesHandle)&p_env->properties, "vm.em_dll");
- TRACE2("init", "analyzing em dll " << dll);
-
- int ret = CmLoadComponent(dll, "EmInitialize");
- if (JNI_OK != ret) {
- WARN("Cannot load EM component from " << dll << ", error " << ret);
- LOGGER_EXIT(1);
- }
-
- ret = p_env->cm->CreateInstance(&(p_env->em_instance), "em");
- if (JNI_OK != ret) {
- WARN("Cannot instantiate EM, error " << ret);
- LOGGER_EXIT(1);
- }
-
- ret = p_env->em_instance->intf->GetInterface((OpenInterfaceHandle*) &(p_env->em_interface),
- OPEN_INTF_EM_VM);
- if (JNI_OK != ret) {
- WARN("Cannot get EM_VM interface, error " << ret);
- LOGGER_EXIT(1);
- }
-
- const char* dlls = properties_get_string_property((PropertiesHandle)&p_env->properties, "vm.dlls");
- if (!dlls) {
- return;
- }
- dlls = strdup(dlls);
- assert(dlls);
- static const char delimiters[] = { PORT_PATH_SEPARATOR, 0 };
- char* tok = strtok((char*)dlls, delimiters);
- while (tok) {
- TRACE2("init", "analyzing dll " << tok);
-#ifndef USE_GC_STATIC
- if (vm_is_a_gc_dll(tok))
- {
- vm_add_gc(tok);
- }
-#endif // !USE_GC_STATIC
-#ifdef USE_DISEM
- else if (vm_is_a_disem_dll(tok)) {
- vm_add_disem(tok);
- }
-#endif
- else
- {
- WARN("Mandatory library cannot be loaded: " << tok);
- LOGGER_EXIT(1);
- }
- tok = strtok(NULL, delimiters);
- }
- STD_FREE((void*)dlls);
-
-} //process_properties_dlls
-
-#define PROCESS_EXCEPTION(message) \
-{ \
- ECHO("Error occured while running starter class: " << message); \
-\
- if (jenv->ExceptionOccurred()) \
- { \
- jenv->ExceptionDescribe(); \
- jenv->ExceptionClear(); \
- } \
-\
- return 1; \
-} \
-
-static int run_java_main(char *class_name, char **java_args, int java_args_num)
-{
- assert(hythread_is_suspend_enabled());
-
- JNIEnv* jenv = (JNIEnv*) jni_native_intf;
-
- jclass start_class = jenv->FindClass("java/lang/VMStart");
- if (jenv->ExceptionOccurred() || !start_class)
- PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart");
-
- jmethodID main_method = jenv->GetStaticMethodID(start_class, "start", "(Ljava/lang/String;[Ljava/lang/String;)V");
- if (jenv->ExceptionOccurred() || !main_method)
- PROCESS_EXCEPTION("can't find start method in class java/lang/VMStart");
-
- jclass string_class = jenv->FindClass("java/lang/String");
- if (jenv->ExceptionOccurred() || !string_class)
- PROCESS_EXCEPTION("can't find java.lang.String class");
-
- jarray args = jenv->NewObjectArray(java_args_num, string_class, NULL);
- if (jenv->ExceptionOccurred() || !args)
- PROCESS_EXCEPTION("can't create arguments array: java.lang.String[" << java_args_num <<"]");
-
- for (int i = 0; i < java_args_num; i++)
- {
- jstring arg = jenv->NewStringUTF(java_args[i]);
- if (jenv->ExceptionOccurred() || !arg)
- PROCESS_EXCEPTION("can't create java.lang.String object for \"" << java_args[i] << "\"");
-
- jenv->SetObjectArrayElement(args, i, arg);
- if (jenv->ExceptionOccurred())
- PROCESS_EXCEPTION("can't set array element for index " << i);
- }
-
- //create Main class name string
- jstring jclassname = jenv->NewStringUTF(class_name);
-
- jenv->CallStaticVoidMethod(start_class, main_method, jclassname, args);
- if (jenv->ExceptionOccurred())
- PROCESS_EXCEPTION("error during start(...) method execution");
-
- return 0;
-} //run_java_main
-
-static int run_java_init()
-{
- assert(hythread_is_suspend_enabled());
-
- JNIEnv* jenv = (JNIEnv*) jni_native_intf;
-
- jclass start_class = jenv->FindClass("java/lang/VMStart");
- if (jenv->ExceptionOccurred() || !start_class)
- PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart");
-
- jmethodID init_method = jenv->GetStaticMethodID(start_class, "initialize", "()V");
- if (jenv->ExceptionOccurred() || !init_method)
- PROCESS_EXCEPTION("can't find initialize method in class java/lang/VMStart");
-
- jenv->CallStaticVoidMethod(start_class, init_method);
- if (jenv->ExceptionOccurred())
- PROCESS_EXCEPTION("error during initialize() method execution");
-
- return 0;
-} //run_java_init
-
-static int run_java_shutdown()
-{
- assert(hythread_is_suspend_enabled());
-
- JNIEnv* jenv = (JNIEnv*) jni_native_intf;
-
- /*
- * Make shutdown resistant to possible exceptions left in JNI code
- */
- if (jenv->ExceptionOccurred()) {
- PROCESS_EXCEPTION("Exception left unhandled before destroying VM");
- }
-
- jclass start_class = jenv->FindClass("java/lang/VMStart");
- if (jenv->ExceptionOccurred() || !start_class) {
- PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart");
- }
-
- jmethodID shutdown_method = jenv->GetStaticMethodID(start_class, "shutdown", "()V");
- if (jenv->ExceptionOccurred() || !shutdown_method) {
- PROCESS_EXCEPTION("can't find initialize method in class java/lang/VMStart");
- }
-
- jenv->CallStaticVoidMethod(start_class, shutdown_method);
- if (jenv->ExceptionOccurred()) {
- PROCESS_EXCEPTION("error during shutdown() method execution");
- }
-
- return 0;
-} //run_java_shutdown
-
-void create_vm(Global_Env *p_env, JavaVMInitArgs* vm_arguments)
-{
-
-#if defined(PLATFORM_NT)
- OSVERSIONINFO osvi;
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- BOOL ok = GetVersionEx(&osvi);
- if(!ok) {
- DWORD e = GetLastError();
- printf("Windows error: %d\n", e);
- exit(1);
- }
- if((osvi.dwMajorVersion != 4 || osvi.dwMinorVersion != 0) && // NT 4.0
- (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 0) && // Windows 2000
- (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 1) && // Windows XP
- (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 2)) { // Windows.NET
- printf("Windows %d.%d is not supported\n", osvi.dwMajorVersion, osvi.dwMinorVersion);
- exit(1);
- }
-#endif
- hythread_init(hythread_lib);
- vm_thread_init(&env);
-
- VM_Global_State::loader_env = &env;
- hythread_attach(NULL);
- // should be removed
- vm_thread_attach();
- MARK_STACK_END
-
- p_env->TI = new DebugUtilsTI;
-
- assert(hythread_is_suspend_enabled());
-
- vm_initialize_critical_sections();
- initialize_vm_cmd_state(p_env, vm_arguments); //PASS vm_arguments to p_env->vm_arguments and free vm_arguments
- set_log_levels_from_cmd(&p_env->vm_arguments);
-
- if (JNI_OK != CmAcquire(&p_env->cm)) {
- WARN("Cannot initialize a component manager");
- LOGGER_EXIT(1);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- // Begin property processing
- //
- // 20030407 Note: property initialization must follow initialization of the default JITs to allow
- // the command line to override those default JITs.
-
- initialize_properties(p_env, env.properties);
-
- // Enable interpreter by default if TI should be enabled
- p_env->TI->setExecutionMode(p_env);
-
- parse_vm_arguments(p_env);
-
- process_properties_dlls(p_env);
- VERIFY(p_env->em_instance != NULL, "EM init failed");
-
- parse_jit_arguments(&p_env->vm_arguments);
-
- // The following must go after getting propertes and parsing arguments
- initialize_classpath(p_env);
- initialize_javahome(p_env);
-
- VM_Global_State::loader_env->pin_interned_strings =
- (bool)vm_get_property_value_boolean("vm.pin_interned_strings", FALSE);
-
- initialize_verify_stack_enumeration();
-
- //
- // End property processing
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef _WINDOWS
- if (!vm_get_boolean_property_value_with_default("vm.assert_dialog"))
- {
- TRACE2("init", "disabling assertion dialogs");
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
- _set_error_mode(_OUT_TO_STDERR);
- }
-#endif // _WINDOWS
-
- // Initialize the VM's sorted list of code chunks (sorted by starting code address)
- void *p = p_env->mem_pool.alloc(sizeof(Method_Lookup_Table));
- vm_methods = new (p) Method_Lookup_Table();
-
- // Initialize memory allocation
- vm_init_mem_alloc();
- gc_init();
- // gc_thread_init(&p_TLS_vmthread->_gc_private_information);
-
- // Prepares to load natives
- bool UNREF status = natives_init();
- assert( status );
- // Preloading system native libraries
- // initialize_natives((PropertiesHandle)&env.properties);
-
- jni_init();
- /*
- * Valentin Al. Sitnick
- * Initialisation of TI.
- */
- if (0 != p_env->TI->Init()) {
- WARN("JVMTI initialization failed. Exiting.");
- p_env->TI->setDisabled();
- vm_exit(1);
- }
-
- // Moved after Method_Lookup_Table initialization
- extern void initialize_signals();
- initialize_signals();
-
- Class::heap_base = (Byte *)gc_heap_base_address();
- Class::heap_end = (Byte *)gc_heap_ceiling_address();
- Class::managed_null = (vm_references_are_compressed() ? Class::heap_base : NULL);
-
- // 20030404 This handshaking protocol isn't quite correct. It doesn't work at the moment because JIT has not yet been
- // modified to support compressed references, so it never answers "true" to supports_compressed_references().
-
- // Check for a mismatch between whether the various VM components all compress references or not.
- Boolean vm_compression = vm_references_are_compressed();
- Boolean gc_compression = gc_supports_compressed_references();
- if (vm_compression) {
- if (!gc_compression) {
- WARN("VM component mismatch: the VM compresses references but the GC doesn't.");
- vm_exit(1);
- }
-
- // We actually check the first element in the jit_compilers array, as current JIT
- // always returns FALSE to the supports_compressed_references() call.
- JIT **jit = &jit_compilers[0];
- if (!interpreter_enabled()) {
- Boolean jit_compression = (*jit)->supports_compressed_references();
- if (!jit_compression) {
- WARN("VM component mismatch: the VM compresses references but a JIT doesn't");
- vm_exit(1);
- }
- }
- } else {
- if (gc_compression) {
- WARN("VM component mismatch: the VM doesn't compress references but the GC does.");
- vm_exit(1);
- }
- JIT **jit = &jit_compilers[0];
- if (!interpreter_enabled()) {
- Boolean jit_compression = (*jit)->supports_compressed_references();
- if (jit_compression) {
- WARN("VM component mismatch: the VM doesn't compress references but a JIT does");
- vm_exit(1);
- }
- }
- }
-
- // create first m2n frame
- assert(hythread_is_suspend_enabled());
- tmn_suspend_disable();
- p_m2n = (M2nFrame*) p_env->mem_pool.alloc(sizeof(M2nFrame));
- p_handles = (HandlesUnion*) p_env->mem_pool.alloc(sizeof(HandlesUnion));
-
- m2n_null_init(p_m2n);
- m2n_set_last_frame(p_m2n);
-
- oh_null_init_handles((ObjectHandles*)p_handles);
- m2n_set_local_handles(p_m2n, (ObjectHandles*)p_handles);
- m2n_set_frame_type(p_m2n, FRAME_NON_UNWINDABLE);
- tmn_suspend_enable();
-
- if (! vm_init(p_env))
- {
- WARN("Failed to initialize VM.");
- vm_exit(1);
- }
-
- // Send VM init event
- jvmti_send_vm_init_event(p_env);
-
-
- int result = run_java_init();
-
- if (result != 0)
- {
- WARN("Failed execute starter class initialize() method.");
- vm_exit(1);
- }
-} //create_vm
-
-static int run_main(Global_Env *p_env, char* class_name, char* jar_file,
- int java_args_num, char* java_args[])
-{
- if (jar_file)
- {
- // check if file is archive
- if(!file_is_archive(jar_file)) {
- ECHO("You must specify a jar file to run.");
- LOGGER_EXIT(1);
- }
-
- // create archive file structure
- void *mem_jar = STD_ALLOCA(sizeof(JarFile));
- JarFile* jarfl = new (mem_jar) JarFile();
- if(!jarfl || !(jarfl->Parse(jar_file)) ) {
- ECHO("VM can't find the jar file you want to run.");
- LOGGER_EXIT(1);
- }
-
- // extract main class name from jar's manifest
- class_name = strdup(archive_get_main_class_name(jarfl));
- if(!class_name) {
- ECHO("Your jar file hasn't specified Main-Class manifest attribute.");
- LOGGER_EXIT(1);
- }
-
- // close archive file
- jarfl->~JarFile();
-
- } else if (class_name) {
- // convert class name: change '.' to '/'
- for (char* pointer = class_name; *pointer; pointer++) {
- if (*pointer == '/') {
- *pointer = '.';
- }
- }
- }
-
- // if class_name unknown print help and exit
- if (!class_name) {
- p_env->TI->setDisabled();
- print_generic_help();
- vm_exit(1);
- }
-
- // run a given class
- int result = run_java_main(class_name, java_args, java_args_num);
-
- return result;
-} //run_main
-
-void destroy_vm(Global_Env *p_env)
-{
-
- run_java_shutdown();
-
- // usually shutdown hooks do vm_exit().
- // so we do not reach this point
- // but in case ...
-
- WARN("Error occured in starter class shutdown() method.");
- vm_exit(-1);
-} //destroy_vm
-
-
-VMEXPORT int vm_main(int argc, char *argv[])
-{
- init_log_system();
-
- char** java_args;
- int java_args_num;
- char* class_name;
- char* jar_file;
-
- JavaVMInitArgs* vm_arguments =
- parse_cmd_arguments(argc, argv, &class_name, &jar_file, &java_args_num);
-
- java_args = argv + argc - java_args_num;
-
- create_vm(&env, vm_arguments);
-
- clear_vm_arguments(vm_arguments);
-
- run_main(&env, class_name, jar_file, java_args_num, java_args);
-
- destroy_vm(&env);
-
- return 33;
-} //vm_main
-
-static inline
-void dump_all_java_stacks() {
- hythread_iterator_t iterator;
- hythread_suspend_all(&iterator, NULL);
- VM_thread *thread = get_vm_thread (hythread_iterator_next(&iterator));
- while(thread) {
- interpreter.stack_dump(thread);
- thread = get_vm_thread (hythread_iterator_next(&iterator));
- }
- hythread_resume_all( NULL);
- INFO("****** END OF JAVA STACKS *****\n");
-}
-
-void quit_handler(int UNREF x) {
- if (VM_Global_State::loader_env->shutting_down != 0) {
- // too late for quit handler
- // required infrastructure can be missing.
- fprintf(stderr, "quit_handler(): called in shut down stage\n");
- return;
- }
-
- if (interpreter_enabled()) {
- dump_all_java_stacks();
- } else {
- td_dump_all_threads(stderr);
- }
-}
-
-void interrupt_handler(int UNREF x)
-{
- if (VM_Global_State::loader_env->shutting_down != 0) {
- // too late for quit handler
- // required infrastructure can be missing.
- fprintf(stderr, "interrupt_handler(): called in shutdown stage\n");
- return;
- }
-
- if(!begin_shutdown_hooks){
- begin_shutdown_hooks = true;
- //FIXME: integration should do int another way.
- //vm_set_event(non_daemon_threads_dead_handle);
- }else
- exit(1); //vm_exit(1);
-}
-
-JIT_Handle vm_load_jit(const char* file_name, apr_dso_handle_t** handle) {
- //if (vm_is_a_jit_dll(file_name)) {
- Dll_JIT* jit = new Dll_JIT(file_name);
- handle[0]=jit->get_lib_handle();
- vm_add_jit(jit);
- return (JIT_Handle)jit;
-
- /*}
- printf("not a jit\n");
- handle[0]=NULL;
- return 0;*/
-}
Index: vmcore/src/init/vm_shutdown.cpp
===================================================================
--- vmcore/src/init/vm_shutdown.cpp (revision 0)
+++ vmcore/src/init/vm_shutdown.cpp (revision 0)
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Intel, Evgueni Brevnov
+ * @version $Revision: 1.1 $
+ */
+
+#include
+#include
+
+#include "open/hythread.h"
+#include "open/jthread.h"
+
+#include "jni.h"
+#include "jni_direct.h"
+#include "environment.h"
+#include "classloader.h"
+#include "compile.h"
+#include "component_manager.h"
+#include "nogc.h"
+#include "jni_utils.h"
+#include "vm_synch.h"
+#include "vm_stats.h"
+#include "thread_dump.h"
+#include "interpreter.h"
+
+#define LOG_DOMAIN "vm.core.shutdown"
+#include "cxxlog.h"
+
+
+/**
+ * TODO:
+ */
+void vm_cleanup_internal_data() {
+ // Print out gathered data.
+#ifdef VM_STATS
+ ClassLoader::PrintUnloadingStats();
+ VM_Statistics::get_vm_stats().print();
+#endif
+
+ // Unload jit instances.
+ vm_delete_all_jits();
+
+ // Unload component manager and all registered components.
+ // TODO: why do we need to unload "em" explicitly?
+ CmFreeComponent("em");
+ CmRelease();
+
+ // Unload all system native libraries.
+ natives_cleanup();
+
+ // TODO: it seems we don't need to do it!!! At least here!!!
+ gc_wrapup();
+
+ // Release global data.
+ // TODO: move these data to VM space.
+ vm_uninitialize_critical_sections();
+ vm_mem_dealloc();
+}
+
+/**
+ * TODO:
+ */
+void vm_exit(int exit_code)
+{
+ jthread java_thread;
+ JNIEnv * jni_env;
+ Global_Env * vm_env;
+
+ assert(hythread_is_suspend_enabled());
+
+ java_thread = jthread_self();
+ jni_env = jthread_get_JNI_env(java_thread);
+ vm_env = jni_get_vm_env(jni_env);
+
+ // Send VM_Death event and switch phase to VM_Death
+ jvmti_send_vm_death_event();
+
+ /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME *
+ * gregory - JVMTI shutdown should be part of DestroyVM after current VM shutdown *
+ * problems are fixed *
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
+ // call Agent_OnUnload() for agents and unload agents
+ vm_env->TI->Shutdown();
+
+ // Raise uncaught exception to current thread.
+ // It will be properly processed in jthread_detach().
+ if (vm_env->uncaught_exception) {
+ exn_raise_object(vm_env->uncaught_exception);
+ }
+
+ // Detach current thread.
+ IDATA UNREF status = jthread_detach(java_thread);
+ assert(status == TM_ERROR_NONE);
+
+ // Cleanup internal data. Disabled by default due to violation access exception.
+ if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit")) {
+ jthread_cancel_all();
+ vm_cleanup_internal_data();
+ LOGGER_EXIT(exit_code);
+ }
+
+ _exit(exit_code);
+}
+
+#define PROCESS_EXCEPTION(message) \
+{ \
+ ECHO("Internal error: " << message); \
+\
+ if (jni_env->ExceptionCheck()== JNI_TRUE) \
+ { \
+ jni_env->ExceptionDescribe(); \
+ jni_env->ExceptionClear(); \
+ } \
+\
+ return JNI_ERR; \
+} \
+
+/**
+ * Calls java.lang.System.exit() method.
+ * Current thread should be attached to VM.
+ *
+ * @param exit_status VM exit code
+ */
+static jint run_system_exit(JNIEnv * jni_env, jint exit_status) {
+ jvalue args[1];
+
+ assert(hythread_is_suspend_enabled());
+
+ args[0].i = exit_status;
+
+ jclass system_class = jni_env->FindClass("java/lang/System");
+ if (jni_env->ExceptionCheck() == JNI_TRUE || system_class == NULL) {
+ // This is debug message only. May appear when VM is already in shutdown stage.
+ PROCESS_EXCEPTION("can't find java.lang.System class.");
+ }
+
+ jmethodID exit_method = jni_env->GetStaticMethodID(system_class, "exit", "(I)V");
+ if (jni_env->ExceptionCheck() == JNI_TRUE || exit_method == NULL) {
+ PROCESS_EXCEPTION("can't find java.lang.System.exit(int) method.");
+ }
+
+ jni_env->CallStaticVoidMethodA(system_class, exit_method, args);
+
+ if (jni_env->ExceptionCheck() == JNI_TRUE) {
+ PROCESS_EXCEPTION("java.lang.System.exit(int) method completed with an exception.");
+ }
+ return JNI_OK;
+}
+
+/**
+ * TODO:
+ */
+jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread)
+{
+ jint status;
+ JNIEnv * jni_env;
+
+ assert(hythread_is_suspend_enabled());
+
+ jni_env = jthread_get_JNI_env(java_thread);
+
+ status = jthread_wait_for_all_nondaemon_threads();
+ if (status != TM_ERROR_NONE) {
+ TRACE("Failed to wait for all non-daemon threads completion.");
+ return JNI_ERR;
+ }
+
+ // Remember thread's uncaught exception if any.
+ java_vm->vm_env->uncaught_exception = jni_env->ExceptionOccurred();
+ jni_env->ExceptionClear();
+
+ status = java_vm->vm_env->uncaught_exception == NULL ? 0 : 1;
+
+ return run_system_exit(jni_env, status);
+}
+
+static inline void dump_all_java_stacks()
+{
+ hythread_t native_thread;
+ hythread_iterator_t iterator;
+ VM_thread * vm_thread;
+
+ INFO("****** BEGIN OF JAVA STACKS *****\n");
+
+ hythread_suspend_all(&iterator, NULL);
+ native_thread ;
+ while(native_thread = hythread_iterator_next(&iterator)) {
+ vm_thread = get_vm_thread(native_thread);
+ assert(vm_thread);
+ interpreter.stack_dump(vm_thread);
+ }
+ hythread_resume_all(NULL);
+
+ INFO("****** END OF JAVA STACKS *****\n");
+}
+
+void quit_handler(int UNREF x) {
+ if (VM_Global_State::loader_env->shutting_down != 0) {
+ // too late for quit handler
+ // required infrastructure can be missing.
+ fprintf(stderr, "quit_handler(): called in shut down stage\n");
+ return;
+ }
+
+ if (interpreter_enabled()) {
+ dump_all_java_stacks();
+ } else {
+ td_dump_all_threads(stderr);
+ }
+}
+
+void interrupt_handler(int UNREF x)
+{
+ static bool begin_shutdown_hooks = false;
+ if (VM_Global_State::loader_env->shutting_down != 0) {
+ // too late for quit handler
+ // required infrastructure can be missing.
+ fprintf(stderr, "interrupt_handler(): called in shutdown stage\n");
+ return;
+ }
+
+ if(!begin_shutdown_hooks){
+ begin_shutdown_hooks = true;
+ //FIXME: integration should do int another way.
+ //vm_set_event(non_daemon_threads_dead_handle);
+ }else
+ exit(1); //vm_exit(1);
+}
Index: vmcore/src/interpreter/interp_imports.cpp
===================================================================
--- vmcore/src/interpreter/interp_imports.cpp (revision 454089)
+++ vmcore/src/interpreter/interp_imports.cpp (working copy)
@@ -37,9 +37,9 @@
class_throw_linking_error(ch, index, opcode);
}
-extern struct JNIEnv_Internal *jni_native_intf;
+extern JNIEnv *jni_native_intf;
-VMEXPORT struct JNIEnv_Internal* get_jni_native_intf() {
+VMEXPORT JNIEnv * get_jni_native_intf() {
return jni_native_intf;
}
Index: vmcore/src/jit/compile.cpp
===================================================================
--- vmcore/src/jit/compile.cpp (revision 454089)
+++ vmcore/src/jit/compile.cpp (working copy)
@@ -903,7 +903,8 @@
assert(ret_ip);
// Record call from caller to the callee.
- CodeChunkInfo *caller = vm_methods->find(ret_ip);
+ Global_Env *env = VM_Global_State::loader_env;
+ CodeChunkInfo *caller = env->vm_methods->find(ret_ip);
if (caller != NULL) {
caller->record_call_to_callee(callee, ret_ip);
}
Index: vmcore/src/jni/jni.cpp
===================================================================
--- vmcore/src/jni/jni.cpp (revision 454089)
+++ vmcore/src/jni/jni.cpp (working copy)
@@ -19,21 +19,25 @@
* @version $Revision: 1.1.2.2.4.5 $
*/
-
#define LOG_DOMAIN "jni"
#include "cxxlog.h"
+#include
+#include
+#include
+
+#include "open/types.h"
+#include "open/hythread.h"
+#include "open/jthread.h"
+#include "open/vm_util.h"
+
#include "platform.h"
#include "lock_manager.h"
#include "Class.h"
#include "classloader.h"
#include "environment.h"
#include "object_handles.h"
-#include "open/types.h"
-#include "open/vm_util.h"
#include "vm_threads.h"
-#include "open/jthread.h"
-
#include "vm_synch.h"
#include "exceptions.h"
#include "reflection.h"
@@ -44,13 +48,9 @@
#include "m2n.h"
#include "nogc.h"
#include "init.h"
-
#include "Verifier_stub.h"
-
#include "jni_utils.h"
-
#include "jit_runtime_support.h"
-
#include "jvmti_direct.h"
#ifdef _IPF_
@@ -58,6 +58,7 @@
#endif // _IPF_
static void JNICALL UnimpStub(JNIEnv*);
+jint JNICALL GetVersion(JNIEnv *);
struct JNINativeInterface_ jni_vtable = {
@@ -65,6 +66,7 @@
(void*)UnimpStub,
(void*)UnimpStub,
(void*)UnimpStub,
+
GetVersion,
DefineClass,
@@ -333,29 +335,208 @@
(void*)UnimpStub,
(void*)UnimpStub,
- DestroyVM,
+ DestroyJavaVM,
AttachCurrentThread,
DetachCurrentThread,
GetEnv,
- AttachCurrentThreadAsDaemon,
-
+ AttachCurrentThreadAsDaemon
};
-static JavaVM_Internal java_vm = JavaVM_Internal(&java_vm_vtable, NULL, (void *)0x1234abcd);
+/**
+ * List of all running in the current process.
+ */
+APR_RING_HEAD(JavaVM_Internal_T, JavaVM_Internal) GLOBAL_VMS;
-static JNIEnv_Internal jni_env = JNIEnv_Internal(&jni_vtable, &java_vm, (void *)0x1234abcd);
+/**
+ * Memory pool to keep global data.
+ */
+apr_pool_t * GLOBAL_POOL = NULL;
-struct JNIEnv_Internal *jni_native_intf = &jni_env;
+/**
+ * Used to synchronize VM creation and destruction.
+ */
+apr_thread_mutex_t * GLOBAL_LOCK = NULL;
-void jni_init()
+static jboolean & get_init_status() {
+ static jboolean init_status = JNI_FALSE;
+ return init_status;
+}
+/**
+ * Initializes JNI module.
+ * Should be called before creating first VM.
+ */
+static jint jni_init()
{
- java_vm.vm_env = VM_Global_State::loader_env;
-} //jni_init
+ jint status;
+ if (get_init_status() == JNI_FALSE) {
+ status = apr_initialize();
+ if (status != APR_SUCCESS) return JNI_ERR;
+ if (apr_atomic_cas32((volatile apr_uint32_t *)&get_init_status(), JNI_TRUE, JNI_FALSE) == JNI_FALSE) {
+ APR_RING_INIT(&GLOBAL_VMS, JavaVM_Internal, link);
+ status = apr_pool_create(&GLOBAL_POOL, 0);
+ if (status != APR_SUCCESS) return JNI_ERR;
+
+ status = apr_thread_mutex_create(&GLOBAL_LOCK, APR_THREAD_MUTEX_DEFAULT, GLOBAL_POOL);
+ if (status != APR_SUCCESS) {
+ apr_pool_destroy(GLOBAL_POOL);
+ return JNI_ERR;
+ }
+ }
+ }
+ return JNI_OK;
+}
+
+/* BEGIN: List of directly exported functions. */
+
+JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * args)
+{
+ // TODO: current implementation doesn't support JDK1_1InitArgs.
+ if (((JavaVMInitArgs *)args)->version == JNI_VERSION_1_1) {
+ return JNI_EVERSION;
+ }
+ ((JavaVMInitArgs *)args)->version = JNI_VERSION_1_4;
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf,
+ jsize bufLen,
+ jsize * nVMs)
+{
+
+ jint status = jni_init();
+ if (status != JNI_OK) {
+ return status;
+ }
+
+ apr_thread_mutex_lock(GLOBAL_LOCK);
+
+ *nVMs = 0;
+ if (!APR_RING_EMPTY(&GLOBAL_VMS, JavaVM_Internal, link)) {
+ JavaVM_Internal * current_vm = APR_RING_FIRST(&GLOBAL_VMS);
+ while (current_vm) {
+ if (*nVMs < bufLen) {
+ vmBuf[*nVMs] = (JavaVM *)current_vm;
+ }
+ ++(*nVMs);
+ current_vm = APR_RING_NEXT(current_vm, link);
+ }
+
+ }
+ apr_thread_mutex_unlock(GLOBAL_LOCK);
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM ** p_vm, JNIEnv ** p_jni_env,
+ void * args) {
+ jboolean daemon = JNI_FALSE;
+ char * name = "main";
+ JNIEnv * jni_env;
+ JavaVMInitArgs * vm_args;
+ JavaVM_Internal * java_vm;
+ Global_Env * vm_env;
+ apr_pool_t * vm_global_pool;
+ jthread java_thread;
+ jint status;
+
+
+ status = jni_init();
+ if (status != JNI_OK) return status;
+
+ apr_thread_mutex_lock(GLOBAL_LOCK);
+
+ // TODO: only one VM instance can be created in the process address space.
+ if (!APR_RING_EMPTY(&GLOBAL_VMS, JavaVM_Internal, link)) {
+ status = JNI_ERR;
+ goto done;
+ }
+
+ // Create global memory pool.
+ status = apr_pool_create(&vm_global_pool, NULL);
+ if (status != APR_SUCCESS) {
+ TRACE2("jni", "Unable to create memory pool for VM");
+ status = JNI_ENOMEM;
+ goto done;
+ }
+
+ // TODO: current implementation doesn't support JDK1_1InitArgs.
+ if (((JavaVMInitArgs *)args)->version == JNI_VERSION_1_1) {
+ status = JNI_EVERSION;
+ goto done;
+ }
+
+ vm_args = (JavaVMInitArgs *)args;
+ // Create JavaVM_Internal.
+ java_vm = (JavaVM_Internal *) apr_palloc(vm_global_pool, sizeof(JavaVM_Internal));
+ if (java_vm == NULL) {
+ status = JNI_ENOMEM;
+ goto done;
+ }
+
+ // Create Global_Env.
+ vm_env = new(vm_global_pool) Global_Env(vm_global_pool);
+ if (vm_env == NULL) {
+ status = JNI_ENOMEM;
+ goto done;
+ }
+
+ java_vm->functions = &java_vm_vtable;
+ java_vm->pool = vm_global_pool;
+ java_vm->vm_env = vm_env;
+ java_vm->reserved = (void *)0x1234abcd;
+ *p_vm = java_vm;
+
+ status = vm_init1(java_vm, vm_args);
+ if (status != JNI_OK) {
+ goto done;
+ }
+
+ // Attaches main thread to VM.
+ status = vm_attach_internal(&jni_env, &java_thread, java_vm, NULL, name, daemon);
+ if (status != JNI_OK) goto done;
+
+ // Attaches main thread to TM.
+ status = jthread_attach(jni_env, java_thread, daemon);
+ if (status != TM_ERROR_NONE) {
+ status = JNI_ERR;
+ goto done;
+ }
+ assert(jthread_self() != NULL);
+ *p_jni_env = jni_env;
+
+ // Now JVMTIThread keeps global reference. Discared temporary global reference.
+ jni_env->DeleteGlobalRef(java_thread);
+
+ // Send VM start event. JNI services are available now.
+ // JVMTI services permited in the start phase are available as well.
+ jvmti_send_vm_start_event(vm_env, jni_env);
+
+ status = vm_init2(jni_env);
+ if (status != JNI_OK) {
+ goto done;
+ }
+
+ // Send VM init event.
+ jvmti_send_vm_init_event(vm_env);
+
+ // Thread start event for the main thread should be sent after VMInit callback has finished.
+ jvmti_send_thread_start_end_event(1);
+
+ // Register created VM.
+ APR_RING_INSERT_TAIL(&GLOBAL_VMS, java_vm, JavaVM_Internal, link);
+
+ status = JNI_OK;
+done:
+ apr_thread_mutex_unlock(GLOBAL_LOCK);
+ return status;
+}
+
+/* END: List of directly exported functions. */
+
static void JNICALL UnimpStub(JNIEnv* UNREF env)
{
// If we ever get here, we are in an implemented JNI function
@@ -614,10 +795,7 @@
TRACE2("jni", "ExceptionDescribe called");
assert(hythread_is_suspend_enabled());
if (exn_raised()) {
-// tmn_suspend_disable(); //---------------------------------v
- fprintf(stderr, "JNI.ExceptionDescribe: %s:\n", exn_get_name());
exn_print_stack_trace(stderr, exn_get());
-// tmn_suspend_enable(); //---------------------------------^
}
} //ExceptionDescribe
@@ -644,8 +822,7 @@
{
TRACE2("jni", "FatalError called");
assert(hythread_is_suspend_enabled());
- fprintf(stderr, "\nFATAL error occurred in a JNI native method:\n\t%s\n", msg);
- vm_exit(109);
+ DIE("\nFATAL error occurred in a JNI native method:\n\t" << msg);
} //FatalError
jobject JNICALL NewGlobalRef(JNIEnv * UNREF env, jobject obj)
@@ -1256,77 +1433,156 @@
return (jlong)CallStaticIntMethod(env, bbcl, id, buf);
}
+/* BEGIN: Invocation API functions. */
-VMEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args) {
- static int called = 0; // this function can only be called once for now;
+VMEXPORT jint JNICALL DestroyJavaVM(JavaVM * vm)
+{
+ char * name = "destroy";
+ jboolean daemon = JNI_FALSE;
+ jthread java_thread;
+ JavaVM_Internal * java_vm;
+ JNIEnv * jni_env;
+ jint status;
- init_log_system();
- TRACE2("jni", "CreateJavaVM called");
- if (called) {
- WARN("Java Invoke :: multiple VM instances are not implemented");
- ASSERT(0, "Not implemented");
- return JNI_ERR;
- } else {
- create_vm(&env, (JavaVMInitArgs *)vm_args);
- *p_env = &jni_env;
- *p_vm = jni_env.vm;
+ TRACE2("jni", "DestroyJavaVM called");
+
+ java_vm = (JavaVM_Internal *) vm;
+
+ java_thread = jthread_self();
+ if (java_thread == NULL) {
+ // Attaches main thread to VM.
+ status = vm_attach_internal(&jni_env, &java_thread, java_vm, NULL, name, daemon);
+ if (status != JNI_OK) return status;
+
+ status = jthread_attach(jni_env, java_thread, daemon);
+ if (status != TM_ERROR_NONE) return JNI_ERR;
+ // Now JVMTIThread keeps global reference. Discared temporary global reference.
+ jni_env->DeleteGlobalRef(java_thread);
+
+ java_thread = jthread_self();
+ }
+ assert(java_thread != NULL);
+
+ apr_thread_mutex_lock(GLOBAL_LOCK);
+
+ status = vm_destroy(java_vm, java_thread);
+ if (status != JNI_OK) return status;
+
+ APR_RING_REMOVE(java_vm, link);
+
+ // Destroy VM environment.
+ delete java_vm->vm_env;
+
+ // Destroy VM pool.
+ apr_pool_destroy(java_vm->pool);
+
+ // TODO: Destroy globals if it is last VM.
+
+ apr_thread_mutex_unlock(GLOBAL_LOCK);
+
+ // TODO: error code should be returned until
+ // VM cleanups its internals properly.
+ return JNI_ERR;
+}
+
+static jint attach_current_thread(JavaVM * java_vm, void ** p_jni_env, void * args, jboolean daemon)
+{
+ char * name;
+ jobject group;
+ JNIEnv * jni_env;
+ JavaVMAttachArgs * jni_1_2_args;
+ jthread java_thread;
+ IDATA status;
+
+ TRACE2("jni", "AttachCurrentThread called");
+
+ if (jthread_self()) {
+ *p_jni_env = jthread_get_JNI_env(jthread_self());
return JNI_OK;
}
+
+ name = NULL;
+ group = NULL;
+
+ if (args != NULL) {
+ jni_1_2_args = (JavaVMAttachArgs *) args;
+ if (jni_1_2_args->version != JNI_VERSION_1_2) {
+ return JNI_EVERSION;
+ }
+ name = jni_1_2_args->name;
+ group = jni_1_2_args->group;
+ }
+
+ // Attaches current thread to VM.
+ status = vm_attach_internal(&jni_env, &java_thread, java_vm, group, name, daemon);
+ if (status != JNI_OK) return status;
+
+ *p_jni_env = jni_env;
+
+ // Attaches current thread to TM.
+ status = jthread_attach(jni_env, java_thread, daemon);
+ assert(jthread_self() != NULL);
+
+ // Now JVMTIThread keeps global reference. Discared temporary global reference.
+ jni_env->DeleteGlobalRef(java_thread);
+
+ // Send thread start event.
+ // TODO: Thread start event should be sent before its initial method executes.
+ jvmti_send_thread_start_end_event(1);
+
+ return status == TM_ERROR_NONE ? JNI_OK : JNI_ERR;
}
-
-VMEXPORT jint JNICALL DestroyVM(JavaVM*)
+VMEXPORT jint JNICALL AttachCurrentThread(JavaVM * vm, void ** p_jni_env, void * args)
{
- TRACE2("jni", "DestroyVM called");
- destroy_vm(&env);
- return JNI_OK;
+ return attach_current_thread(vm, p_jni_env, args, JNI_FALSE);
}
-VMEXPORT jint JNICALL AttachCurrentThread(JavaVM* vm, void** penv, void* UNREF args)
+VMEXPORT jint JNICALL AttachCurrentThreadAsDaemon(JavaVM * vm, void ** p_jni_env, void * args)
{
- TRACE2("jni", "AttachCurrentThread called");
- if (NULL == p_TLS_vmthread)
- WARN("WARNING!! Attaching deattached thread is not implemented!!\n");
- GetEnv(vm, penv, JNI_VERSION_1_4);
- return JNI_ERR;
+ return attach_current_thread(vm, p_jni_env, args, JNI_TRUE);
}
-VMEXPORT jint JNICALL DetachCurrentThread(JavaVM*)
+VMEXPORT jint JNICALL DetachCurrentThread(JavaVM * vm)
{
- WARN("Java Invoke :: DetachCurrentThread not implemented");
- ASSERT(0, "Not implemented");
- return JNI_ERR;
+ jthread java_thread;
+ IDATA status;
+
+ java_thread = jthread_self();
+ if (java_thread == NULL) return JNI_EDETACHED;
+
+ status = jthread_detach(java_thread);
+
+ // Send thread end event.
+ jvmti_send_thread_start_end_event(0);
+ return status == TM_ERROR_NONE ? JNI_OK : JNI_ERR;
}
-VMEXPORT jint JNICALL GetEnv(JavaVM* vm, void** penv, jint ver)
+VMEXPORT jint JNICALL GetEnv(JavaVM * vm, void ** penv, jint ver)
{
+ VM_thread * vm_thread;
+
TRACE2("jni", "GetEnv called, ver = " << ver);
assert(hythread_is_suspend_enabled());
- if (p_TLS_vmthread == NULL)
- return JNI_EDETACHED;
+ vm_thread = p_TLS_vmthread;
+ if (vm_thread == NULL) return JNI_EDETACHED;
- if ((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JNI)
- switch (ver)
- {
+ if ((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JNI) {
+ switch (ver) {
case JNI_VERSION_1_1:
case JNI_VERSION_1_2:
case JNI_VERSION_1_4:
- *penv = (void*)jni_native_intf;
+ *penv = (void*)vm_thread->jni_env;
return JNI_OK;
}
- else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JVMTI)
+ } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JVMTI) {
return create_jvmti_environment(vm, penv, ver);
- else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x10000000)
- {
+ } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x10000000) {
WARN("GetEnv requested unsupported JVMPI environment!! Only JVMTI is supported by VM.");
- }
- else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x20000000)
- {
+ } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x20000000) {
WARN("GetEnv requested unsupported JVMDI environment!! Only JVMTI is supported by VM.");
- }
- else
- {
+ } else {
WARN("GetEnv called with unsupported interface version 0x" << ((void *)((POINTER_SIZE_INT)ver)));
}
@@ -1334,12 +1590,7 @@
return JNI_EVERSION;
}
-VMEXPORT jint JNICALL AttachCurrentThreadAsDaemon(JavaVM*, void** UNREF penv, void* UNREF args)
-{
- WARN("Java Invoke :: AttachCurrentThreadAsDaemon not implemented");
- ASSERT(0, "Not implemented");
- return JNI_ERR;
-}
+/* END: Invocation API functions. */
/* Global Handles: see jni_utils.h for more information about them */
ObjectHandle gh_jlc;
@@ -1384,21 +1635,19 @@
jdouble gc_double_POSITIVE_INFINITY = 0;
jdouble gc_double_NEGATIVE_INFINITY = 0;
-
+// TODO: should return error code instead of exiting.
static void check_for_unexpected_exception(){
assert(hythread_is_suspend_enabled());
if (exn_raised()) {
- fprintf(stderr, "Error initializing java machine\n");
- fprintf(stderr, "Uncaught and unexpected exception\n");
print_uncaught_exception_message(stderr, "static initializing", exn_get());
- vm_exit(1);
+ DIE("Error initializing java machine\n");
}
}
-void global_object_handles_init(){
- Global_Env *env = VM_Global_State::loader_env;
- JNIEnv_Internal *jenv = jni_native_intf;
+void global_object_handles_init(JNIEnv * jni_env) {
+ Global_Env * vm_env = jni_get_vm_env(jni_env);
+
gh_jlc = oh_allocate_global_handle();
gh_jls = oh_allocate_global_handle();
gh_jlcloneable = oh_allocate_global_handle();
@@ -1422,27 +1671,27 @@
ObjectHandle h_jlt = oh_allocate_global_handle();
tmn_suspend_disable();
- gh_jlc->object = struct_Class_to_java_lang_Class(env->JavaLangClass_Class);
- gh_jls->object = struct_Class_to_java_lang_Class(env->JavaLangString_Class);
- gh_jlcloneable->object = struct_Class_to_java_lang_Class(env->java_lang_Cloneable_Class);
- gh_aoboolean->object = struct_Class_to_java_lang_Class(env->ArrayOfBoolean_Class);
- gh_aobyte->object = struct_Class_to_java_lang_Class(env->ArrayOfByte_Class);
- gh_aochar->object = struct_Class_to_java_lang_Class(env->ArrayOfChar_Class);
- gh_aoshort->object = struct_Class_to_java_lang_Class(env->ArrayOfShort_Class);
- gh_aoint->object = struct_Class_to_java_lang_Class(env->ArrayOfInt_Class);
- gh_aolong->object = struct_Class_to_java_lang_Class(env->ArrayOfLong_Class);
- gh_aofloat->object = struct_Class_to_java_lang_Class(env->ArrayOfFloat_Class);
- gh_aodouble->object = struct_Class_to_java_lang_Class(env->ArrayOfDouble_Class);
+ gh_jlc->object = struct_Class_to_java_lang_Class(vm_env->JavaLangClass_Class);
+ gh_jls->object = struct_Class_to_java_lang_Class(vm_env->JavaLangString_Class);
+ gh_jlcloneable->object = struct_Class_to_java_lang_Class(vm_env->java_lang_Cloneable_Class);
+ gh_aoboolean->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfBoolean_Class);
+ gh_aobyte->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfByte_Class);
+ gh_aochar->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfChar_Class);
+ gh_aoshort->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfShort_Class);
+ gh_aoint->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfInt_Class);
+ gh_aolong->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfLong_Class);
+ gh_aofloat->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfFloat_Class);
+ gh_aodouble->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfDouble_Class);
tmn_suspend_enable(); //-------------------------------------------------------^
- Class *preload_class(Global_Env* env, const char *classname);
- Class* jlboolean = preload_class(env, "java/lang/Boolean");
- Class* jlbyte = preload_class(env, "java/lang/Byte");
- Class* jlchar = preload_class(env, "java/lang/Character");
- Class* jlshort = preload_class(env, "java/lang/Short");
- Class* jlint = preload_class(env, "java/lang/Integer");
- Class* jllong = preload_class(env, "java/lang/Long");
- Class* jlfloat = preload_class(env, "java/lang/Float");
- Class* jldouble = preload_class(env, "java/lang/Double");
+ Class *preload_class(Global_Env* vm_env, const char *classname);
+ Class* jlboolean = preload_class(vm_env, "java/lang/Boolean");
+ Class* jlbyte = preload_class(vm_env, "java/lang/Byte");
+ Class* jlchar = preload_class(vm_env, "java/lang/Character");
+ Class* jlshort = preload_class(vm_env, "java/lang/Short");
+ Class* jlint = preload_class(vm_env, "java/lang/Integer");
+ Class* jllong = preload_class(vm_env, "java/lang/Long");
+ Class* jlfloat = preload_class(vm_env, "java/lang/Float");
+ Class* jldouble = preload_class(vm_env, "java/lang/Double");
tmn_suspend_disable();
gh_jlboolean->object = struct_Class_to_java_lang_Class(jlboolean);
@@ -1453,33 +1702,34 @@
gh_jllong->object = struct_Class_to_java_lang_Class(jllong);
gh_jlfloat->object = struct_Class_to_java_lang_Class(jlfloat);
gh_jldouble->object = struct_Class_to_java_lang_Class(jldouble);
- h_jlt->object= struct_Class_to_java_lang_Class(env->java_lang_Throwable_Class);
+ h_jlt->object= struct_Class_to_java_lang_Class(vm_env->java_lang_Throwable_Class);
tmn_suspend_enable(); //-------------------------------------------------------^
assert(hythread_is_suspend_enabled());
- gid_throwable_traceinfo = jenv->GetFieldID((jclass)h_jlt, "vm_stacktrace", "[J");
+ gid_throwable_traceinfo = jni_env->GetFieldID((jclass)h_jlt, "vm_stacktrace", "[J");
assert(hythread_is_suspend_enabled());
- gid_boolean_value = jenv->GetFieldID((jclass)gh_jlboolean, "value", "Z");
- gid_byte_value = jenv->GetFieldID((jclass)gh_jlbyte, "value", "B");
- gid_char_value = jenv->GetFieldID((jclass)gh_jlchar, "value", "C");
- gid_short_value = jenv->GetFieldID((jclass)gh_jlshort, "value", "S");
- gid_int_value = jenv->GetFieldID((jclass)gh_jlint, "value", "I");
- gid_long_value = jenv->GetFieldID((jclass)gh_jllong, "value", "J");
- gid_float_value = jenv->GetFieldID((jclass)gh_jlfloat, "value", "F");
- gid_double_value = jenv->GetFieldID((jclass)gh_jldouble, "value", "D");
+ gid_boolean_value = jni_env->GetFieldID((jclass)gh_jlboolean, "value", "Z");
+ gid_byte_value = jni_env->GetFieldID((jclass)gh_jlbyte, "value", "B");
+ gid_char_value = jni_env->GetFieldID((jclass)gh_jlchar, "value", "C");
+ gid_short_value = jni_env->GetFieldID((jclass)gh_jlshort, "value", "S");
+ gid_int_value = jni_env->GetFieldID((jclass)gh_jlint, "value", "I");
+ gid_long_value = jni_env->GetFieldID((jclass)gh_jllong, "value", "J");
+ gid_float_value = jni_env->GetFieldID((jclass)gh_jlfloat, "value", "F");
+ gid_double_value = jni_env->GetFieldID((jclass)gh_jldouble, "value", "D");
assert(hythread_is_suspend_enabled());
- gid_doubleisNaN = jenv->GetStaticMethodID((jclass)gh_jldouble, "isNaN", "(D)Z");
+ gid_doubleisNaN = jni_env->GetStaticMethodID((jclass)gh_jldouble, "isNaN", "(D)Z");
- gid_stringinit = jenv->GetMethodID((jclass)gh_jls, "", "([C)V");
- gid_string_field_value = jenv->GetFieldID((jclass)gh_jls, "value", "[C");
- if(env->strings_are_compressed)
- gid_string_field_bvalue = jenv->GetFieldID((jclass)gh_jls, "bvalue", "[B");
- assert(hythread_is_suspend_enabled());
+ gid_stringinit = jni_env->GetMethodID((jclass)gh_jls, "", "([C)V");
+ gid_string_field_value = jni_env->GetFieldID((jclass)gh_jls, "value", "[C");
+
+ if (vm_env->strings_are_compressed) {
+ gid_string_field_bvalue = jni_env->GetFieldID((jclass)gh_jls, "bvalue", "[B");
+ }
- gid_string_field_offset = jenv->GetFieldID((jclass)gh_jls, "offset", "I");
- gid_string_field_count = jenv->GetFieldID((jclass)gh_jls, "count", "I");
+ gid_string_field_offset = jni_env->GetFieldID((jclass)gh_jls, "offset", "I");
+ gid_string_field_count = jni_env->GetFieldID((jclass)gh_jls, "count", "I");
assert(hythread_is_suspend_enabled());
oh_deallocate_global_handle(h_jlt);
@@ -1493,18 +1743,17 @@
assert(hythread_is_suspend_enabled());
}
-void unsafe_global_object_handles_init(){
+void unsafe_global_object_handles_init(JNIEnv * jni_env) {
assert(!hythread_is_suspend_enabled());
tmn_suspend_enable();
- JNIEnv_Internal *jenv = jni_native_intf;
- jfieldID POSITIVE_INFINITY_id = jenv->GetStaticFieldID((jclass)gh_jldouble, "POSITIVE_INFINITY", "D");
- gc_double_POSITIVE_INFINITY = jenv->GetStaticDoubleField((jclass)gh_jldouble, POSITIVE_INFINITY_id);
+ jfieldID POSITIVE_INFINITY_id = jni_env->GetStaticFieldID((jclass)gh_jldouble, "POSITIVE_INFINITY", "D");
+ gc_double_POSITIVE_INFINITY = jni_env->GetStaticDoubleField((jclass)gh_jldouble, POSITIVE_INFINITY_id);
check_for_unexpected_exception();
assert(hythread_is_suspend_enabled());
- jfieldID NEGATIVE_INFINITY_id = jenv->GetStaticFieldID((jclass)gh_jldouble, "NEGATIVE_INFINITY", "D");
- gc_double_NEGATIVE_INFINITY = jenv->GetStaticDoubleField((jclass)gh_jldouble, NEGATIVE_INFINITY_id);
+ jfieldID NEGATIVE_INFINITY_id = jni_env->GetStaticFieldID((jclass)gh_jldouble, "NEGATIVE_INFINITY", "D");
+ gc_double_NEGATIVE_INFINITY = jni_env->GetStaticDoubleField((jclass)gh_jldouble, NEGATIVE_INFINITY_id);
assert(hythread_is_suspend_enabled());
check_for_unexpected_exception();
assert(hythread_is_suspend_enabled());
Index: vmcore/src/jni/jni_utils.cpp
===================================================================
--- vmcore/src/jni/jni_utils.cpp (revision 454089)
+++ vmcore/src/jni/jni_utils.cpp (working copy)
@@ -84,10 +84,10 @@
return cl;
} //class_loader_lookup
-void class_loader_load_native_lib( const char* lib,
+void class_loader_load_native_lib(const char* lib,
ClassLoaderHandle cl)
{
- cl->LoadNativeLibrary( lib );
+ cl->LoadNativeLibrary(lib);
}
@@ -102,12 +102,6 @@
return cl;
} //class_loader_find_if_exists
-
-void class_loader_set_system_class_loader(ClassLoaderHandle cl)
-{
- VM_Global_State::loader_env->system_class_loader = (UserDefinedClassLoader*) cl;
-}
-
VMEXPORT
jvalue *get_jvalue_arg_array(Method *method, va_list args)
{
@@ -453,7 +447,6 @@
jclass SignatureToClass (JNIEnv* env_ext, const char* sig, ClassLoader *class_loader)
{
assert(hythread_is_suspend_enabled());
- JNIEnv_Internal *env = (JNIEnv_Internal *)env_ext;
assert (sig);
if (sig[0] == 'L' || sig[0] == '[') {
@@ -463,7 +456,7 @@
return clazz;
}
- Global_Env *ge = env->vm->vm_env;
+ Global_Env *ge = jni_get_vm_env(env_ext);
Class* clss = NULL;
switch (sig[0]) {
@@ -499,7 +492,7 @@
break;
}
- return jni_class_from_handle(env, clss);
+ return jni_class_from_handle(env_ext, clss);
} // SignatureToClass
@@ -722,8 +715,7 @@
jthrowable exn = class_get_error(loader, name->bytes);
assert(exn);
exn_clear();
- jint UNUSED ok = Throw(env, exn);
- assert(ok == 0);
+ Throw(env, exn);
return 0;
}
}
@@ -817,3 +809,11 @@
}
return true;
}
+
+JavaVM * jni_get_java_vm(JNIEnv * jni_env) {
+ return ((JNIEnv_Internal *)jni_env)->vm;
+}
+
+Global_Env * jni_get_vm_env(JNIEnv * jni_env) {
+ return ((JNIEnv_Internal *)jni_env)->vm->vm_env;
+}
Index: vmcore/src/jvmti/jvmti.cpp
===================================================================
--- vmcore/src/jvmti/jvmti.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti.cpp (working copy)
@@ -290,7 +290,7 @@
!strncmp(option, "-Xrun", 5))
{
TRACE2("jvmti", "Enabling EM JVMTI mode");
- add_pair_to_properties(p_env->properties, "vm.jvmti.enabled", "true");
+ add_pair_to_properties(*p_env->properties, "vm.jvmti.enabled", "true");
break;
}
}
@@ -472,7 +472,7 @@
const char *lib_name,
char **p_path1, char **p_path2)
{
- const char *vm_libs = vm->vm_env->properties.get("vm.boot.library.path")->as_string();
+ const char *vm_libs = vm->vm_env->properties->get("vm.boot.library.path")->as_string();
assert(vm_libs);
char *path1 = apr_pstrdup(pool, vm_libs);
char *path2 = port_dso_name_decorate(lib_name, pool);
Index: vmcore/src/jvmti/jvmti_break.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_break.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_break.cpp (working copy)
@@ -64,7 +64,7 @@
hThread->object = (Java_java_lang_Thread *)j_thread->object;
tmn_suspend_enable();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEventBreakpoint func =
(jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT);
Index: vmcore/src/jvmti/jvmti_event.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_event.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_event.cpp (working copy)
@@ -80,7 +80,6 @@
jvmtiError add_event_to_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread)
{
TIEnv *p_env = (TIEnv *)env;
- //JNIEnv *jni_env = jni_native_intf;
hythread_t p_thread = jthread_get_native_thread(event_thread);
TIEventThread *et = p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL];
@@ -107,7 +106,6 @@
void remove_event_from_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread)
{
TIEnv *p_env = (TIEnv *)env;
- // JNIEnv *jni_env = jni_native_intf;
hythread_t p_thread = jthread_get_native_thread(event_thread);
TIEventThread *et = p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL];
@@ -419,7 +417,7 @@
tmn_suspend_enable();
// Send VM_INIT TI events
TIEnv *ti_env = ti->getEnvironments();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
TIEnv *next_env;
while (NULL != ti_env)
{
@@ -652,7 +650,7 @@
// event is enabled in this environment
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env;
if (NULL != ti_env->event_table.MethodEntry)
@@ -696,7 +694,7 @@
// event is enabled in this environment
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env;
if (NULL != ti_env->event_table.MethodExit) {
TRACE2("jvmti.stack", "Calling MethodExit callback for method: "
@@ -843,7 +841,7 @@
TIEnv *ti_env = (TIEnv*) jvmti_env;
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
assert(method);
TRACE2("jvmti.event.popframe", "PopFrame event is called for method:"
@@ -895,7 +893,7 @@
// event is enabled in this environment
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env;
TRACE2("jvmti.break.ss", "Calling SingleStep callback for env " << jvmti_env << ": " <<
@@ -974,7 +972,7 @@
// event is enabled in this environment
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env;
if (NULL != ti_env->event_table.FieldAccess)
@@ -1049,7 +1047,7 @@
// event is enabled in this environment
jthread thread = getCurrentThread();
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env;
if (NULL != ti_env->event_table.FieldModification)
@@ -1080,7 +1078,7 @@
assert(ti->isEnabled());
// Create local handles frame
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
ObjectHandle hThread = oh_allocate_local_handle();
hThread->object = (Java_java_lang_Thread *)jthread_get_java_thread(curr_native_thread)->object;
@@ -1234,7 +1232,7 @@
hythread_t curr_thread = hythread_self();
// Create local handles frame
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
ObjectHandle exn_object = oh_allocate_local_handle();
exn_object->object = exn;
@@ -1351,7 +1349,7 @@
return;
}
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
tmn_suspend_disable();
// Create local handles frame
@@ -1408,7 +1406,7 @@
return;
}
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
tmn_suspend_disable();
ObjectHandle hThread = oh_allocate_local_handle();
ObjectHandle hClass = oh_allocate_local_handle();
@@ -1467,7 +1465,7 @@
if (!ti->isEnabled())
return;
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
tmn_suspend_disable();
ObjectHandle hLoader = oh_convert_to_local_handle((ManagedObject*)loader->GetLoader());
if( !(hLoader->object) ) hLoader = NULL;
@@ -1552,7 +1550,7 @@
return;
}
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
tmn_suspend_disable(); // -----------vv
ObjectHandle hThread = oh_allocate_local_handle();
ObjectHandle hClass = oh_allocate_local_handle();
@@ -1650,7 +1648,7 @@
static void process_jvmti_event(jvmtiEvent event_type, int per_thread, ...) {
va_list args;
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
TIEnv *ti_env, *next_env;
DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
void *callback_func;
@@ -1759,7 +1757,7 @@
if (ti_env->global_events[JVMTI_EVENT_VM_DEATH - JVMTI_MIN_EVENT_TYPE_VAL])
{
jvmtiEventVMDeath func = (jvmtiEventVMDeath)ti_env->get_event_callback(JVMTI_EVENT_VM_DEATH);
- JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
+ JNIEnv *jni_env = jni_native_intf;
if (NULL != func)
{
TRACE2("jvmti.event.vd", "Callback JVMTI_PHASE_DEATH called");
Index: vmcore/src/jvmti/jvmti_property.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_property.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_property.cpp (working copy)
@@ -75,7 +75,7 @@
// get bootclasspath property
Global_Env *g_env = ((TIEnv*)env)->vm->vm_env;
- Properties *properties = &g_env->properties;
+ Properties *properties = g_env->properties;
const char *bcp_prop = properties_get_string_property(
reinterpret_cast(properties),
"vm.boot.class.path");
@@ -131,7 +131,7 @@
jint properties_count = 0;
- Properties::Iterator *iterator = ((TIEnv*)env)->vm->vm_env->properties.getIterator();
+ Properties::Iterator *iterator = ((TIEnv*)env)->vm->vm_env->properties->getIterator();
const Prop_entry *next = NULL;
while((next = iterator->next()))
properties_count++;
@@ -142,7 +142,7 @@
return errorCode;
// Copy properties defined in properties list
- iterator = ((TIEnv*)env)->vm->vm_env->properties.getIterator();
+ iterator = ((TIEnv*)env)->vm->vm_env->properties->getIterator();
for (int iii = 0; iii < properties_count; iii++)
{
next = iterator->next();
@@ -188,7 +188,7 @@
if (NULL == property || NULL == value_ptr)
return JVMTI_ERROR_NULL_POINTER;
- Prop_Value *prop_value = ((TIEnv*)env)->vm->vm_env->properties.get(property);
+ Prop_Value *prop_value = ((TIEnv*)env)->vm->vm_env->properties->get(property);
if (NULL == prop_value)
return JVMTI_ERROR_NOT_AVAILABLE;
@@ -240,9 +240,9 @@
e->key = strdup(property);
e->value = ps;
- Prop_entry *pe = vm_env->properties.get_entry(property);
+ Prop_entry *pe = vm_env->properties->get_entry(property);
if (NULL == pe)
- vm_env->properties.add(e);
+ vm_env->properties->add(e);
else
pe->replace(e);
Index: vmcore/src/jvmti/jvmti_step.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_step.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_step.cpp (working copy)
@@ -31,6 +31,7 @@
#include "open/bytecodes.h"
#include "open/jthread.h"
#include "jvmti_break_intf.h"
+#include "jni_utils.h"
static inline short
jvmti_GetHalfWordValue( const unsigned char *bytecode,
@@ -483,7 +484,8 @@
// call so we need to search through all methods for this
// one to find it, no way to get vtable and offset in it
NativeCodePtr ip = disasm->get_target_address_from_context(regs);
- CodeChunkInfo *cci = vm_methods->find(ip);
+ Global_Env * vm_env = jni_get_vm_env(vm_thread->jni_env);
+ CodeChunkInfo *cci = vm_env->vm_methods->find(ip);
if (cci)
method = cci->get_method();
else
Index: vmcore/src/jvmti/jvmti_thread.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_thread.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_thread.cpp (working copy)
@@ -26,6 +26,7 @@
#include "cxxlog.h"
#include "jvmti_utils.h"
+#include "jni_utils.h"
#include "vm_threads.h"
#include "thread_generic.h"
@@ -648,6 +649,8 @@
const void* arg,
jint priority)
{
+ JNIEnv * jni_env;
+
TRACE2("jvmti.thread", "RunAgentThread called");
SuspendEnabledChecker sec;
/*
@@ -673,6 +676,8 @@
jmethodID set_daemon = GetMethodID(jvmti_test_jenv, thread_class, "setDaemon", "(Z)V");
assert(set_daemon);
CallVoidMethod(jvmti_test_jenv, thread, set_daemon, JNI_TRUE);
+
+ jni_env = jthread_get_JNI_env(jthread_self());
// Run new thread
// FIXME TM integration, pass arguments correctly
//Java_java_lang_Thread_start_generic(jvmti_test_jenv, thread, env, proc, arg, priority);
@@ -681,7 +686,7 @@
attrs.stacksize = 0;
attrs.daemon = JNI_TRUE;
attrs.jvmti_env = env;
- jthread_create_with_function(jvmti_test_jenv, thread, &attrs, proc, arg);
+ jthread_create_with_function(jni_env, thread, &attrs, proc, arg);
return JVMTI_ERROR_NONE;
}
Index: vmcore/src/jvmti/jvmti_thread_group.cpp
===================================================================
--- vmcore/src/jvmti/jvmti_thread_group.cpp (revision 454089)
+++ vmcore/src/jvmti/jvmti_thread_group.cpp (working copy)
@@ -30,7 +30,7 @@
#include "suspend_checker.h"
#include "environment.h"
-static JNIEnv_Internal * jvmti_test_jenv = jni_native_intf;
+static JNIEnv * jvmti_test_jenv = jni_native_intf;
/*
* Get Top Thread Groups
Index: vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (working copy)
@@ -163,7 +163,7 @@
// current thread isn't allowed to set systemClassLoader as a
// context class loader. Actually, it is abnormal situation if
// thread can not change his own context class loader.
- Thread.currentThread().setContextClassLoader(systemClassLoader);
+ // Thread.currentThread().setContextClassLoader(systemClassLoader);
}
//assert initialized;
SecurityManager sc = System.getSecurityManager();
Index: vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java (working copy)
@@ -44,7 +44,7 @@
EMThreadSupport.run();
}
};
- profilerThread = new Thread(emWorker, "profiler thread");
+ profilerThread = new Thread(Thread.systemThreadGroup, emWorker, "profiler thread");
profilerThread.setDaemon(true);
profilerThread.start();
}
Index: vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (working copy)
@@ -111,10 +111,7 @@
/*
* Staic private part
*/
-
- // Finalizer Threads Group
- private static final ThreadGroup threadGroup = new ThreadGroup("Finalizer Threads Group");
-
+
// Maximum quantity of finalizers threads
private static final int MAX_THREADS = 256;
@@ -313,7 +310,7 @@
private FinalizerStartLock startLock = new FinalizerStartLock();
protected FinalizerThread (boolean permanent) {
- super(threadGroup, "FinalizerThread");
+ super(Thread.systemThreadGroup, "FinalizerThread");
this.permanent = permanent;
this.setDaemon(true);
}
Index: vmcore/src/kernel_classes/javasrc/java/lang/Thread.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (working copy)
@@ -56,11 +56,6 @@
private static final String STACK_TRACE_INDENT = " ";
/**
- * Counter used to generate default thread names
- */
- private static int threadCounter = 0;
-
- /**
* This thread's thread group
*/
ThreadGroup group;
@@ -140,18 +135,32 @@
Object lock = new Object();
/**
- * generates a unique thread ID
- */
- private static synchronized long getNextThreadId() {
- return ++threadOrdinalNum;
- }
-
- /*
* used to generate a default thread name
*/
private static final String THREAD = "Thread-";
/**
+ * System thread group for keeping helper threads.
+ */
+ static ThreadGroup systemThreadGroup = null;
+
+ /**
+ * Main thread group.
+ */
+ static ThreadGroup mainThreadGroup = null;
+
+ /*
+ * Number of threads that was created w/o garbage collection.
+ */
+ private static int currentGCWatermarkCount = 0;
+
+ /*
+ * Max number of threads to be created w/o GC, required collect dead Thread
+ * references.
+ */
+ private static final int GC_WATERMARK_MAX_COUNT = 700;
+
+ /**
* @com.intel.drl.spec_ref
*/
public Thread() {
@@ -194,6 +203,58 @@
}
/**
+ * Creates a new thread object for the thread attached to VM.
+ * The first attached thread is the main thread.
+ *
+ * @param group determines the thread group to place the thread in
+ * @param name thread's name
+ * @param nativeAddr address of the attached native thread
+ * @param stackeSize size of the thread's stack
+ * @param priority thread's priority
+ * @param daemon true if the thread is daemon, false otherwise
+ */
+ Thread(ThreadGroup group, String name, long nativeAddr,
+ long stackSize, int priority, boolean daemon) {
+
+ ClassLoader contextLoader = null;
+
+ if (group == null) {
+ if (systemThreadGroup == null) {
+ // This is main thread.
+ systemThreadGroup = new ThreadGroup();
+ mainThreadGroup = new ThreadGroup(systemThreadGroup, "main");
+ group = mainThreadGroup;
+ // Initialize system class loader.
+ contextLoader = ClassLoader.getSystemClassLoader();
+ } else {
+ group = mainThreadGroup;
+ }
+ }
+
+ this.group = group;
+ this.stackSize = stackSize;
+ this.priority = priority;
+ this.daemon = daemon;
+ this.threadId = getNextThreadId();
+ this.name = (name != null) ? name : THREAD + threadId;
+ // Each thread created from JNI has bootstrap class loader as
+ // its context class loader. The only exception is the main thread
+ // which has system class loader as its context class loader.
+ this.contextClassLoader = contextLoader;
+ this.target = null;
+ // The thread is actually running.
+ this.isAlive = true;
+ this.started = true;
+
+ ThreadWeakRef newRef = new ThreadWeakRef(this);
+ newRef.setNativeAddr(nativeAddr);
+
+ SecurityUtils.putContext(this, AccessController.getContext());
+ // adding the thread to the thread group should be the last action
+ group.add(this);
+ }
+
+ /**
* @com.intel.drl.spec_ref
*/
public Thread(ThreadGroup group, Runnable target, String name,
@@ -201,70 +262,53 @@
Thread currentThread = VMThreadManager.currentThread();
SecurityManager securityManager = System.getSecurityManager();
+
+ ThreadGroup threadGroup = null;
+ if (group != null) {
+ if (securityManager != null) {
+ securityManager.checkAccess(group);
+ }
+ threadGroup = group;
+ } else if (securityManager != null) {
+ threadGroup = securityManager.getThreadGroup();
+ }
+ if (threadGroup == null) {
+ threadGroup = currentThread.group;
+ }
+ this.group = threadGroup;
+ this.daemon = currentThread.daemon;
+ this.contextClassLoader = currentThread.contextClassLoader;
+ this.target = target;
+ this.stackSize = stackSize;
+ this.priority = currentThread.priority;
+ this.threadId = getNextThreadId();
+ // throws NullPointerException if the given name is null
+ this.name = (name != THREAD) ? this.name = name.toString() :
+ THREAD + threadId;
- ThreadGroup threadGroup = null;
- if (group != null) {
- if (securityManager != null) {
- securityManager.checkAccess(group);
- }
- threadGroup = group;
- } else if (securityManager != null) {
- threadGroup = securityManager.getThreadGroup();
- }
- if (threadGroup == null) {
- threadGroup = currentThread.group;
- }
- this.group = threadGroup;
- // throws NullPointerException if the given name is null
- this.name = (name != THREAD) ? this.name = name.toString() : THREAD
- + threadCounter++;
- this.daemon = currentThread.daemon;
- this.contextClassLoader = currentThread.contextClassLoader;
- this.target = target;
- this.stackSize = stackSize;
- this.priority = currentThread.priority;
- initializeInheritableLocalValues(currentThread);
+ initializeInheritableLocalValues(currentThread);
checkGCWatermark();
ThreadWeakRef oldRef = ThreadWeakRef.poll();
ThreadWeakRef newRef = new ThreadWeakRef(this);
- long oldPointer = (oldRef == null)? 0 : oldRef.getNativeAddr();
+ long oldPointer = (oldRef == null) ? 0 : oldRef.getNativeAddr();
long newPointer = VMThreadManager.init(this, newRef, oldPointer);
if (newPointer == 0) {
- throw new OutOfMemoryError("Failed to create new thread");
+ throw new OutOfMemoryError("Failed to create new thread");
}
newRef.setNativeAddr(newPointer);
-
- this.threadId = getNextThreadId();
+
SecurityUtils.putContext(this, AccessController.getContext());
- checkAccess();
+ checkAccess();
+ // adding the thread to the thread group should be the last action
threadGroup.add(this);
}
/**
* @com.intel.drl.spec_ref
*/
- Thread(boolean nativeThread) {
- VMThreadManager.attach(this);
- this.name = "System thread";
- this.group = new ThreadGroup();
- this.group.add(this);
- this.daemon = false;
- this.started = true;
- this.priority = NORM_PRIORITY;
- // initialize the system class loader and set it as context
- // classloader
- ClassLoader.getSystemClassLoader();
-
- this.threadId = getNextThreadId();
- SecurityUtils.putContext(this, AccessController.getContext());
- }
-
- /**
- * @com.intel.drl.spec_ref
- */
public Thread(ThreadGroup group, String name) {
this(group, null, name, 0);
}
@@ -482,11 +526,7 @@
}
}
StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
- if (ste != null) {
- return ste;
- } else {
- return new StackTraceElement[0];
- }
+ return ste != null ? ste : new StackTraceElement[0];
}
/**
@@ -668,8 +708,7 @@
? threadGroup.maxPriority : priority;
int status = VMThreadManager.setPriority(this, this.priority);
if (status != VMThreadManager.TM_ERROR_NONE) {
- // throw new InternalError(
- // "Thread Manager internal error " + status);
+ //throw new InternalError("Thread Manager internal error " + status);
}
}
@@ -687,22 +726,25 @@
this.isAlive = true;
if (VMThreadManager.start(this, stackSize, daemon, priority) != 0) {
- throw new OutOfMemoryError("Failed to start new thread");
+ throw new OutOfMemoryError("Failed to create new thread");
}
started = true;
}
}
- /*
- * This method serves as a wrapper around Thread.run() method to meet
- * specification requirements in regard to ucaught exception catching.
+ /**
+ * Performs premortal actions. First it processes uncaught exception if any.
+ * Second removes current thread from its thread group.
+ * VM calls this method when current thread is detaching from VM.
+ *
+ * @param uncaughtException uncaught exception or null
*/
- void runImpl() {
+ void detach(Throwable uncaughtException) {
try {
- run();
- } catch (Throwable e) {
- getUncaughtExceptionHandler().uncaughtException(this, e);
+ if (uncaughtException != null) {
+ getUncaughtExceptionHandler().uncaughtException(this, uncaughtException);
+ }
} finally {
group.remove(this);
synchronized(lock) {
@@ -712,8 +754,6 @@
}
}
-
-
public enum State {
NEW,
RUNNABLE,
@@ -810,12 +850,10 @@
/**
* @com.intel.drl.spec_ref
*/
- public static void setDefaultUncaughtExceptionHandler(
- UncaughtExceptionHandler eh) {
+ public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- sm
- .checkPermission(RuntimePermissionCollection.SET_DEFAULT_UNCAUGHT_EXCEPTION_HANDLER_PERMISSION);
+ sm.checkPermission(RuntimePermissionCollection.SET_DEFAULT_UNCAUGHT_EXCEPTION_HANDLER_PERMISSION);
}
defaultExceptionHandler = eh;
}
@@ -836,8 +874,7 @@
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- sm
- .checkPermission(RuntimePermissionCollection.MODIFY_THREAD_PERMISSION);
+ sm.checkPermission(RuntimePermissionCollection.MODIFY_THREAD_PERMISSION);
}
exceptionHandler = eh;
}
@@ -890,6 +927,14 @@
localValues.remove(local);
}
}
+
+ /**
+ * Associate current thread object with native thread structure.
+ */
+ private void initNativeThread() {
+
+ }
+
/**
* Initializes local values represented by
@@ -899,7 +944,8 @@
* InheritableThreadLocal class
* This method should be called from Thread's constructor.
*/
- private void initializeInheritableLocalValues(Thread parent) {
+ private void initializeInheritableLocalValues(Thread parent)
+ {
Map, Object> parentLocalValues = parent.localValues;
if (parentLocalValues == null) {
return;
@@ -916,34 +962,34 @@
}
/**
- * @com.intel.drl.spec_ref
+ * generates a unique thread ID
*/
- public static interface UncaughtExceptionHandler {
-
- /**
- * @com.intel.drl.spec_ref
- */
- void uncaughtException(Thread t, Throwable e);
+ private static synchronized long getNextThreadId()
+ {
+ return ++threadOrdinalNum;
}
/*
- * Number of threads that was created w/o garbage collection.
- */
- private static int currentGCWatermarkCount = 0;
-
- /*
- * Max number of threads to be created w/o GC, required collect dead Thread
- * references.
- */
- private static final int GC_WATERMARK_MAX_COUNT = 700;
-
- /*
* Checks if more then GC_WATERMARK_MAX_COUNT threads was created and calls
- * System.gc() to ensure that dead thread references was callected.
+ * System.gc() to ensure that dead thread references was collected.
*/
- private void checkGCWatermark() {
- if (++currentGCWatermarkCount % GC_WATERMARK_MAX_COUNT == 0) {
+ private void checkGCWatermark()
+ {
+ if (++currentGCWatermarkCount % GC_WATERMARK_MAX_COUNT == 0)
+ {
System.gc();
}
}
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static interface UncaughtExceptionHandler
+ {
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ void uncaughtException(Thread t, Throwable e);
+ }
}
Index: vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java (working copy)
@@ -363,7 +363,7 @@
if(throwable instanceof ThreadDeath){
return;
}
- System.err.println("Uncaught exception in "+thread.getName()+":");
+ System.err.println("Uncaught exception in " + thread.getName() + ":");
throwable.printStackTrace();
}
Index: vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (working copy)
@@ -41,7 +41,8 @@
*
* @api2vm
*/
-final class VMClassRegistry {
+final class VMClassRegistry
+{
/**
* This method satisfies the requirements of the specification for the
* {@link Class#getSimpleName() Class.getSimpleName()}
@@ -86,7 +87,8 @@
/**
* This class is not supposed to be instantiated.
*/
- private VMClassRegistry() {
+ private VMClassRegistry()
+ {
}
/**
@@ -108,7 +110,7 @@
* @api2vm
*/
static native Class> defineClass(String name, ClassLoader classLoader,
- byte[] data, int off, int len) throws ClassFormatError;
+ byte[] data, int off, int len) throws ClassFormatError;
/**
* This method satisfies the requirements of the specification for the
@@ -138,10 +140,24 @@
/**
* This method satisfies the requirements of the specification for the
+ * {@link Class#getClassLoader() Class.getClassLoader()} method except
+ * the clazz parameter may be null. In this case context class loader
+ * of the current thread is returned.
+ *
+ * @api2vm
+ */
+ static ClassLoader getClassLoader(Class> clazz) {
+ return clazz != null ? getClassLoader0(clazz)
+ : Thread.currentThread().getContextClassLoader();
+ }
+
+ /**
+ * This method satisfies the requirements of the specification for the
* {@link Class#getClassLoader() Class.getClassLoader()} method.
+ *
* @api2vm
*/
- static native ClassLoader getClassLoader(Class> clazz);
+ static native ClassLoader getClassLoader0(Class> clazz);
/**
* This method satisfies the requirements of the specification for the
Index: vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java
===================================================================
--- vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (revision 454089)
+++ vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (working copy)
@@ -37,7 +37,7 @@
*
*/
class VMStart {
- static int exitCode = 0;
+
public static void initialize() {
//start helper threads such as Finalizer
startHelperThreads();
@@ -47,30 +47,6 @@
parseSystemProperties();
}
- public static void start (String mainClassName, String args[]) {
- try {
- // create main thread in new thread group
- MainThread mainThread = new MainThread(mainClassName, args);
- mainThread.start();
- //startHelperThreads();
- //System.out.println("Join Group " + Thread.currentThread().getThreadGroup());
- } catch (Throwable e) {
- e.printStackTrace(System.err);
- System.exit(-1);
- }
- }
-
- public static void shutdown() {
- try {
- joinAllNonDaemonThreads();
- //System.out.println("Joined all ");
- System.exit(exitCode);
- } catch (Throwable e) {
- e.printStackTrace(System.err);
- System.exit(-1);
- }
- }
-
public static void parseSystemProperties() {
}
@@ -87,75 +63,14 @@
}
// should shutdown helper threads
static class DefaultShutDownHook extends Thread {
+
+ public DefaultShutDownHook() {
+ super("Thread-shutdown");
+ }
+
public void run() {
FinalizerThread.shutdown();
EMThreadSupport.shutdown();
}
}
-
- // main thread
- static class MainThread extends Thread {
- String mainClass;
- String args[];
- public boolean started = false;
-
- MainThread (String mainClass, String args[]) {
- super(new ThreadGroup("main"), "main");
- this.mainClass = mainClass;
- this.args = args;
-
- }
- public void run() {
- }
-
- void runImpl() {
- // prevent access from user classes to run() method
- if(started) {
- return;
- }
- started = true;
-
- try {
- // load and start main class
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- Class cl = Class.forName(mainClass, true, loader);
- final Method mainMethod = cl.getMethod("main",
- new Class[]{String[].class});
- int expectedModifiers = (Modifier.PUBLIC | Modifier.STATIC);
- if ((mainMethod.getModifiers() & expectedModifiers) != expectedModifiers
- || mainMethod.getReturnType() != Void.TYPE) {
- throw new NoSuchMethodError(
- "The method main must be declared public, static, and void.");
- }
- // the class itself may be non-public
- AccessController.doPrivileged(new PrivilegedAction