Index: trunk/vm/vmcore/include/atomics.h =================================================================== --- trunk/vm/vmcore/include/atomics.h (revision 476066) +++ trunk/vm/vmcore/include/atomics.h (working copy) @@ -24,7 +24,6 @@ #include "jni.h" #include "Class.h" -#include "vm_synch.h" JNIEXPORT jlong getFieldOffset Index: trunk/vm/vmcore/include/environment.h =================================================================== --- trunk/vm/vmcore/include/environment.h (revision 476066) +++ trunk/vm/vmcore/include/environment.h (working copy) @@ -68,6 +68,12 @@ bool verify_all; // psrebriy 20050815 Verify all classes including loaded by bootstrap class loader bool pin_interned_strings; // if true, interned strings are never moved + Lock_Manager *p_jit_a_method_lock; + Lock_Manager *p_vtable_patch_lock; + Lock_Manager *p_meth_addr_table_lock; + Lock_Manager *p_method_call_lock; + Lock_Manager *p_handle_lock; + // If set to true by the "-compact_fields" command line option, // the VM will not pad out fields of less than 32 bits to four bytes. // However, fields will still be aligned to a natural boundary, @@ -194,20 +200,9 @@ 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 - * 1 - shutting down - * 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 Index: trunk/vm/vmcore/include/init.h =================================================================== --- trunk/vm/vmcore/include/init.h (revision 476066) +++ trunk/vm/vmcore/include/init.h (working copy) @@ -31,7 +31,6 @@ 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); void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments); void set_log_levels_from_cmd(JavaVMInitArgs* vm_arguments); Index: trunk/vm/vmcore/include/lock_manager.h =================================================================== --- trunk/vm/vmcore/include/lock_manager.h (revision 476066) +++ trunk/vm/vmcore/include/lock_manager.h (working copy) @@ -66,13 +66,6 @@ bool m_unlock; }; - -extern Lock_Manager *p_jit_a_method_lock; -extern Lock_Manager *p_vtable_patch_lock; -extern Lock_Manager *p_meth_addr_table_lock; -// 20040224 Support for recording which methods (actually, CodeChunkInfo's) call which other methods. -extern Lock_Manager *p_method_call_lock; -extern Lock_Manager *p_handle_lock; #endif // __cplusplus #endif // _lock_manager_H_ Index: trunk/vm/vmcore/include/vm_synch.h =================================================================== --- trunk/vm/vmcore/include/vm_synch.h (revision 476066) +++ trunk/vm/vmcore/include/vm_synch.h (working copy) @@ -1,27 +1 @@ -/* - * 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.1.4.3 $ - */ -void vm_initialize_critical_sections(); -void vm_uninitialize_critical_sections(); -void vm_remove_critical_sections(); -#include "mon_enter_exit.h" -#include "thread_manager.h" - Index: trunk/vm/vmcore/src/class_support/Environment.cpp =================================================================== --- trunk/vm/vmcore/src/class_support/Environment.cpp (revision 476066) +++ trunk/vm/vmcore/src/class_support/Environment.cpp (working copy) @@ -32,6 +32,7 @@ #include "verifier.h" #include "native_overrides.h" #include "compile.h" +#include "component_manager.h" Global_Env::Global_Env(apr_pool_t * pool): @@ -115,6 +116,13 @@ verify_all = false; pin_interned_strings = false; + // 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(); + p_method_call_lock = new Lock_Manager(); + // // preloaded classes // @@ -164,10 +172,7 @@ JavaLangString_VTable = NULL; JavaLangString_allocation_handle = 0; - uncaught_exception = NULL; - vm_class_offset = 0; - shutting_down = 0; TI = new DebugUtilsTI; vm_methods = new Method_Lookup_Table; @@ -178,6 +183,10 @@ Global_Env::~Global_Env() { + if (vm_get_boolean_property_value_with_default("vm.noCleanupOnExit")) { + return; + } + GlobalClassLoaderIterator ClIterator; ClassLoader *cl = ClIterator.first(); @@ -197,16 +206,37 @@ 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); + // 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; + + // Unload jit instances. + vm_delete_all_jits(); + + // Unload component manager and all registered components. + CmRelease(); + + // Unload all system native libraries. + natives_cleanup(); + + // Unload GC-releated resources. + gc_wrapup(); + + // Deallocate global vtable & jit code pools. + vm_mem_dealloc(); + + // TODO: Currently, there is only one global thread library instance. + // It still can be used after VM is destroyed. + // hythread_lib_destroy(hythread_lib); } Class* Global_Env::LoadCoreClass(const String* s) Index: trunk/vm/vmcore/src/class_support/method.cpp =================================================================== --- trunk/vm/vmcore/src/class_support/method.cpp (revision 476066) +++ trunk/vm/vmcore/src/class_support/method.cpp (working copy) @@ -474,7 +474,9 @@ void Method::add_vtable_patch(void *patch) { - p_vtable_patch_lock->_lock(); // vvv + Global_Env * vm_env = VM_Global_State::loader_env; + + vm_env->p_vtable_patch_lock->_lock(); // vvv if (_vtable_patch == NULL) { VTable_Patches *vp = (VTable_Patches *)STD_MALLOC(sizeof(VTable_Patches)); @@ -487,7 +489,7 @@ for (int i = 0; i < MAX_VTABLE_PATCH_ENTRIES; i++) { if (curr_vp->patch_table[i] == NULL) { curr_vp->patch_table[i] = patch; - p_vtable_patch_lock->_unlock(); // ^^ + vm_env->p_vtable_patch_lock->_unlock(); // ^^ return; } } @@ -497,21 +499,22 @@ _vtable_patch = new_vp; new_vp->patch_table[0] = patch; - p_vtable_patch_lock->_unlock(); // ^^^ + vm_env->p_vtable_patch_lock->_unlock(); // ^^^ } //Method::add_vtable_patch void Method::apply_vtable_patches() { - p_vtable_patch_lock->_lock(); + Global_Env * vm_env = VM_Global_State::loader_env; if (_vtable_patch == NULL) { // Constructors are never entered into a vtable. - p_vtable_patch_lock->_unlock(); return; } + vm_env->p_vtable_patch_lock->_lock(); + void *code_addr = get_code_addr(); VTable_Patches *vp = (VTable_Patches *)_vtable_patch; @@ -523,7 +526,7 @@ } } - p_vtable_patch_lock->_unlock(); + vm_env->p_vtable_patch_lock->_unlock(); } //Method::apply_vtable_patches Index: trunk/vm/vmcore/src/class_support/method_lookup.cpp =================================================================== --- trunk/vm/vmcore/src/class_support/method_lookup.cpp (revision 476066) +++ trunk/vm/vmcore/src/class_support/method_lookup.cpp (working copy) @@ -82,8 +82,10 @@ void Method_Lookup_Table::add(CodeChunkInfo *m) { - p_meth_addr_table_lock->_lock(); + Global_Env * vm_env = VM_Global_State::loader_env; + vm_env->p_meth_addr_table_lock->_lock(); + void *code_block_addr = m->get_code_block_addr(); // If the table is full, allocate more memory. @@ -100,7 +102,7 @@ _table[idx] = m; _next_free_entry++; - p_meth_addr_table_lock->_unlock(); + vm_env->p_meth_addr_table_lock->_unlock(); } //Method_Lookup_Table::add @@ -160,6 +162,8 @@ CodeChunkInfo *Method_Lookup_Table::find(void *addr, bool is_ip_past) { + Global_Env * vm_env = VM_Global_State::loader_env; + if (addr == NULL) { return NULL; } @@ -186,7 +190,7 @@ VM_Statistics::get_vm_stats().num_method_lookup_cache_miss++; #endif //VM_STATS - p_meth_addr_table_lock->_lock(); + vm_env->p_meth_addr_table_lock->_lock(); unsigned L = 0, R = _next_free_entry; while (L < R) { @@ -205,12 +209,12 @@ #ifdef USE_METHOD_LOOKUP_CACHE _cache[cache_idx] = m; #endif //USE_METHOD_LOOKUP_CACHE - p_meth_addr_table_lock->_unlock(); + vm_env->p_meth_addr_table_lock->_unlock(); return m; } } - p_meth_addr_table_lock->_unlock(); + vm_env->p_meth_addr_table_lock->_unlock(); return NULL; } //Method_Lookup_Table::find @@ -218,11 +222,13 @@ CodeChunkInfo *Method_Lookup_Table::find_deadlock_free(void *addr) { - bool ok = p_meth_addr_table_lock->_lock_or_null(); // vvv + Global_Env * vm_env = VM_Global_State::loader_env; + + bool ok = vm_env->p_meth_addr_table_lock->_lock_or_null(); // vvv if (ok) { // We acquired the lock. Can use the fast lookup. CodeChunkInfo *m = find(addr); - p_meth_addr_table_lock->_unlock_or_null(); // ^^^ + vm_env->p_meth_addr_table_lock->_unlock_or_null(); // ^^^ return m; } else { // We failed to acquire the lock. Use slow linear search. Index: trunk/vm/vmcore/src/init/finalize.cpp =================================================================== --- trunk/vm/vmcore/src/init/finalize.cpp (revision 476066) +++ trunk/vm/vmcore/src/init/finalize.cpp (working copy) @@ -35,7 +35,6 @@ #include "compile.h" #include "nogc.h" #include "jit_runtime_support.h" -#include "vm_synch.h" #include "finalize.h" Index: trunk/vm/vmcore/src/init/parse_arguments.cpp =================================================================== --- trunk/vm/vmcore/src/init/parse_arguments.cpp (revision 476066) +++ trunk/vm/vmcore/src/init/parse_arguments.cpp (working copy) @@ -367,8 +367,8 @@ const char* arg = option + strlen("-Xdumpfile:"); dump_file_name = arg; } - else if (strcmp(option, "-XcleanupOnExit") == 0) { - add_pair_to_properties(*p_env->properties, "vm.cleanupOnExit", "true"); + else if (strcmp(option, "-XnoCleanupOnExit") == 0) { + add_pair_to_properties(*p_env->properties, "vm.noCleanupOnExit", "true"); } else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) { // Store a pointer to the portlib @@ -619,16 +619,16 @@ " Specify gc specific options\n" " -Xem:\n" " Specify em specific options\n" - " -Xdumpstubs\n" - " Writes stubs generated by LIL to disk\n" - " -Xparallel_jit\n" - " Launch compilation in parallel (default)\n" - " -Xno_parallel_jit\n" - " Do not launch compilation in parallel\n" - " -Xdumpfile:\n" - " Specifies a file name for the dump\n" - " -XcleanupOnExit\n" - " Excplicitly free VM resources before exit\n"); + " -Xdumpstubs\n" + " Writes stubs generated by LIL to disk\n" + " -Xparallel_jit\n" + " Launch compilation in parallel (default)\n" + " -Xno_parallel_jit\n" + " Do not launch compilation in parallel\n" + " -Xdumpfile:\n" + " Specifies a file name for the dump\n" + " -XnoCleanupOnExit\n" + " Exit without cleaning internal resorces\n"); } //print_help_on_nonstandard_options void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments) Index: trunk/vm/vmcore/src/init/vm.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm.cpp (revision 476066) +++ trunk/vm/vmcore/src/init/vm.cpp (working copy) @@ -40,7 +40,6 @@ #include "open/vm_util.h" #include "jit_intf.h" #include "object_handles.h" -#include "vm_synch.h" #include "vm_threads.h" #include "vm_stats.h" #include "vm_arrays.h" @@ -116,7 +115,7 @@ true, TRUE}, {"vm.jvmti.enabled", "Whether JVMTI mode is enabled.", true, FALSE}, - {"vm.cleanupOnExit", "Excplicitly free VM resources before exit.", + {"vm.noCleanupOnExit", "Exit without cleaning internal resorces.", true, FALSE}, {"vm.bootclasspath.appendclasspath", "Append classpath to the bootclasspath", true, FALSE}, Index: trunk/vm/vmcore/src/init/vm_init.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm_init.cpp (revision 476066) +++ trunk/vm/vmcore/src/init/vm_init.cpp (working copy) @@ -61,22 +61,6 @@ void* Slot::heap_base = NULL; void* Slot::heap_ceiling = NULL; -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(); - p_method_call_lock = new Lock_Manager(); -} - -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; -} - Class* preload_class(Global_Env * vm_env, const char * classname) { String * s = vm_env->string_pool.lookup(classname); return vm_env->LoadCoreClass(s); @@ -630,7 +614,6 @@ init_log_system(); set_log_levels_from_cmd(&vm_env->vm_arguments); - vm_initialize_critical_sections(); vm_monitor_init(); status = CmAcquire(&vm_env->cm); Index: trunk/vm/vmcore/src/init/vm_shutdown.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm_shutdown.cpp (revision 476066) +++ trunk/vm/vmcore/src/init/vm_shutdown.cpp (working copy) @@ -30,10 +30,8 @@ #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" @@ -41,84 +39,6 @@ #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 - JavaVM *java_vm; - jni_env->GetJavaVM(&java_vm); - vm_env->TI->Shutdown(java_vm); - - // 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); \ @@ -133,33 +53,31 @@ } \ /** - * Calls java.lang.System.exit() method. - * Current thread should be attached to VM. + * Calls java.lang.System.execShutdownSequence() method. * - * @param exit_status VM exit code + * @param jni_env JNI environment of the current thread */ -static jint run_system_exit(JNIEnv * jni_env, jint exit_status) { - jvalue args[1]; +static jint exec_shutdown_sequence(JNIEnv * jni_env) { + jclass system_class; + jmethodID shutdown_method; assert(hythread_is_suspend_enabled()); - args[0].i = exit_status; - - jclass system_class = jni_env->FindClass("java/lang/System"); + 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."); + shutdown_method = jni_env->GetStaticMethodID(system_class, "execShutdownSequence", "()V"); + if (jni_env->ExceptionCheck() == JNI_TRUE || shutdown_method == NULL) { + PROCESS_EXCEPTION("can't find java.lang.System.execShutdownSequence() method."); } - jni_env->CallStaticVoidMethodA(system_class, exit_method, args); + jni_env->CallStaticVoidMethod(system_class, shutdown_method); if (jni_env->ExceptionCheck() == JNI_TRUE) { - PROCESS_EXCEPTION("java.lang.System.exit(int) method completed with an exception."); + PROCESS_EXCEPTION("java.lang.System.execShutdownSequence() method completed with an exception."); } return JNI_OK; } @@ -171,10 +89,16 @@ { jint status; JNIEnv * jni_env; + jobject uncaught_exception; + VM_thread * vm_thread; + hythread_t native_thread; + hythread_t current_native_thread; + hythread_iterator_t it; assert(hythread_is_suspend_enabled()); jni_env = jthread_get_JNI_env(java_thread); + current_native_thread = hythread_self(); status = jthread_wait_for_all_nondaemon_threads(); if (status != TM_ERROR_NONE) { @@ -182,13 +106,58 @@ return JNI_ERR; } + // Print out gathered data. +#ifdef VM_STATS + ClassLoader::PrintUnloadingStats(); + VM_Statistics::get_vm_stats().print(); +#endif + // Remember thread's uncaught exception if any. - java_vm->vm_env->uncaught_exception = jni_env->ExceptionOccurred(); + uncaught_exception = jni_env->ExceptionOccurred(); jni_env->ExceptionClear(); - status = java_vm->vm_env->uncaught_exception == NULL ? 0 : 1; + // Execute pinding shutdown hooks & finalizers + status = exec_shutdown_sequence(jni_env); + if (status != JNI_OK) return status; - return run_system_exit(jni_env, status); + // Send VM_Death event and switch to VM_Death phase. + // This should be the last event sent by VM. + // This event should be sent before Agent_OnUnload called. + jvmti_send_vm_death_event(); + + // Raise uncaught exception to current thread. + // It will be properly processed in jthread_detach(). + if (uncaught_exception) { + exn_raise_object(uncaught_exception); + } + + // Detach current thread. + status = jthread_detach(java_thread); + if (status != TM_ERROR_NONE) return JNI_ERR; + + // Call Agent_OnUnload() for agents and unload agents. + java_vm->vm_env->TI->Shutdown(java_vm); + + // Stop all (except current) java and native threads + // before destroying VM-wide data. + + // TODO: current implementation doesn't stop java threads :-( + // So, don't perform cleanup if there are running java threads. + it = hythread_iterator_create(NULL); + while (native_thread = hythread_iterator_next(&it)) { + vm_thread = get_vm_thread(native_thread); + if (vm_thread != NULL && native_thread != current_native_thread) { + add_pair_to_properties(*java_vm->vm_env->properties, "vm.noCleanupOnExit", "true"); + hythread_iterator_release(&it); + return JNI_ERR; + } + } + hythread_iterator_release(&it); + + // TODO: ups we don't stop native threads as well :-(( + // We are lucky! Currently, there are no such threads. + + return JNI_OK; } static inline void dump_all_java_stacks() @@ -212,13 +181,6 @@ } 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 { @@ -229,17 +191,11 @@ 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); + exit(1); } Index: trunk/vm/vmcore/src/jit/compile.cpp =================================================================== --- trunk/vm/vmcore/src/jit/compile.cpp (revision 476066) +++ trunk/vm/vmcore/src/jit/compile.cpp (working copy) @@ -145,6 +145,8 @@ // 20040224 Support for recording which methods (actually, CodeChunkInfo's) call which other methods. void CodeChunkInfo::record_call_to_callee(CodeChunkInfo *callee, void *caller_ip) { + Global_Env * vm_env = VM_Global_State::loader_env; + assert(callee); assert(caller_ip); @@ -152,7 +154,7 @@ // 20040422 No, the backedge isn't needed yet. Just record one direction now, and create the other direction later. // Acquire a lock to ensure that growing the callee array is safe. - p_method_call_lock->_lock(); // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + vm_env->p_method_call_lock->_lock(); // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Is the pair already in our list? unsigned i; @@ -160,7 +162,7 @@ Callee_Info *c = &(_callee_info[i]); if ((c->callee == callee) && (c->caller_ip == caller_ip)) { c->num_calls++; - p_method_call_lock->_unlock(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + vm_env->p_method_call_lock->_unlock(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return; } } @@ -190,7 +192,7 @@ c->num_calls = 1; _num_callees++; - p_method_call_lock->_unlock(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + vm_env->p_method_call_lock->_unlock(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } //CodeChunkInfo::record_call_to_callee @@ -677,11 +679,13 @@ JIT_Result compile_do_compilation_jit(Method* method, JIT* jit) { + Global_Env * vm_env = VM_Global_State::loader_env; + assert(method); assert(jit); if (!parallel_jit) { - p_jit_a_method_lock->_lock(); + vm_env->p_jit_a_method_lock->_lock(); // MikhailF reports that each JIT in recompilation chain has its own // JIT* pointer. // If in addition to recompilation chains one adds recompilation loops, @@ -689,7 +693,7 @@ // modified. if (NULL != method->get_chunk_info_no_create_mt(jit, CodeChunkInfo::main_code_chunk_id)) { - p_jit_a_method_lock->_unlock(); + vm_env->p_jit_a_method_lock->_unlock(); return JIT_SUCCESS; } } @@ -706,7 +710,7 @@ if (JIT_SUCCESS != res) { if (!parallel_jit) { - p_jit_a_method_lock->_unlock(); + vm_env->p_jit_a_method_lock->_unlock(); } return res; } @@ -728,11 +732,11 @@ method->apply_vtable_patches(); method->unlock(); if (!parallel_jit) { - p_jit_a_method_lock->_unlock(); + vm_env->p_jit_a_method_lock->_unlock(); } // Find TI environment - DebugUtilsTI *ti = VM_Global_State::loader_env->TI; + DebugUtilsTI *ti = vm_env->TI; // Call TI callbacks if (ti->isEnabled() && ti->getPhase() == JVMTI_PHASE_LIVE) { Index: trunk/vm/vmcore/src/jit/jit_runtime_support.cpp =================================================================== --- trunk/vm/vmcore/src/jit/jit_runtime_support.cpp (revision 476066) +++ trunk/vm/vmcore/src/jit/jit_runtime_support.cpp (working copy) @@ -55,7 +55,6 @@ #include "object_handles.h" #include "vm_arrays.h" #include "vm_strings.h" -#include "vm_synch.h" #include "vm_threads.h" #include "open/types.h" #include "open/bytecodes.h" Index: trunk/vm/vmcore/src/jni/jni.cpp =================================================================== --- trunk/vm/vmcore/src/jni/jni.cpp (revision 476066) +++ trunk/vm/vmcore/src/jni/jni.cpp (working copy) @@ -38,7 +38,6 @@ #include "environment.h" #include "object_handles.h" #include "vm_threads.h" -#include "vm_synch.h" #include "exceptions.h" #include "reflection.h" #include "ini.h" @@ -1463,8 +1462,8 @@ apr_thread_mutex_lock(GLOBAL_LOCK); status = vm_destroy(java_vm, java_thread); - if (status != JNI_OK) return status; + // Remove current VM from the list of all VMs running in the current adress space. APR_RING_REMOVE(java_vm, link); // Destroy VM environment. @@ -1472,14 +1471,10 @@ // 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; + return status; } static jint attach_current_thread(JavaVM * java_vm, void ** p_jni_env, void * args, jboolean daemon) Index: trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java =================================================================== --- trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (working copy) @@ -86,7 +86,7 @@ /** * VM calls this method to request finalizer thread shutdown. */ - static void shutdown() { + static void shutdown(boolean startFinalizationOnExit) { if (TRACE) { trace("shutting down finalizer thread"); } @@ -102,13 +102,6 @@ } /* - * Support for runFinalizersOnExit(boolean) from Runtime class - */ - static void setFinalizersOnExit(boolean value) { - startFinalizationOnExit = value; - } - - /* * Staic private part */ @@ -141,9 +134,6 @@ */ private static int waitFinishCounter = 0; - // true indicates that finalization on exit should be started - private static volatile boolean startFinalizationOnExit = false; - // Indicates processors quantity in the system private static int processorsQuantity; Index: trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java =================================================================== --- trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java (working copy) @@ -18,10 +18,7 @@ * @author Serguei S.Zapreyev * @version $Revision: 1.1.2.2.4.5 $ * - * This Core API Runtime class ("Software") is furnished under license and may - * only be used or copied in accordance with the terms of that license. - * - **/ + */ /** * ############################################################################### @@ -36,7 +33,7 @@ * reimplemented on the native side. * ############################################################################### * ############################################################################### - **/ + */ package java.lang; @@ -48,148 +45,20 @@ import java.lang.UnsatisfiedLinkError; import java.lang.VMExecutionEngine; import java.lang.VMMemoryManager; - -import java.util.Vector; - +import java.util.ArrayList; import org.apache.harmony.vm.VMStack; -//import org.apache.harmony.vm.VMStack.CallsTraceElement; +import org.apache.harmony.kernel.vm.VM; +import org.apache.harmony.luni.util.DeleteOnExit; +import org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection; +import org.apache.harmony.lang.RuntimePermissionCollection; /** - * * @com.intel.drl.spec_ref - * - **/ + */ +public class Runtime +{ -public class Runtime { - //-------------------------------------------------------------------------------- - // Nested Runtime.ShutdownVM class: - //-------------------------------------------------------------------------------- - - static final class ShutdownVM { - - private static class Synchro { - }; - - private static Vector hooksList = new Vector(); - - private static int VMState = 0; // 0 - normal work - // 1 - being shutdown sequence running - // 2 - being finalizing - - private static boolean finalizationOnExit = false; - - /** - * - * Support for runFinalizersOnExit(boolean) from Runtime class - * - */ - - static void runFinalizersOnExit(boolean value) { - synchronized (Synchro.class) { - FinalizerThread.setFinalizersOnExit(value); - finalizationOnExit = value; - } - } - - /** - * - * Support for exit(int) from Runtime class - * - */ - - static void exit(int status) { - // The virtual machine's shutdown sequence consists of two phases: - - // #1: - // In the first phase all registered shutdown hooks, if any, are started in some - // unspecified order and allowed to run concurrently until they finish. - synchronized (Synchro.class) { - try { - if (VMState == 0) { - VMState = 1; - if (hooksList != null) { - for (int i = 0; i < hooksList.size(); i++) { - ((Thread)hooksList.elementAt(i)).start(); - } - - for (int i = 0; i < hooksList.size(); i++) { - while (true){ - try { - ((Thread)hooksList.elementAt(i)).join(); - break; - } catch (InterruptedException e) { - continue; - } - } - } - - hooksList.removeAllElements(); - } - } - } catch (Throwable e) {} // skip any exceptions in shutdown sequence - } - - // #2: - // In the second phase all uninvoked finalizers are run if finalization-on-exit has been - // enabled. Once this is done the virtual machine halts." - synchronized (Synchro.class) { - VMState = 2; - VMExecutionEngine.exit(status, finalizationOnExit); - } - - } - - /** - * - * Support for addShutdownHook(Thread) from Runtime class - * - */ - - static void addShutdownHook(Thread hook) throws IllegalStateException, IllegalArgumentException { - if (hook.getState() != Thread.State.NEW) { - throw new IllegalArgumentException(); - } - synchronized (hooksList) { - if (hooksList.contains((Object) hook)) { - throw new IllegalArgumentException(); - } - } - if (VMState > 0) { - throw new IllegalStateException(); - } - synchronized (hooksList) { - hooksList.addElement((Object) hook); - } - } - - /** - * - * Support for removeShutdownHook(Thread) from Runtime class - * - */ - - static boolean removeShutdownHook(Thread hook) throws IllegalStateException { - if (VMState > 0) { - throw new IllegalStateException(); - } - synchronized (hooksList) { - return hooksList == null ? false : hooksList.removeElement((Object) hook); - } - } - - /** - * - * Support for halt(int) from Runtime class - * - */ - - static void halt(int status) { - VMExecutionEngine.exit(status, false); - } - } - - //-------------------------------------------------------------------------------- // Nested protected Runtime.SubProcess class: //-------------------------------------------------------------------------------- @@ -202,19 +71,16 @@ /** * Constructs a new SubInputStream instance. - **/ + */ SubInputStream() { this.streamHandle = -1; } /** - * * Reads the next byte of data from the input stream.... * - * See: - * int read() from InputStream - * - **/ + * @see int read() from InputStream + */ private final native int readInputByte0(long handle) throws IOException; public final int read() throws IOException { @@ -222,15 +88,12 @@ } /** - * * Returns the number of bytes that can be read (or skipped over) from * this input stream without blocking by the next caller * of a method for this input stream... * - * See: - * int available() from InputStream - * - **/ + * @see int available() from InputStream + */ private final native int available0(long handle); public final int available() throws IOException { @@ -238,14 +101,10 @@ } /** - * * Reads len bytes from input stream ... * - * See: - * void read(byte[], int, int) from InputStream - * - **/ - + * @see void read(byte[], int, int) from InputStream + */ public int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); @@ -284,14 +143,11 @@ } /** - * * Closes this input stream and releases any system resources associated * with the stream. * - * See: - * void close() from InputStream - * - **/ + * @see void close() from InputStream + */ private final native void close0(long handle) throws IOException; public final synchronized void close() throws IOException { @@ -308,32 +164,24 @@ //-------------------------------------------------------------------------------- /** - * * Extends OutputStream class. - * - * - **/ - + */ final static class SubOutputStream extends OutputStream { long streamHandle; /** * Constructs a new SubOutputStream instance. - **/ + */ SubOutputStream() { this.streamHandle = -1; } /** - * * Writes the specified byte to this output stream ... * - * See: - * void write(int) from OutputStream - * - **/ - + * @see void write(int) from OutputStream + */ private final native void writeOutputByte0(long handle, int bt); public final void write(int b) throws IOException { @@ -341,15 +189,11 @@ } /** - * * Writes len bytes from the specified byte array starting at * offset off to this output stream ... * - * See: - * void write(byte[], int, int) from OutputStream - * - **/ - + * @see void write(byte[], int, int) from OutputStream + */ private final native void writeOutputBytes0(long handle, byte[] b, int off, int len); public final void write(byte[] b, int off, int len) throws IOException { @@ -365,28 +209,20 @@ } /** - * * Writes b.length bytes from the specified byte array to this output stream... * - * See: - * void write(byte[]) from OutputStream - * - **/ - + * @see void write(byte[]) from OutputStream + */ public final void write(byte[] b) throws IOException { write(b, 0, b.length); } /** - * * Flushes this output stream and forces any buffered output * bytes to be written out ... * - * See: - * void flush() from OutputStream - * - **/ - + * @see void flush() from OutputStream + */ private final native void flush0(long handle); public final void flush() throws IOException { @@ -394,15 +230,11 @@ } /** - * * Closes this output stream and releases any system resources * associated with this stream ... * - * See: - * void close() from OutputStream - * - **/ - + * @see void close() from OutputStream + */ private final native void close0(long handle); public final synchronized void close() throws IOException { @@ -424,7 +256,10 @@ private SubProcess.SubInputStream is; private SubProcess.SubInputStream es; - protected SubProcess() { // An application cannot create its own instance of this class. + /** + * An application cannot create its own instance of this class. + */ + protected SubProcess() { this.processHandle = -1; this.processExitCode = 0; this.os = null; @@ -440,34 +275,22 @@ } /** - * - * See: - * OutputStream getOutputStream() from Process - * - **/ - + * @see OutputStream.getOutputStream() from Process + */ public final OutputStream getOutputStream() { return os; } /** - * - * See: - * InputStream getInputStream() from Process - * - **/ - + * @see InputStream.getInputStream() from Process + */ public final InputStream getInputStream() { return is; } /** - * - * See: - * InputStream getErrorStream() from Process - * - **/ - + * @see InputStream getErrorStream() from Process + */ public final InputStream getErrorStream() { return es; } @@ -504,12 +327,8 @@ } /** - * - * See: - * int waitFor() from Process - * - **/ - + * @seeint waitFor() from Process + */ public int waitFor() throws InterruptedException { while (true) { synchronized (this) { @@ -522,12 +341,8 @@ } /** - * - * See: - * int exitValue() from Process - * - **/ - + * @see int exitValue() from Process + */ public synchronized int exitValue() throws IllegalThreadStateException { if (!getState0(processHandle)) { throw new IllegalThreadStateException("process has not exited"); @@ -537,12 +352,8 @@ } /** - * - * See: - * void destroy() from Process - * - **/ - + * @see void destroy() from Process + */ private final native void destroy0(int thisProcessHandle); public synchronized final void destroy() { @@ -555,127 +366,175 @@ ////////////////////////////////////////// RUNTIME BODY //////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// - private static Runtime thisApplicationRuntime = new Runtime(); // "Every Java application has a single instance of class Runtime ..." + /** + * "Every Java application has a single instance of class Runtime ..." + */ + private static Runtime thisApplicationRuntime = new Runtime(); - private Runtime() { // "An application cannot create its own instance of this class." + private static ArrayList hooksList = new ArrayList(); + + /** + * 0 - normal work + * 1 - being shutdown sequence running + * 2 - being finalizing + */ + private static int VMState = 0; + + static boolean finalizeOnExit = false; + + /** + * An application cannot create its own instance of this class. + */ + private Runtime() { } /** - * * @com.intel.drl.spec_ref - * */ - public static Runtime getRuntime() { return thisApplicationRuntime; } + void execShutdownSequence() { + synchronized (hooksList) { + if (VMState > 0) { + return; + } + try { + // Phase1: Execute all registered hooks. + VMState = 1; + for (int i = 0; i < hooksList.size(); i++) { + ((Thread)hooksList.get(i)).start(); + } + + for (int i = 0; i < hooksList.size(); i++) { + while (true){ + try { + ((Thread)hooksList.get(i)).join(); + break; + } catch (InterruptedException e) { + continue; + } + } + } + // Phase2: Execute all finalizers if nessesary. + VMState = 2; + FinalizerThread.shutdown(finalizeOnExit); + + // Close connections. + if (VM.closeJars) { + JarURLConnection.closeCachedFiles(); + } + + // Delete files. + if (VM.deleteOnExit) { + DeleteOnExit.deleteOnExit(); + } + } catch (Throwable e) { + // just catch all exceptions + } + } + } + /** - * * @com.intel.drl.spec_ref - * */ - public void exit(int status) throws SecurityException { - SecurityManager currentSecurity = System.getSecurityManager(); - - if (currentSecurity != null) { - currentSecurity.checkExit(status); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkExit(status); } - ShutdownVM.exit(status); + // Halt the VM if it is running finalizers. + if (VMState == 2 && finalizeOnExit == true && status != 0) { + halt(status); + } + + execShutdownSequence(); + // No need to invoke finalizers one more time. + // vvvvv + VMExecutionEngine.exit(status, false); } /** - * * @com.intel.drl.spec_ref - * */ - public void addShutdownHook(Thread hook) { - SecurityManager currentSecurity = System.getSecurityManager(); - - if (currentSecurity != null) { - currentSecurity.checkPermission(new RuntimePermission("shutdownHooks")); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(RuntimePermissionCollection.SHUTDOWN_HOOKS_PERMISSION); } - - ShutdownVM.addShutdownHook(hook); + if (hook == null || hook.getState() != Thread.State.NEW) { + throw new IllegalArgumentException(); + } + if (VMState > 0) { + throw new IllegalStateException(); + } + synchronized (hooksList) { + if (hooksList.contains((Object) hook)) { + throw new IllegalArgumentException(); + } + hooksList.add((Object) hook); + } } /** - * * @com.intel.drl.spec_ref - * */ - public boolean removeShutdownHook(Thread hook) { - SecurityManager currentSecurity = System.getSecurityManager(); - - if (currentSecurity != null) { - currentSecurity.checkPermission(new RuntimePermission("shutdownHooks")); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(RuntimePermissionCollection.SHUTDOWN_HOOKS_PERMISSION); } - - return ShutdownVM.removeShutdownHook(hook); + if (VMState > 0) { + throw new IllegalStateException(); + } + synchronized (hooksList) { + return hook == null ? false : hooksList.remove((Object) hook); + } } /** - * * @com.intel.drl.spec_ref - * */ - public void halt(int status) { - SecurityManager currentSecurity = System.getSecurityManager(); + SecurityManager sm = System.getSecurityManager(); - if (currentSecurity != null) { - currentSecurity.checkExit(status); - + if (sm != null) { + sm.checkExit(status); } - - ShutdownVM.halt(status); + VMExecutionEngine.exit(status, false); } /** - * * @com.intel.drl.spec_ref - * */ - public static void runFinalizersOnExit(boolean value) { - SecurityManager currentSecurity = System.getSecurityManager(); - - if (currentSecurity != null) { - currentSecurity.checkExit(0); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkExit(0); } - - ShutdownVM.runFinalizersOnExit(value); + synchronized(hooksList) { + finalizeOnExit = value; + } } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String command) throws IOException { return exec(command, null, null); } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String cmd, String[] envp) throws IOException { return exec(cmd, envp, null); } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String command, String[] envp, File dir) throws IOException { if (command == null) { throw new NullPointerException(); @@ -709,33 +568,24 @@ } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String[] cmdarray) throws IOException { return exec(cmdarray, null, null); } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String[] cmdarray, String[] envp) throws IOException, NullPointerException, IndexOutOfBoundsException, SecurityException { return exec(cmdarray, envp, null); } /** - * * @com.intel.drl.spec_ref - * */ - public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException { SecurityManager currentSecurity = System.getSecurityManager(); @@ -777,92 +627,64 @@ } /** - * * @com.intel.drl.spec_ref - * */ - public int availableProcessors() { return VMExecutionEngine.getAvailableProcessors(); } /** - * * @com.intel.drl.spec_ref - * */ - public long freeMemory() { return VMMemoryManager.getFreeMemory(); } /** - * * @com.intel.drl.spec_ref - * */ - public long totalMemory() { return VMMemoryManager.getTotalMemory(); } /** - * * @com.intel.drl.spec_ref - * */ - public long maxMemory() { return VMMemoryManager.getMaxMemory(); } /** - * * @com.intel.drl.spec_ref - * */ - public void gc() { VMMemoryManager.runGC(); } /** - * * @com.intel.drl.spec_ref - * */ - public void runFinalization() { - //VMMemoryManager.runFinalzation(); VMMemoryManager.runFinalization(); } /** - * * @com.intel.drl.spec_ref - * */ - public void traceInstructions(boolean on) { VMExecutionEngine.traceInstructions(on); } /** - * * @com.intel.drl.spec_ref - * */ - public void traceMethodCalls(boolean on) { VMExecutionEngine.traceMethodCalls(on); } /** - * * @com.intel.drl.spec_ref - * */ - public void load(String filename) throws SecurityException, UnsatisfiedLinkError { load0(filename, VMClassRegistry.getClassLoader(VMStack.getCallerClass(0)), true); } @@ -883,11 +705,8 @@ } /** - * * @com.intel.drl.spec_ref - * */ - public void loadLibrary(String libname) throws SecurityException, UnsatisfiedLinkError { loadLibrary0(libname, VMClassRegistry.getClassLoader(VMStack.getCallerClass(0)), true); } @@ -972,22 +791,16 @@ } /** - * * @com.intel.drl.spec_ref - * */ - public InputStream getLocalizedInputStream(InputStream in) { //XXX: return new BufferedInputStream( (InputStream) (Object) new InputStreamReader( in ) ); return in; } /** - * * @com.intel.drl.spec_ref - * */ - public OutputStream getLocalizedOutputStream(OutputStream out) { //XXX: return new BufferedOutputStream( (OutputStream) (Object) new OutputStreamWriter( out ) ); return out; Index: trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java =================================================================== --- trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java (working copy) @@ -384,6 +384,13 @@ } /** + * Initiaies the VM shutdown sequence. + */ + static void execShutdownSequence() { + Runtime.getRuntime().execShutdownSequence(); + } + + /** * Sets the value of err field without any security checks */ private static native void setErrUnsecure(PrintStream err); Index: trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java =================================================================== --- trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (working copy) @@ -26,14 +26,11 @@ import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; + /** - * This class is a VM start point. - * It does following steps:
    - *
  • starts all helper threads as Finalizer and Execution Manager threads. - *
  • parse system properties and configure VM environment. - *
  • load main class and start main method in new thread. - *
  • catch Throwable. - *
  • call System.exit(), to execute shutdown hooks + * This class does the following: + *
  • starts Finalizer and Execution Manager helper threads. + *
  • parses system properties and configure VM environment. *
*/ class VMStart { @@ -58,7 +55,7 @@ } catch (Throwable e) { System.err.println("Internal error"); e.printStackTrace(System.err); - Runtime.getRuntime().halt(-1); + Runtime.getRuntime().halt(1); } } // should shutdown helper threads @@ -69,7 +66,6 @@ } public void run() { - FinalizerThread.shutdown(); EMThreadSupport.shutdown(); } } Index: trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java =================================================================== --- trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java (working copy) @@ -21,15 +21,12 @@ package org.apache.harmony.kernel.vm; -import org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection; -import org.apache.harmony.luni.util.DeleteOnExit; - import org.apache.harmony.vm.VMStack; public final class VM { - private static boolean closeJars = false; - private static boolean deleteOnExit = false; + public static boolean closeJars = false; + public static boolean deleteOnExit = false; private VM() { } @@ -89,15 +86,7 @@ * 2) We've proposed another approach to perform shutdown actions. */ public static void closeJars() { - class CloseJarsHook implements Runnable { - public void run() { - JarURLConnection.closeCachedFiles(); - } - } - if (!closeJars) { - closeJars = true; - Runtime.getRuntime().addShutdownHook(new Thread(new CloseJarsHook())); - } + closeJars = true; } /** @@ -105,15 +94,7 @@ * 2) We've proposed another approach to perform shutdown actions. */ public static void deleteOnExit() { - class DeleteOnExitHook implements Runnable { - public void run() { - DeleteOnExit.deleteOnExit(); - } - } - if (!deleteOnExit) { - deleteOnExit = true; - Runtime.getRuntime().addShutdownHook(new Thread(new DeleteOnExitHook())); - } + deleteOnExit = true; } /** Index: trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp =================================================================== --- trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp (working copy) @@ -50,32 +50,15 @@ /* * Class: java_lang_VMExecutionEngine * Method: exit - * Signature: (IZ)V - */ -// FixME: should be removed -//JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit -JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ - (JNIEnv *, jclass, jint status, jboolean) -{ - // ToDo: process jboolean - vm_exit(status); -} - -/* - * Class: java_lang_VMExecutionEngine - * Method: exit * Signature: (IZ[Ljava/lang/Runnable;)V */ -JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ_3Ljava_lang_Runnable_2 - (JNIEnv *, jclass, jint status, jboolean, jobjectArray) +JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit + (JNIEnv * jni_env, jclass, jint status, jboolean needFinalization, jobjectArray) { - // ToDo: process jboolean // ToDo: process jobjectArray - vm_exit(status); + _exit(status); } - - /* * Class: java_lang_VMExecutionEngine * Method: getAssertionStatus Index: trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.h =================================================================== --- trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.h (revision 476066) +++ trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.h (working copy) @@ -42,15 +42,10 @@ /* Native methods */ /* - * Method: java.lang.VMExecutionEngine.exit(IZ[Ljava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ - (JNIEnv *, jclass, jint, jboolean); - /* * Method: java.lang.VMExecutionEngine.exit(IZ[Ljava/lang/Runnable;)V */ -JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ_3Ljava_lang_Runnable_2 +JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit (JNIEnv *, jclass, jint, jboolean, jobjectArray); /* Index: trunk/vm/vmcore/src/object/object_handles.cpp =================================================================== --- trunk/vm/vmcore/src/object/object_handles.cpp (revision 476066) +++ trunk/vm/vmcore/src/object/object_handles.cpp (working copy) @@ -207,6 +207,7 @@ ObjectHandle oh_allocate_global_handle() { + Global_Env * vm_env = VM_Global_State::loader_env; // Allocate and init handle ObjectHandlesOld* h = oh_allocate_object_handle(); //(ObjectHandlesOld*)m_malloc(sizeof(ObjectHandlesOld)); @@ -214,14 +215,14 @@ h->allocated_on_the_stack = false; hythread_suspend_disable(); // ----------------vvv - p_handle_lock->_lock(); + vm_env->p_handle_lock->_lock(); // Insert at beginning of globals list h->prev = NULL; h->next = global_object_handles; global_object_handles = h; if(h->next) h->next->prev = h; - p_handle_lock->_unlock(); + vm_env->p_handle_lock->_unlock(); hythread_suspend_enable(); //--------------------------------------------^^^ return &h->handle; } //vm_create_global_object_handle @@ -235,8 +236,10 @@ void oh_deallocate_global_handle(ObjectHandle handle) { + Global_Env * vm_env = VM_Global_State::loader_env; + tmn_suspend_disable(); // ----------vvv - p_handle_lock->_lock(); + vm_env->p_handle_lock->_lock(); assert(is_global_handle(handle)); handle->object = NULL; @@ -245,7 +248,7 @@ if (h->prev) h->prev->next = h->next; if (h==global_object_handles) global_object_handles = h->next; - p_handle_lock->_unlock(); + vm_env->p_handle_lock->_unlock(); tmn_suspend_enable(); // -------------------------------------^^^ STD_FREE(h); } //vm_delete_global_object_handle Index: trunk/vm/vmcore/src/object/vm_arrays.cpp =================================================================== --- trunk/vm/vmcore/src/object/vm_arrays.cpp (revision 476066) +++ trunk/vm/vmcore/src/object/vm_arrays.cpp (working copy) @@ -32,7 +32,6 @@ #include "object_handles.h" #include "object_layout.h" #include "vm_arrays.h" -#include "vm_synch.h" #include "open/vm_util.h" #include "vm_stats.h" Index: trunk/vm/vmcore/src/thread/lock_manager.cpp =================================================================== --- trunk/vm/vmcore/src/thread/lock_manager.cpp (revision 476066) +++ trunk/vm/vmcore/src/thread/lock_manager.cpp (working copy) @@ -24,27 +24,11 @@ #include "lock_manager.h" #include "vm_threads.h" #include "exceptions.h" -#include "vm_synch.h" //void vm_thread_enumerate_from_native(VM_thread *thread); // unused anywhere - -Lock_Manager *p_jit_a_method_lock; -Lock_Manager *p_vtable_patch_lock; -Lock_Manager *p_meth_addr_table_lock; -Lock_Manager *p_thread_lock; -Lock_Manager *p_method_call_lock; -Lock_Manager *p_handle_lock; extern hythread_library_t hythread_lib; -VMEXPORT void jit_lock() { - p_jit_a_method_lock->_lock(); -} - -VMEXPORT void jit_unlock() { - p_jit_a_method_lock->_unlock(); -} - Lock_Manager::Lock_Manager() { UNREF IDATA stat = hymutex_create (&lock, TM_MUTEX_NESTED); Index: trunk/vm/vmcore/src/thread/mon_enter_exit.cpp =================================================================== --- trunk/vm/vmcore/src/thread/mon_enter_exit.cpp (revision 476066) +++ trunk/vm/vmcore/src/thread/mon_enter_exit.cpp (working copy) @@ -46,7 +46,6 @@ #include "thread_generic.h" #include "object_generic.h" -#include "vm_synch.h" #include "vm_stats.h" #include "object_handles.h" Index: trunk/vm/vmcore/src/thread/thread_generic.cpp =================================================================== --- trunk/vm/vmcore/src/thread/thread_generic.cpp (revision 476066) +++ trunk/vm/vmcore/src/thread/thread_generic.cpp (working copy) @@ -62,7 +62,6 @@ #include "m2n.h" #include "exceptions.h" #include "jit_intf.h" -#include "vm_synch.h" #include "exception_filter.h" #include "vm_threads.h" #include "jni_utils.h" Index: trunk/vm/vmcore/src/thread/thread_manager.cpp =================================================================== --- trunk/vm/vmcore/src/thread/thread_manager.cpp (revision 476066) +++ trunk/vm/vmcore/src/thread/thread_manager.cpp (working copy) @@ -45,7 +45,6 @@ #include "open/vm_util.h" #include "nogc.h" #include "sync_bits.h" -#include "vm_synch.h" #include "lock_manager.h" #include "thread_manager.h" Index: trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp =================================================================== --- trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp (working copy) @@ -58,7 +58,6 @@ #include "open/gc.h" #include "open/vm_util.h" -#include "vm_synch.h" #include "vm_threads.h" #include "ini.h" #include "type.h" Index: trunk/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp =================================================================== --- trunk/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp (working copy) @@ -31,7 +31,6 @@ #include -#include "vm_synch.h" #include "open/vm_util.h" #include "encoder.h" #include "nogc.h" Index: trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp =================================================================== --- trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (working copy) @@ -40,7 +40,6 @@ #include "open/thread_helpers.h" #include "vm_arrays.h" -#include "vm_synch.h" #include "vm_strings.h" #include "ini.h" #include "nogc.h" Index: trunk/vm/vmcore/src/util/ipf/base/arithmetic_helpers_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/ipf/base/arithmetic_helpers_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ipf/base/arithmetic_helpers_ipf.cpp (working copy) @@ -40,7 +40,6 @@ #include "environment.h" #include "method_lookup.h" #include "exceptions.h" -#include "vm_synch.h" #include "open/gc.h" #include "ini.h" #include "open/vm_util.h" Index: trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp (working copy) @@ -57,7 +57,6 @@ #include "nogc.h" #include "open/gc.h" #include "open/vm_util.h" -#include "vm_synch.h" #include "vm_threads.h" #include "ini.h" Index: trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp (working copy) @@ -40,7 +40,6 @@ #include "../m2n_ipf_internal.h" #include "object_layout.h" #include "open/vm_util.h" -#include "vm_synch.h" #include "vm_threads.h" #include "jit_intf.h" #include "jit_intf_cpp.h" Index: trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp (working copy) @@ -40,7 +40,6 @@ #include "exceptions.h" #include "vm_threads.h" -#include "vm_synch.h" #include "compile.h" #include "open/vm_util.h" Index: trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp (working copy) @@ -56,7 +56,6 @@ #include "vm_strings.h" #include "vm_arrays.h" #include "vm_threads.h" -#include "vm_synch.h" #include "port_malloc.h" #include "jni_utils.h" // This is for readInternal override Index: trunk/vm/vmcore/src/util/linux/signals_em64t.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_em64t.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/linux/signals_em64t.cpp (working copy) @@ -56,11 +56,9 @@ #include "exceptions.h" #include "exceptions_jit.h" -#include "vm_synch.h" #include "vm_threads.h" #include "open/vm_util.h" #include "compile.h" -#include "vm_synch.h" #include "vm_stats.h" #include "sync_bits.h" @@ -386,9 +384,7 @@ return; } - if (env->shutting_down != 0) { - fprintf(stderr, "null_java_reference_handler(): called in shutdown stage\n"); - } else if (!interpreter_enabled()) { + if (!interpreter_enabled()) { if (java_throw_from_sigcontext( uc, env->java_lang_NullPointerException_Class)) { return; @@ -405,9 +401,7 @@ ucontext_t *uc = (ucontext_t *)context; Global_Env *env = VM_Global_State::loader_env; - if (env->shutting_down != 0) { - fprintf(stderr, "null_java_divide_by_zero_handler(): called in shutdown stage\n"); - } else if (!interpreter_enabled()) { + if (!interpreter_enabled()) { if (java_throw_from_sigcontext( uc, env->java_lang_ArithmeticException_Class)) { return; @@ -425,14 +419,6 @@ void yield_other_handler(int signum, siginfo_t* info, void* context) { - if (VM_Global_State::loader_env->shutting_down != 0) { - // Too late for this kind of signals - fprintf(stderr, "yield_other_handler(): called in shutdown stage\n"); - - // crash with default handler - signal(signum, 0); - } - VM_thread* thread = p_active_threads_list; pthread_t self = GetCurrentThreadId(); TRACE2("SIGNALLING", "get_context_handler, try to find pthread_t " << self); Index: trunk/vm/vmcore/src/util/linux/signals_ia32.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (working copy) @@ -57,11 +57,9 @@ #include "exceptions.h" #include "exceptions_jit.h" -#include "vm_synch.h" #include "vm_threads.h" #include "open/vm_util.h" #include "compile.h" -#include "vm_synch.h" #include "vm_stats.h" #include "sync_bits.h" @@ -486,9 +484,7 @@ return; } - if (env->shutting_down != 0) { - fprintf(stderr, "null_java_reference_handler(): called in shutdown stage\n"); - } else if (!interpreter_enabled()) { + if (!interpreter_enabled()) { if (java_throw_from_sigcontext( uc, env->java_lang_NullPointerException_Class)) { return; @@ -511,9 +507,7 @@ TRACE2("signals", "ArithmeticException detected at " << (void *)uc->uc_mcontext.gregs[REG_EIP]); - if (env->shutting_down != 0) { - fprintf(stderr, "null_java_divide_by_zero_handler(): called in shutdown stage\n"); - } else if (!interpreter_enabled()) { + if (!interpreter_enabled()) { if (java_throw_from_sigcontext( uc, env->java_lang_ArithmeticException_Class)) { return; @@ -657,16 +651,6 @@ void yield_other_handler(int signum, siginfo_t* info, void* context) { // FIXME: integration, should be moved to port or OpenTM - Global_Env *env = VM_Global_State::loader_env; - if (env->shutting_down != 0) { - // Too late for this kind of signals - // crash with default handle. - fprintf(stderr, "yield_other_handler(): called in shut down stage\n"); - signal(signum, 0); - return; - } - - VM_thread* thread = p_active_threads_list; pthread_t self = GetCurrentThreadId(); TRACE2("SIGNALLING", "get_context_handler, try to find pthread_t " << self); Index: trunk/vm/vmcore/src/util/linux/signals_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (working copy) @@ -56,11 +56,9 @@ #include "open/gc.h" #include "exceptions.h" -#include "vm_synch.h" #include "vm_threads.h" #include "open/vm_util.h" #include "compile.h" -#include "vm_synch.h" #include "vm_stats.h" #include "sync_bits.h" @@ -488,13 +486,6 @@ void null_java_reference_handler(int signum) { - if (VM_Global_State::loader_env->shutting_down != 0) { - fprintf(stderr, "null_java_reference_handler(): called in shutdown stage\n"); - - // crash with default handler - signal(signum, 0); - } - uint32* top_ebp = NULL; //TODO: ADD correct stack handling here!! Global_Env *env = VM_Global_State::loader_env; @@ -504,13 +495,6 @@ void null_java_divide_by_zero_handler(int signum) { - if (VM_Global_State::loader_env->shutting_down != 0) { - fprintf(stderr, "null_java_divide_by_zero_handler(): called in shutdown stage\n"); - - // crash with default handler - signal(signum, 0); - } - uint32* top_ebp = NULL; //TODO: ADD correct stack handling here!! Global_Env *env = VM_Global_State::loader_env; Index: trunk/vm/vmcore/src/util/win/em64t/nt_exception_filter.cpp =================================================================== --- trunk/vm/vmcore/src/util/win/em64t/nt_exception_filter.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/win/em64t/nt_exception_filter.cpp (working copy) @@ -25,7 +25,6 @@ #include "Environment.h" #include "gc_for_vm.h" #include "exceptions.h" -#include "vm_synch.h" #include "method_lookup.h" #include "vm_strings.h" #include "vm_threads.h" Index: trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp =================================================================== --- trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp (working copy) @@ -28,8 +28,6 @@ #include "stack_dump.h" #include "jvmti_break_intf.h" -#include "m2n.h" - // Windows specific #include #include @@ -302,92 +300,44 @@ bool run_default_handler = true; PCONTEXT context = nt_exception->ContextRecord; - - if (VM_Global_State::loader_env->shutting_down == 0) { - - TRACE2("signals", "VEH received an exception: code = 0x" << - ((void*)nt_exception->ExceptionRecord->ExceptionCode) << - " location IP = 0x" << ((void*)context->Eip)); - - // this filter catches _all_ hardware exceptions including those caused by - // VM internal code. To elimate confusion over what caused the - // exception, we first make sure the exception was thrown inside a Java - // method else crash handler or default handler is executed, this means that - // it was thrown by VM C/C++ code. - if (((code == STATUS_ACCESS_VIOLATION || - code == STATUS_INTEGER_DIVIDE_BY_ZERO || - code == STATUS_STACK_OVERFLOW) && - vm_identify_eip((void *)context->Eip) == VM_TYPE_JAVA) || - code == JVMTI_EXCEPTION_STATUS) - { + + TRACE2("signals", "VEH received an exception: code = 0x" << + ((void*)nt_exception->ExceptionRecord->ExceptionCode) << + " location IP = 0x" << ((void*)context->Eip)); + + // this filter catches _all_ hardware exceptions including those caused by + // VM internal code. To elimate confusion over what caused the + // exception, we first make sure the exception was thrown inside a Java + // method else crash handler or default handler is executed, this means that + // it was thrown by VM C/C++ code. + if (((code == STATUS_ACCESS_VIOLATION || + code == STATUS_INTEGER_DIVIDE_BY_ZERO || + code == STATUS_STACK_OVERFLOW) && + vm_identify_eip((void *)context->Eip) == VM_TYPE_JAVA) || + code == JVMTI_EXCEPTION_STATUS) { run_default_handler = false; - } else if (code == STATUS_STACK_OVERFLOW) { - if (is_unwindable()) { - if (hythread_is_suspend_enabled()) { - tmn_suspend_disable(); - } - run_default_handler = false; - } else { - M2nFrame* frame = m2n_get_last_frame(); + } else if (code == STATUS_STACK_OVERFLOW) { + if (is_unwindable()) { + if (hythread_is_suspend_enabled()) { + tmn_suspend_disable(); + } + run_default_handler = false; + } else { Global_Env *env = VM_Global_State::loader_env; exn_raise_by_class(env->java_lang_StackOverflowError_Class); - p_TLS_vmthread->restore_guard_page = true; - return EXCEPTION_CONTINUE_EXECUTION; - } + p_TLS_vmthread->restore_guard_page = true; + return EXCEPTION_CONTINUE_EXECUTION; } - - } else { - if (VM_Global_State::loader_env->shutting_down > 1) { - // Deadly errors in shutdown. - fprintf(stderr, "SEH handler: too many shutdown errors"); - return EXCEPTION_CONTINUE_SEARCH; - } else { - fprintf(stderr, "SEH handler: shutdown error"); - } } if (run_default_handler) { - const char *msg = 0; - switch (code) { - // list of errors we can handle: - case STATUS_ACCESS_VIOLATION: msg = "ACCESS_VIOLATION"; break; - case STATUS_INTEGER_DIVIDE_BY_ZERO: msg = "INTEGER_DIVIDE_BY_ZERO"; break; - case STATUS_PRIVILEGED_INSTRUCTION: msg = "PRIVILEGED_INSTRUCTION"; break; - case STATUS_SINGLE_STEP: msg = "SINGLE_STEP"; break; - case STATUS_BREAKPOINT: msg = "BREAKPOINT"; break; - case STATUS_ILLEGAL_INSTRUCTION: msg = "ILLEGAL_INSTRUCTION"; break; - case STATUS_GUARD_PAGE_VIOLATION: msg = "GUARD_PAGE_VIOLATION"; break; - case STATUS_INVALID_HANDLE: msg = "INVALID_HANDLE"; break; - case STATUS_DATATYPE_MISALIGNMENT: msg = "DATATYPE_MISALIGNMENT"; break; - case STATUS_FLOAT_INVALID_OPERATION: msg = "FLOAT_INVALID_OPERATION"; break; - case STATUS_NONCONTINUABLE_EXCEPTION: msg = "NONCONTINUABLE_EXCEPTION"; break; - case STATUS_STACK_OVERFLOW: msg = "STACK_OVERFLOW"; break; - case STATUS_CONTROL_C_EXIT: msg = "CONTROL_C_EXIT"; break; - case STATUS_ARRAY_BOUNDS_EXCEEDED: msg = "ARRAY_BOUNDS_EXCEEDED"; break; - case STATUS_FLOAT_DENORMAL_OPERAND: msg = "FLOAT_DENORMAL_OPERAND"; break; - case STATUS_FLOAT_INEXACT_RESULT: msg = "FLOAT_INEXACT_RESULT"; break; - case STATUS_FLOAT_OVERFLOW: msg = "FLOAT_OVERFLOW"; break; - case STATUS_FLOAT_STACK_CHECK: msg = "FLOAT_STACK_CHECK"; break; - case STATUS_FLOAT_UNDERFLOW: msg = "FLOAT_UNDERFLOW"; break; - case STATUS_INTEGER_OVERFLOW: msg = "INTEGER_OVERFLOW"; break; - case STATUS_IN_PAGE_ERROR: msg = "IN_PAGE_ERROR"; break; - case STATUS_INVALID_DISPOSITION: msg = "INVALID_DISPOSITION"; break; - - default: - return EXCEPTION_CONTINUE_SEARCH; +#ifndef NDEBUG + if (vm_get_boolean_property_value_with_default("vm.assert_dialog")) { + if (UnhandledExceptionFilter(nt_exception) == EXCEPTION_CONTINUE_SEARCH) { + DebugBreak(); + } } - - - - VM_Global_State::loader_env->shutting_down++; - - if (!vm_get_boolean_property_value_with_default("vm.assert_dialog")) { - print_state(nt_exception, msg); - - print_callstack(nt_exception); - LOGGER_EXIT(-1); - - } +#endif return EXCEPTION_CONTINUE_SEARCH; } @@ -461,6 +411,7 @@ uint32 exception_esp = regs.esp; DebugUtilsTI* ti = VM_Global_State::loader_env->TI; + // TODO: We already checked that above. Is it possible to reuse the result? bool java_code = (vm_identify_eip((void *)regs.eip) == VM_TYPE_JAVA); exn_athrow_regs(®s, exc_clss, java_code); Index: trunk/vm/vmcore/src/util/win/ipf/nt_exception_filter.cpp =================================================================== --- trunk/vm/vmcore/src/util/win/ipf/nt_exception_filter.cpp (revision 476066) +++ trunk/vm/vmcore/src/util/win/ipf/nt_exception_filter.cpp (working copy) @@ -23,7 +23,6 @@ #include "Class.h" #include "Environment.h" #include "exceptions.h" -#include "vm_synch.h" #include "method_lookup.h" #include "vm_strings.h" #include "vm_threads.h" Index: trunk/vm/vmstart/src/compmgr/component_manager_impl.cpp =================================================================== --- trunk/vm/vmstart/src/compmgr/component_manager_impl.cpp (revision 476066) +++ trunk/vm/vmstart/src/compmgr/component_manager_impl.cpp (working copy) @@ -384,7 +384,7 @@ ComponentInfoHandle component_info = component_manager_impl->components; while (NULL != component_info) { ComponentInfoHandle component_info_next = component_info->next; - ret_new = FreeComponentInfo(component_info_next); + ret_new = FreeComponentInfo(component_info); if (APR_SUCCESS == ret) { ret = ret_new; }