Index: trunk/vm/interpreter/src/interpreter.cpp =================================================================== --- trunk/vm/interpreter/src/interpreter.cpp (revision 487462) +++ trunk/vm/interpreter/src/interpreter.cpp (working copy) @@ -2392,11 +2392,10 @@ static inline void -stackDump(StackFrame& frame) { +stackDump(FILE * file, StackFrame& frame) { StackFrame *f = &frame; - ECHO("****** STACK DUMP: ************"); while(f) { Method *m = f->method; Class *c = m->get_class(); @@ -2406,35 +2405,21 @@ line = m->get_line_number((uint16)ip); } #ifdef INTERPRETER_DEEP_DEBUG - ECHO(c->name->bytes << "." - << m->get_name()->bytes - << m->get_descriptor()->bytes << " (" - << class_get_source_file_name(c) << ":" - << line << ")" - << " last bcs: (8 of " << f->n_last_bytecode << "): " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-1)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-2)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-3)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-4)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-5)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-6)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-7)&7]] << " " - << opcodeNames[f->last_bytecodes[ - (f->n_last_bytecode-8)&7]]); + fprintf(file, "%s.%s%s (%s:%i) last bcs: (8 of %i): %s %s %s %s %s %s %s %s", + c->name->bytes, m->get_name()->bytes, m->get_descriptor()->bytes, + class_get_source_file_name(c), line, f->n_last_bytecode, + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-1)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-2)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-3)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-4)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-5)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-6)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-7)&7]], + opcodeNames[f->last_bytecodes[(f->n_last_bytecode-8)&7]]); #else const char *filename = class_get_source_file_name(c); - ECHO(class_get_name(c) << "." - << m->get_name()->bytes - << m->get_descriptor()->bytes << " (" - << (filename != NULL ? filename : "NULL") << ":" - << line << ")"); + fprintf(file, " %s.%s%s (%s:%i)\n", class_get_name(c), m->get_name()->bytes, + m->get_descriptor()->bytes, (filename != NULL ? filename : "NULL"), line); #endif f = f->prev; } @@ -2442,15 +2427,14 @@ void stack_dump(VM_thread *thread) { StackFrame *frame = getLastStackFrame(thread); - stackDump(*frame); + stackDump(stdout, *frame); } void stack_dump() { StackFrame *frame = getLastStackFrame(); - stackDump(*frame); + stackDump(stdout, *frame); } - static inline void UNUSED dump_all_java_stacks() { hythread_iterator_t iterator; @@ -2973,14 +2957,14 @@ case OPCODE_RET: Opcode_WIDE_RET(frame); break; default: DEBUG2("wide bytecode 0x" << hex << (int)*ip1 << " not implemented\n"); - stackDump(frame); + stackDump(stdout, frame); ABORT("Unexpected wide bytecode"); } break; } default: DEBUG2("bytecode 0x" << hex << (int)ip0 << " not implemented\n"); - stackDump(frame); + stackDump(stdout, frame); ABORT("Unexpected bytecode"); } assert(&frame == getLastStackFrame()); @@ -2991,6 +2975,20 @@ if (frame.exc == 0) continue; got_exception: assert(&frame == getLastStackFrame()); + + if (VM_Global_State::loader_env->IsVmShutdowning()) { + assert(!hythread_is_suspend_enabled()); + assert(exn_raised()); + if (frame.locked_monitors) { + M2N_ALLOC_MACRO; + vm_monitor_exit_wrapper(frame.locked_monitors->monitor); + M2N_FREE_MACRO; + assert(!frame.locked_monitors->next); + } + M2N_FREE_MACRO; + return; + } + clear_current_thread_exception(); if (interpreter_ti_notification_mode) { Index: trunk/vm/jitrino/src/jet/jet.cpp =================================================================== --- trunk/vm/jitrino/src/jet/jet.cpp (revision 487462) +++ trunk/vm/jitrino/src/jet/jet.cpp (working copy) @@ -283,7 +283,6 @@ {"stats", "type: bool; default: off; scope: global \n" "Collects and shows various statistics about compiled methods. \n" - "Note: you may need to pass -XcleanupOnExit to VM to view the stats. \n" }, #endif // ~JIT_STATS Index: trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp =================================================================== --- trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp (revision 487462) +++ trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp (working copy) @@ -25,6 +25,7 @@ #include "open/types.h" #include "port_malloc.h" #include "vm_threads.h" +#include "exceptions.h" #include "m2n.h" #include "encoder.h" @@ -313,37 +314,58 @@ return buf; } +static void m2n_pop_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); + free_local_object_handles2(m2n->local_object_handles); +} + +static void m2n_free_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); + free_local_object_handles3(m2n->local_object_handles); +} + char * m2n_gen_pop_m2n(char * buf, bool handles, unsigned num_callee_saves, int32 bytes_to_m2n_bottom, unsigned num_preserve_ret) { - assert (num_preserve_ret <= 2); - unsigned handles_offset = 2 * LcgEM64TContext::GR_SIZE + bytes_to_m2n_bottom; - if (handles) { - if (num_preserve_ret > 0) { - // Save return value - assert(LcgEM64TContext::GR_SIZE == 8); - handles_offset += LcgEM64TContext::GR_SIZE; - buf = push(buf, rax_opnd, size_64); - if (num_preserve_ret > 1) { - handles_offset += LcgEM64TContext::GR_SIZE; - buf = push(buf, rdx_opnd, size_64); - } - } + assert (num_preserve_ret <= 2); + assert(LcgEM64TContext::GR_SIZE == 8); - // Must free the handles - M_Base_Opnd m(rsp_reg, handles_offset); - buf = mov(buf, rdi_opnd, m, size_64); - buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)free_local_object_handles2), size_64); - buf = call(buf, rax_opnd, size_64); + if (num_preserve_ret > 0) { + // Save return value + // NOTE: don't break stack allignment by pushing only one register. + buf = push(buf, rax_opnd, size_64); + buf = push(buf, rdx_opnd, size_64); + } - if (num_preserve_ret > 0) { - // Restore return value - if (num_preserve_ret > 1) { - buf = pop(buf, rdx_opnd, size_64); - } - buf = pop(buf, rax_opnd, size_64); - } + if (handles) { + // There are handles located on the stack + buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)m2n_pop_local_handles), size_64); + } else { + buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)m2n_free_local_handles), size_64); } + + // NOTE: the following should be true before the call ($rsp % 8 == 0 && $rsp % 16 != 0)! + // Call m2n_pop_local_handles or m2n_free_local_handles + buf = call(buf, rax_opnd, size_64); + + if (num_preserve_ret > 0) { + // Restore return value + buf = pop(buf, rdx_opnd, size_64); + buf = pop(buf, rax_opnd, size_64); + } + // pop prev_m2nf buf = mov(buf, r10_opnd, M_Base_Opnd(rsp_reg, bytes_to_m2n_bottom), size_64); bytes_to_m2n_bottom += LcgEM64TContext::GR_SIZE; Index: trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp =================================================================== --- trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp (revision 487462) +++ trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp (working copy) @@ -19,15 +19,17 @@ * @version $Revision: 1.1.2.1.4.4 $ */ +#include "open/types.h" +#include "open/hythread.h" -#include "port_malloc.h" #include "m2n.h" #include "m2n_ia32_internal.h" +#include "port_malloc.h" #include "object_handles.h" #include "vm_threads.h" -#include "open/types.h" #include "encoder.h" #include "interpreter.h" // for asserts only +#include "exceptions.h" ////////////////////////////////////////////////////////////////////////// @@ -234,8 +236,6 @@ return buf; } -void free_local_object_handles2(ObjectHandles*); - unsigned m2n_pop_m2n_size(bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret) { unsigned size = 7+(4-num_callee_saves); @@ -245,54 +245,69 @@ return size + 128; } -void m2n_pop_local_handles() { - M2nFrame *m2n = m2n_get_last_frame(); +static void m2n_pop_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); + free_local_object_handles2(m2n->local_object_handles); +} + +static void m2n_free_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); free_local_object_handles3(m2n->local_object_handles); } char* m2n_gen_pop_m2n(char* buf, bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret) { + if (preserve_ret > 0) { + // Save return value + buf = push(buf, eax_opnd); + if (preserve_ret > 1) { + buf = push(buf, edx_opnd); + } + } + if (handles) { - // Must free the handles - unsigned handles_off = 8+extra_on_stack; - if (preserve_ret>0) { - // Save return value - handles_off += 4; - buf = push(buf, eax_opnd); - if (preserve_ret>1) { - handles_off += 4; - buf = push(buf, edx_opnd); - } - } - M_Base_Opnd m(esp_reg, handles_off); - buf = push(buf, m); - buf = call(buf, (char*)free_local_object_handles2); - Imm_Opnd imm(4); - buf = alu(buf, add_opc, esp_opnd, imm); - if (preserve_ret>0) { - // Restore return value - if (preserve_ret>1) buf = pop(buf, edx_opnd); - buf = pop(buf, eax_opnd); - } + // There are handles located on the stack + buf = call(buf, (char*)m2n_pop_local_handles); } else { - buf = push(buf, eax_opnd); - buf = push(buf, ecx_opnd); - buf = push(buf, edx_opnd); - buf = call(buf, (char*)m2n_pop_local_handles); - buf = pop(buf, edx_opnd); - buf = pop(buf, ecx_opnd); - buf = pop(buf, eax_opnd); + buf = call(buf, (char*)m2n_free_local_handles); } + if (preserve_ret > 0) { + // Restore return value + if (preserve_ret > 1) { + buf = pop(buf, edx_opnd); + } + buf = pop(buf, eax_opnd); + } + + // pop "garbage" from the stack if (extra_on_stack) { Imm_Opnd imm(extra_on_stack); buf = alu(buf, add_opc, esp_opnd, imm); } + + // Unlink the M2nFrame from the list of the current thread buf = pop(buf, esi_opnd); buf = pop(buf, ebx_opnd); buf = mov(buf, M_Base_Opnd(ebx_reg, +0), esi_opnd); buf = alu(buf, add_opc, esp_opnd, Imm_Opnd(+16)); - + + // TODO: check if there is no need to restore callee saved registers + // JUSTIFICATION: m2n frame is popped as a result of "normal" + // (opposite to destuctive) stack unwinding + // Restore callee saved general registers if (num_callee_saves<4) buf = pop(buf, edi_opnd); if (num_callee_saves<3) buf = pop(buf, esi_opnd); if (num_callee_saves<2) buf = pop(buf, ebx_opnd); Index: trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp =================================================================== --- trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp (revision 487462) +++ trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp (working copy) @@ -33,6 +33,7 @@ #include "open/vm_util.h" #include "stub_code_utils.h" #include "interpreter.h" +#include "exceptions.h" ////////////////////////////////////////////////////////////////////////// @@ -243,15 +244,34 @@ emitter->ipf_movi(M2N_OBJECT_HANDLES, (int)imm_val); } -void free_local_object_handles2(ObjectHandles* head); - void m2n_pop_local_handles() { assert(!hythread_is_suspend_enabled()); M2nFrame *m2n = m2n_get_last_frame(); free_local_object_handles3(m2n_get_local_handles(m2n)); } +static void m2n_pop_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); + free_local_object_handles2(m2n->local_object_handles); +} +static void m2n_free_local_handles() { + assert(!hythread_is_suspend_enabled()); + + if (exn_raised()) { + exn_rethrow(); + } + + M2nFrame * m2n = m2n_get_last_frame(); + free_local_object_handles3(m2n->local_object_handles); +} + void m2n_gen_pop_m2n(Merced_Code_Emitter* emitter, bool handles, M2nPreserveRet preserve_ret, bool do_alloc, unsigned out_reg, int target) { if (handles) { @@ -260,40 +280,33 @@ unsigned free_target = (unsigned) target; emitter->ipf_cmp(icmp_eq, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, M2N_OBJECT_HANDLES, 0); emitter->ipf_br(br_cond, br_many, br_spnt, br_none, free_target, SCRATCH_PRED_REG); - // Yes, save return register - if (preserve_ret==MPR_Gr) - emitter->ipf_add(6, RETURN_VALUE_REG, 0); - else if (preserve_ret==MPR_Fr) - emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16)); - // Do free - if (!out_reg) out_reg = 32+8+M2N_NUMBER_LOCALS; - emitter->ipf_add(out_reg, M2N_OBJECT_HANDLES, 0); - emit_call_with_gp(*emitter, (void**)free_local_object_handles2); - // Restore return register - if (preserve_ret==MPR_Gr) { - emitter->ipf_add(RETURN_VALUE_REG, 6, 0); - } else if (preserve_ret==MPR_Fr) { - emitter->ipf_adds(SP_REG, 16, SP_REG); - emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG); - } - emitter->set_target(free_target); + } + // Yes, save return register + if (preserve_ret == MPR_Gr) { + emitter->ipf_add(6, RETURN_VALUE_REG, 0); + } else if (preserve_ret == MPR_Fr) { + emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16)); + } + + if (handles) { + emit_call_with_gp(*emitter, (void**)m2n_pop_local_handles); } else { - // Yes, save return register - if (preserve_ret==MPR_Gr) - emitter->ipf_add(6, RETURN_VALUE_REG, 0); - else if (preserve_ret==MPR_Fr) - emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16)); - // Do free - emit_call_with_gp(*emitter, (void**)m2n_pop_local_handles); - // Restore return register - if (preserve_ret==MPR_Gr) { - emitter->ipf_add(RETURN_VALUE_REG, 6, 0); - } else if (preserve_ret==MPR_Fr) { - emitter->ipf_adds(SP_REG, 16, SP_REG); - emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG); - } + emit_call_with_gp(*emitter, (void**)m2n_free_local_handles); } + + // Restore return register + if (preserve_ret == MPR_Gr) { + emitter->ipf_add(RETURN_VALUE_REG, 6, 0); + } else if (preserve_ret == MPR_Fr) { + emitter->ipf_adds(SP_REG, 16, SP_REG); + emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG); + } + + if (handles) { + emitter->set_target(free_target); + } + // Unlink the M2nFrame from the list of the current thread size_t offset_lm2nf = (size_t)&((VM_thread*)0)->last_m2n_frame; emitter->ipf_adds(SCRATCH_GENERAL_REG2, (int)offset_lm2nf, THREAD_PTR_REG); Index: trunk/vm/vmcore/include/environment.h =================================================================== --- trunk/vm/vmcore/include/environment.h (revision 487462) +++ trunk/vm/vmcore/include/environment.h (working copy) @@ -42,6 +42,9 @@ struct Global_Env { public: + // Global VM states. + enum VM_STATE { VM_INITIALIZING, VM_RUNNING, VM_SHUTDOWNING }; + apr_pool_t* mem_pool; // memory pool BootstrapClassLoader* bootstrap_class_loader; UserDefinedClassLoader* system_class_loader; @@ -167,7 +170,6 @@ 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; @@ -177,8 +179,11 @@ Class* java_lang_ArithmeticException_Class; Class* java_lang_ClassCastException_Class; Class* java_lang_OutOfMemoryError_Class; + Class* java_lang_ThreadDeath_Class; + + ObjectHandle java_lang_Object; ObjectHandle java_lang_OutOfMemoryError; - ObjectHandle java_lang_ThreadDeathError; + ObjectHandle java_lang_ThreadDeath; // object of java.lang.Error class used for JVMTI JIT PopFrame support ObjectHandle popFrameException; @@ -206,6 +211,9 @@ // Offset to the vm_class field in java.lang.Class; unsigned vm_class_offset; + // The VM state. See VM_STATE enum above. + volatile int vm_state; + // FIXME // The whole environemt will be refactored to VM instance // The following contains a cached copy of EM interface table @@ -237,6 +245,18 @@ bootstrapping = false; } + int isVmInitializing() { + return vm_state == VM_INITIALIZING; + } + + int isVmRunning() { + return vm_state == VM_RUNNING; + } + + int IsVmShutdowning() { + return vm_state == VM_SHUTDOWNING; + } + //load a class via bootstrap classloader Class* LoadCoreClass(const String* name); Class* LoadCoreClass(const char* name); Index: trunk/vm/vmcore/include/init.h =================================================================== --- trunk/vm/vmcore/include/init.h (revision 487462) +++ trunk/vm/vmcore/include/init.h (working copy) @@ -26,6 +26,8 @@ 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_interrupt_handler(int); +void vm_dump_handler(int); 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/stack_trace.h =================================================================== --- trunk/vm/vmcore/include/stack_trace.h (revision 487462) +++ trunk/vm/vmcore/include/stack_trace.h (working copy) @@ -153,23 +153,33 @@ void st_print_frame(ExpandableMemBlock* buf, StackTraceFrame* stf); /** - * Prints the current thread's trace. + * Prints stack trace of all java threads. * - * This function supports and prints all Java and M2N frames. + * This function supports and prints all Java frames. * * @param[in] f - the pointer to the file, where the stack trace will be printed * * @note Intended for debugging purposes. */ -void st_print(FILE* f); +void st_print_all(FILE* f); /** - * Prints the current thread's trace into the stderr stream. + * Prints the current java thread stack trace into specified stream. * - * This function supports and prints all Java and M2N frames. + * This function supports and prints all Java frames. * + * @param[in] f - the pointer to the file, where the stack trace will be printed + * @param[in] thread - the thread wich stack should be printed + * * @note Intended for debugging purposes. */ +void st_print(FILE* f, hythread_t thread); + +/** + * Prints the current java thread stack trace into the stderr stream. + * + * @note Intended for debugging purposes. + */ void st_print(); #endif //!_STACK_TRACE_H_ Index: trunk/vm/vmcore/src/class_support/Environment.cpp =================================================================== --- trunk/vm/vmcore/src/class_support/Environment.cpp (revision 487462) +++ trunk/vm/vmcore/src/class_support/Environment.cpp (working copy) @@ -168,7 +168,6 @@ 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; @@ -177,6 +176,7 @@ java_lang_ArithmeticException_Class = NULL; java_lang_ClassCastException_Class = NULL; java_lang_OutOfMemoryError_Class = NULL; + java_lang_ThreadDeath_Class = NULL; java_lang_OutOfMemoryError = NULL; popFrameException = NULL; @@ -193,6 +193,7 @@ JavaLangString_VTable = NULL; vm_class_offset = 0; + vm_state = VM_INITIALIZING; TI = new DebugUtilsTI; vm_methods = new Method_Lookup_Table; @@ -203,10 +204,6 @@ Global_Env::~Global_Env() { - if (get_boolean_property("vm.noCleanupOnExit", false, VM_PROPERTIES)) { - return; - } - GlobalClassLoaderIterator ClIterator; ClassLoader *cl = ClIterator.first(); Index: trunk/vm/vmcore/src/exception/exceptions_impl.cpp =================================================================== --- trunk/vm/vmcore/src/exception/exceptions_impl.cpp (revision 487462) +++ trunk/vm/vmcore/src/exception/exceptions_impl.cpp (working copy) @@ -215,10 +215,6 @@ vm_execute_java_method_array((jmethodID) init_cause_method, &ret_val, args); tmn_suspend_enable(); - - if (exn_raised()) { - DIE(("Exception constructor has thrown an exception")); - } } jthrowable create_exception(Class* exc_class, Method* exc_init, jvalue* args) { Index: trunk/vm/vmcore/src/exception/exceptions_jit.cpp =================================================================== --- trunk/vm/vmcore/src/exception/exceptions_jit.cpp (revision 487462) +++ trunk/vm/vmcore/src/exception/exceptions_jit.cpp (working copy) @@ -209,18 +209,13 @@ si_goto_previous(si); } - Method *interrupted_method = NULL; - NativeCodePtr interrupted_method_location = NULL; - JIT *interrupted_method_jit = NULL; + assert(!si_is_native(si)); - if (!si_is_native(si)) - { - CodeChunkInfo *interrupted_cci = si_get_code_chunk_info(si); - assert(interrupted_cci); - interrupted_method = interrupted_cci->get_method(); - interrupted_method_location = si_get_ip(si); - interrupted_method_jit = interrupted_cci->get_jit(); - } + CodeChunkInfo *interrupted_cci = si_get_code_chunk_info(si); + assert(interrupted_cci); + Method *interrupted_method = interrupted_cci->get_method(); + NativeCodePtr interrupted_method_location = si_get_ip(si); + JIT *interrupted_method_jit = interrupted_cci->get_jit(); // Remove single step breakpoints which could have been set on the // exception bytecode @@ -236,6 +231,13 @@ ti->vm_brpt->unlock(); } + // When VM is in shutdown stage we need to execute final block to + // release monitors and propogate an exception to the upper frames. + if (VM_Global_State::loader_env->IsVmShutdowning()) { + exn_class = VM_Global_State::loader_env->JavaLangObject_Class; + *exn_obj = NULL; + } + bool same_frame = true; while (!si_is_past_end(si) && !si_is_native(si)) { CodeChunkInfo *cci = si_get_code_chunk_info(si); @@ -262,10 +264,15 @@ // Found a handler that catches the exception. #ifdef VM_STATS cci->num_catches++; - if (same_frame) + if (same_frame) { VM_Statistics::get_vm_stats().num_exceptions_caught_same_frame++; - if (handler->is_exc_obj_dead()) + } + if (handler->is_exc_obj_dead()) { VM_Statistics::get_vm_stats().num_exceptions_dead_object++; + if (!*exn_obj) { + VM_Statistics::get_vm_stats().num_exceptions_object_not_created++; + } + } #endif // VM_STATS // Setup handler context jit->fix_handler_context(method, si_get_jit_context(si)); @@ -293,18 +300,9 @@ } // Create exception if necessary - if (!*exn_obj) { - if (handler->is_exc_obj_dead() - && !VM_Global_State::loader_env->TI->isEnabled()) { -#ifdef VM_STATS - VM_Statistics::get_vm_stats().num_exceptions_object_not_created++; -#endif // VM_STATS - } - else { - *exn_obj = - create_lazy_exception(exn_class, exn_constr, - jit_exn_constr_args, vm_exn_constr_args); - } + if (!*exn_obj && !handler->is_exc_obj_dead()) { + *exn_obj = create_lazy_exception(exn_class, exn_constr, + jit_exn_constr_args, vm_exn_constr_args); } BEGIN_RAISE_AREA; @@ -339,12 +337,12 @@ } // Exception propagates to the native code + assert(si_is_native(si)); // The current thread exception is set to the exception and we return 0/NULL to the native code if (*exn_obj == NULL) { - *exn_obj = - create_lazy_exception(exn_class, exn_constr, - jit_exn_constr_args, vm_exn_constr_args); + *exn_obj = create_lazy_exception(exn_class, exn_constr, + jit_exn_constr_args, vm_exn_constr_args); } assert(!hythread_is_suspend_enabled()); Index: trunk/vm/vmcore/src/init/finalize.cpp =================================================================== --- trunk/vm/vmcore/src/init/finalize.cpp (revision 487462) +++ trunk/vm/vmcore/src/init/finalize.cpp (working copy) @@ -336,12 +336,14 @@ vm_execute_java_method_array((jmethodID) finalize_meth, 0, args); tmn_suspend_enable(); +#ifndef NDEBUG if (exn_raised()) { INFO2("finalize", "Uncaught exception " << exn_get_name() - << " while running a wakeFinalization in FinalizerThread"); - exn_clear(); + << " while running a wakeFinalization in FinalizerThread"); } +#endif + exn_clear(); p_TLS_vmthread->finalize_thread_flags &= ~FINALIZER_STARTER; } //Objects_To_Finalize::run_finalizers @@ -416,7 +418,8 @@ TRACE2("finalize", "finalize object " << class_get_name(handle->object->vt()->clss)); vm_execute_java_method_array( (jmethodID) finalize, 0, args); tmn_suspend_enable(); - + +#ifndef NDEBUG if (exn_raised()) { tmn_suspend_disable(); assert(handle->object->vt()->clss); @@ -424,9 +427,10 @@ << exn_get_name() << " while running a finalize of the object" << class_get_name(object->vt()->clss) << "."); - tmn_suspend_enable(); - exn_clear(); + tmn_suspend_enable(); } +#endif + exn_clear(); } return i; } //Objects_To_Finalize::do_finalization @@ -463,6 +467,7 @@ vm_execute_java_method_array( (jmethodID) enqueue, &r, args); tmn_suspend_enable(); +#ifndef NDEBUG if (exn_raised()) { tmn_suspend_disable(); assert(object->vt()->clss); @@ -471,8 +476,10 @@ << " while running a enqueue method of the object" << class_get_name(object->vt()->clss) << "."); tmn_suspend_enable(); - exn_clear(); + } +#endif + exn_clear(); } TRACE2("ref", "enqueue_references() completed"); Index: trunk/vm/vmcore/src/init/parse_arguments.cpp =================================================================== --- trunk/vm/vmcore/src/init/parse_arguments.cpp (revision 487462) +++ trunk/vm/vmcore/src/init/parse_arguments.cpp (working copy) @@ -203,8 +203,6 @@ " 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" " -XD=\n" " set an internal system property\n"); } //print_help_on_nonstandard_options @@ -233,8 +231,6 @@ " Use verifier.\n" " vm.jvmti.enabled (default FALSE):\n" " Whether JVMTI mode is enabled.\n" - " vm.cleanupOnExit (default FALSE):\n" - " Excplicitly free VM resources before exit.\n" " vm.bootclasspath.appendclasspath (default FALSE):\n" " Append classpath to the bootclasspath.\n" "\nOther properties:\n\n" @@ -481,9 +477,6 @@ const char* arg = option + strlen("-Xdumpfile:"); dump_file_name = arg; } - else if (strcmp(option, "-XnoCleanupOnExit") == 0) { - p_env->VmProperties()->set("vm.noCleanupOnExit", "true"); - } else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) { // Store a pointer to the portlib p_env->portLib = p_env->vm_arguments.options[i].extraInfo; Index: trunk/vm/vmcore/src/init/vm_init.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm_init.cpp (revision 487462) +++ trunk/vm/vmcore/src/init/vm_init.cpp (working copy) @@ -376,8 +376,6 @@ 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 = @@ -398,6 +396,8 @@ preload_class(vm_env, "java/lang/ClassCastException"); vm_env->java_lang_OutOfMemoryError_Class = preload_class(vm_env, "java/lang/OutOfMemoryError"); + vm_env->java_lang_ThreadDeath_Class = + preload_class(vm_env, "java/lang/ThreadDeath"); vm_env->java_lang_Cloneable_Class = preload_class(vm_env, vm_env->Clonable_String); @@ -704,11 +704,19 @@ // Now the thread is attached to VM and it is valid to disable it. hythread_suspend_disable(); - - // Create OutOfMemoryError. + + // Create java.lang.Object. + vm_env->java_lang_Object = oh_allocate_global_handle(); + vm_env->java_lang_Object->object = + class_alloc_new_object(vm_env->JavaLangObject_Class); + // Create java.lang.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 java.lang.ThreadDeath. + vm_env->java_lang_ThreadDeath = oh_allocate_global_handle(); + vm_env->java_lang_ThreadDeath->object = + class_alloc_new_object(vm_env->java_lang_ThreadDeath_Class); // Create pop frame exception. vm_env->popFrameException = oh_allocate_global_handle(); @@ -717,8 +725,8 @@ // 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); + // Precompile ThreadDeath. + class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeath_Class); hythread_suspend_enable(); Index: trunk/vm/vmcore/src/init/vm_properties.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm_properties.cpp (revision 487462) +++ trunk/vm/vmcore/src/init/vm_properties.cpp (working copy) @@ -267,7 +267,6 @@ properties.set("vm.jit_may_inline_sync", "true"); properties.set("vm.use_verifier", "true"); properties.set("vm.jvmti.enabled", "false"); - properties.set("vm.cleanupOnExit", "false"); properties.set("vm.bootclasspath.appendclasspath", "false"); /* Index: trunk/vm/vmcore/src/init/vm_shutdown.cpp =================================================================== --- trunk/vm/vmcore/src/init/vm_shutdown.cpp (revision 487462) +++ trunk/vm/vmcore/src/init/vm_shutdown.cpp (working copy) @@ -24,6 +24,7 @@ #include "open/hythread.h" #include "open/jthread.h" #include "open/gc.h" +#include "open/thread_externals.h" #include "jni.h" #include "jni_direct.h" @@ -82,6 +83,85 @@ return JNI_OK; } +static void vm_shutdown_callback() { + hythread_t self_native; + jthread self_java; + VM_thread * self_vm; + JNIEnv * jni_env; + Global_Env * vm_env; + + self_native = hythread_self(); + self_java = jthread_get_java_thread(self_native); + self_vm = get_vm_thread(self_native); + + // Make sure the thread is still attached to the VM. + if (self_java == NULL || self_vm == NULL) { + return; + } + + jni_env = jthread_get_JNI_env(self_java); + vm_env = jni_get_vm_env(jni_env); + + // We need to be in suspend disabled state to be able to throw an exception. + assert(!hythread_is_suspend_enabled()); + + //hythread_suspend_disable(); + + // Raise an exception. In shutdown stage it should cause entire stack unwinding. + jthread_throw_exception_object(vm_env->java_lang_ThreadDeath); + + //hythread_suspend_enable(); +} + +/* +void vm_shutdown_stop_java_threads(int exit_code) +{ + jthread current_java_thread; + JNIEnv_Internal * jni_env; + Global_Env * vm_env; + + // Current thread should be in suspend enabled state to prevent + // possible dead-locks. + assert(hythread_is_suspend_enabled()); + + current_java_thread = jthread_self(); + // Current thread should be attached to ThreadManager. + assert(current_java_thread); + jni_env = (JNIEnv_Internal *) jthread_get_JNI_env(current_java_thread); + vm_env = jni_env->vm->vm_env; + + // 2) Acquire VM state lock. + apr_thread_mutex_lock(vm_env->vm_state_mutex); + assert(vm_env->vm_state != Global_Env::VM_INITIALIZING); + + // 3) Check VM state. + if (vm_env->vm_state == Global_Env::VM_SHUTDOWNING) { + apr_thread_mutex_unlock(vm_env->vm_state_mutex); + return; + } + + assert(vm_env->vm_state == Global_Env::VM_RUNNING); + + // 4) Change VM state. Exception propagation mechanism should be changed + // upon setting up this flag. + vm_env->vm_state = Global_Env::VM_SHUTDOWNING; + + // 5) Block thread creation. + // TODO: investigate how to achive that with ThreadManager + + // 6) Execute shutdown callback for the current thread. + vm_shutdown_callback(NULL); + + // 7) Setup shutdown callback to all java threads but current. + // It causes an exception to be raised and all java monitors to + // be released upon reaching a safepoint. + hythread_group_set_suspend_disabled_callback(hythread_group_get_java(), vm_shutdown_callback, NULL); + + // 8) Unlock VM state mutex. + apr_thread_mutex_unlock(vm_env->vm_state_mutex); +} +*/ + /** * TODO: */ @@ -92,13 +172,15 @@ jobject uncaught_exception; VM_thread * vm_thread; hythread_t native_thread; - hythread_t current_native_thread; + hythread_t self; hythread_iterator_t it; + hythread_t * running_threads; + int size; assert(hythread_is_suspend_enabled()); jni_env = jthread_get_JNI_env(java_thread); - current_native_thread = hythread_self(); + self = hythread_self(); status = jthread_wait_for_all_nondaemon_threads(); if (status != TM_ERROR_NONE) { @@ -138,65 +220,177 @@ // Call Agent_OnUnload() for agents and unload agents. java_vm->vm_env->TI->Shutdown(java_vm); + // Block thread creation. + // TODO: investigate how to achive that with ThreadManager + + // Starting this moment any exception occured in java thread will cause + // entire java stack unwinding to the most recent native frame. + // JNI is not available as well. + assert(java_vm->vm_env->vm_state == Global_Env::VM_RUNNING); + java_vm->vm_env->vm_state = Global_Env::VM_SHUTDOWNING; + // 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. + // Stop java threads + size = 0; it = hythread_iterator_create(NULL); - while (native_thread = hythread_iterator_next(&it)) { + running_threads = (hythread_t *)apr_palloc( + java_vm->vm_env->mem_pool, hythread_iterator_size(it) * sizeof(hythread_t)); + while(native_thread = hythread_iterator_next(&it)) { vm_thread = get_vm_thread(native_thread); - if (vm_thread != NULL && native_thread != current_native_thread) { - java_vm->vm_env->VmProperties()->set("vm.noCleanupOnExit", "true"); - hythread_iterator_release(&it); - return JNI_ERR; + if (vm_thread != NULL && native_thread != self) { + running_threads[size] = native_thread; + ++size; + hythread_set_safepoint_callback(native_thread, vm_shutdown_callback); } } hythread_iterator_release(&it); + // Interrupt running threads. + for (int i = 0; i < size; i++) { + hythread_interrupt(running_threads[i]); + } + + // Wait for threads completion. + for (int i = 0; i < size; i++) { + hythread_join(running_threads[i]); + } + // 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() -{ - hythread_t native_thread; - hythread_iterator_t iterator; - VM_thread * vm_thread; +static int vm_interrupt_process(void * data) { + hythread_t * threadBuf; + int i; - INFO("****** BEGIN OF JAVA STACKS *****\n"); + threadBuf = (hythread_t *)data; + i = 0; + // Join all threads. + while (threadBuf[i] != NULL) { + hythread_join(threadBuf[i]); + i++; + } - hythread_suspend_all(&iterator, NULL); - native_thread ; - while(native_thread = hythread_iterator_next(&iterator)) { - vm_thread = get_vm_thread(native_thread); - if (!vm_thread) continue; - interpreter.stack_dump(vm_thread); + // Return 130 to be compatible with RI. + exit(130); +} + +/** + * Initiates VM shutdown sequence. + */ +static int vm_interrupt_entry_point(void * data) { + JNIEnv * jni_env; + JavaVMAttachArgs args; + JavaVM * java_vm; + jint status; + + java_vm = (JavaVM *)data; + args.version = JNI_VERSION_1_2; + args.group = NULL; + args.name = "InterruptionHandler"; + + status = AttachCurrentThread(java_vm, (void **)&jni_env, &args); + if (status == JNI_OK) { + exec_shutdown_sequence(jni_env); + DetachCurrentThread(java_vm); } - hythread_resume_all(NULL); - - INFO("****** END OF JAVA STACKS *****\n"); + return status; } -void quit_handler(int UNREF x) { - jvmti_notify_data_dump_request(); - if (interpreter_enabled()) { - dump_all_java_stacks(); - } else { - td_dump_all_threads(stderr); +/** + * Dumps all java stacks. + */ +static int vm_dump_entry_point(void * data) { + JNIEnv * jni_env; + JavaVMAttachArgs args; + JavaVM * java_vm; + jint status; + + java_vm = (JavaVM *)data; + args.version = JNI_VERSION_1_2; + args.group = NULL; + args.name = "DumpHandler"; + + status = AttachCurrentThread(java_vm, (void **)&jni_env, &args); + if (status == JNI_OK) { + // TODO: specify particular VM to notify. + jvmti_notify_data_dump_request(); + st_print_all(stdout); + DetachCurrentThread(java_vm); } + return status; } -void interrupt_handler(int UNREF x) -{ - static bool begin_shutdown_hooks = false; +/** + * Current process recieved an interruption signal (Ctrl+C pressed). + * Shutdown all running VMs and terminate the process. + */ +void vm_interrupt_handler(int UNREF x) { + JavaVM ** vmBuf; + hythread_t * threadBuf; + int nVMs; + jint status; - 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); + status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs); + assert(nVMs <= 1); + if (status != JNI_OK) return; + + vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *)); + status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs); + assert(nVMs <= 1); + if (status != JNI_OK) goto cleanup; + + status = hythread_attach(NULL); + if (status != TM_ERROR_NONE) goto cleanup; + + + threadBuf = (hythread_t *) STD_MALLOC((nVMs + 1) * sizeof(hythread_t)); + threadBuf[nVMs] = NULL; + + // Create a new thread for each VM to avoid scalability and deadlock problems. + for (int i = 0; i < nVMs; i++) { + threadBuf[i] = NULL; + hythread_create((threadBuf + i), 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_entry_point, (void *)vmBuf[i]); + } + + // spawn a new thread which will terminate the proccess. + hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_process, (void *)threadBuf); + +cleanup: + STD_FREE(vmBuf); } + +/** + * Current process recieved an ??? signal (Ctrl+Break pressed). + * Prints java stack traces for each VM running in the current procces. + */ +void vm_dump_handler(int UNREF x) { + JavaVM ** vmBuf; + int nVMs; + jint status; + + status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs); + assert(nVMs <= 1); + if (status != JNI_OK) return; + + vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *)); + status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs); + assert(nVMs <= 1); + + if (status != JNI_OK) goto cleanup; + + status = hythread_attach(NULL); + if (status != TM_ERROR_NONE) goto cleanup; + + // Create a new thread for each VM to avoid scalability and deadlock problems. + for (int i = 0; i < nVMs; i++) { + hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_dump_entry_point, (void *)vmBuf[i]); + } + +cleanup: + STD_FREE(vmBuf); +} Index: trunk/vm/vmcore/src/jni/jni.cpp =================================================================== --- trunk/vm/vmcore/src/jni/jni.cpp (revision 487462) +++ trunk/vm/vmcore/src/jni/jni.cpp (working copy) @@ -50,6 +50,7 @@ #include "jni_utils.h" #include "jit_runtime_support.h" #include "jvmti_direct.h" +#include "stack_trace.h" #ifdef _IPF_ #include "stub_code_utils.h" @@ -418,16 +419,13 @@ 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); - } - + JavaVM_Internal * current_vm = APR_RING_FIRST(&GLOBAL_VMS); + while (current_vm != APR_RING_SENTINEL(&GLOBAL_VMS, JavaVM_Internal, link)) { + 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; @@ -522,6 +520,9 @@ goto done; } + // The VM is fully initialized now. + vm_env->vm_state = Global_Env::VM_RUNNING; + // Send VM init event. jvmti_send_vm_init_event(vm_env); @@ -644,56 +645,58 @@ assert(hythread_is_suspend_enabled()); return struct_Class_to_jclass(clss); } - else - { - assert(exn_raised()); - return NULL; - } + + assert(exn_raised()); + return NULL; } //DefineClass -jclass JNICALL FindClass(JNIEnv* env_ext, - const char* name) + jclass JNICALL FindClass(JNIEnv * jni_env, + const char * name) { - if (exn_raised()) return NULL; TRACE2("jni", "FindClass called, name = " << name); + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (exn_raised() || vm_env->IsVmShutdowning()) return NULL; char *ch = strchr(name, '.'); if (NULL != ch) { - ThrowNew_Quick(env_ext, + ThrowNew_Quick(jni_env, VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes, name); return NULL; } - String* cls_name = VM_Global_State::loader_env->string_pool.lookup(name); - return FindClass(env_ext, cls_name); + String* cls_name = vm_env->string_pool.lookup(name); + return FindClass(jni_env, cls_name); } //FindClass -jclass JNICALL GetSuperclass(JNIEnv * UNREF env, jclass clazz) +jclass JNICALL GetSuperclass(JNIEnv * jni_env, jclass clazz) { TRACE2("jni", "GetSuperclass called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; Class* clss = jclass_to_struct_Class(clazz); if(clss) { if(clss->is_interface()) { - return 0; + return NULL; } else { Class* super_class = clss->get_super_class(); if(super_class) { assert(hythread_is_suspend_enabled()); return struct_Class_to_jclass(super_class); } else { - return 0; + return NULL; } } } else { - return 0; + return NULL; } } //GetSuperclass -jboolean JNICALL IsAssignableFrom(JNIEnv * UNREF env, +jboolean JNICALL IsAssignableFrom(JNIEnv * UNREF jni_env, jclass clazz1, jclass clazz2) { @@ -710,10 +713,11 @@ } } //IsAssignableFrom -jint JNICALL Throw(JNIEnv * UNREF env, jthrowable obj) +jint JNICALL Throw(JNIEnv * UNREF jni_env, jthrowable obj) { TRACE2("jni", "Throw called"); assert(hythread_is_suspend_enabled()); + if(obj) { exn_raise_object(obj); return 0; @@ -722,7 +726,7 @@ } } // Throw -jint JNICALL ThrowNew(JNIEnv *env, jclass clazz, const char *message) +jint JNICALL ThrowNew(JNIEnv * jni_env, jclass clazz, const char *message) { TRACE2("jni", "ThrowNew called, message = " << (message ? message : "")); assert(hythread_is_suspend_enabled()); @@ -730,18 +734,23 @@ jstring str = (jstring)0; if(message) { - str = NewStringUTF(env, message); + str = NewStringUTF(jni_env, message); if(!str) { return -1; } } - jmethodID init_id = GetMethodID(env, clazz, "", "(Ljava/lang/String;)V"); + jmethodID init_id = GetMethodID(jni_env, clazz, "", "(Ljava/lang/String;)V"); + if (!init_id) { + jni_env->DeleteLocalRef(str); + return -1; + } + jvalue args[1]; args[0].l = str; - jobject obj = NewObjectA(env, clazz, init_id, args); - env->DeleteLocalRef(str); - if(obj && !ExceptionOccurred(env)) { + jobject obj = NewObjectA(jni_env, clazz, init_id, args); + jni_env->DeleteLocalRef(str); + if(obj && !ExceptionOccurred(jni_env)) { exn_raise_object(obj); return 0; } else { @@ -749,58 +758,79 @@ } } //ThrowNew -jint JNICALL ThrowNew_Quick(JNIEnv *env, const char *classname, const char *message) +jint JNICALL ThrowNew_Quick(JNIEnv * jni_env, const char *classname, const char *message) { - jclass exclazz = FindClass(env, classname); + jclass exclazz = FindClass(jni_env, classname); if(!exclazz) { return -1; } - jint result = ThrowNew(env, exclazz, message); - env->DeleteLocalRef(exclazz); + jint result = ThrowNew(jni_env, exclazz, message); + jni_env->DeleteLocalRef(exclazz); return result; } // ThrowNew_Quick //FIXME LAZY EXCEPTION (2006.05.15) // chacks usage of this function and replace by lazy -jthrowable JNICALL ExceptionOccurred(JNIEnv * UNREF env) +jthrowable JNICALL ExceptionOccurred(JNIEnv * jni_env) { TRACE2("jni", "ExceptionOccurred called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) { + // Wait until shutdown exception is raised by callback. + while (!exn_raised()) { + // Switch enable/disable status to give a chance for + // callback execution. + hythread_suspend_disable(); + hythread_suspend_enable(); + hythread_yield(); + } + } + jthrowable result = exn_get(); + #ifdef _DEBUG - tmn_suspend_disable(); - if (!exn_raised()) - { - TRACE2("jni", "Exception occured, no exception"); - } - else - { + hythread_suspend_disable(); + if (result) { TRACE2("jni", "Exception occured, class = " << exn_get_name()); + } else { + TRACE2("jni", "Exception occured, no exception"); } - tmn_suspend_enable(); + if (vm_env->IsVmShutdowning() && !result) { + TRACE2("vm.core.shutdown", "ExceptionOccured: shutdown exception hasn't been raised"); + } + hythread_suspend_enable(); #endif - - if(exn_raised()) { - return exn_get(); - } else { - return 0; - } + + return result; } //ExceptionOccurred -void JNICALL ExceptionDescribe(JNIEnv * UNREF env) +void JNICALL ExceptionDescribe(JNIEnv * jni_env) { TRACE2("jni", "ExceptionDescribe called"); assert(hythread_is_suspend_enabled()); + // we should not report vm shutdown exception to the user + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; if (exn_raised()) { exn_print_stack_trace(stderr, exn_get()); } } //ExceptionDescribe -void JNICALL ExceptionClear(JNIEnv * UNREF env) +void JNICALL ExceptionClear(JNIEnv * jni_env) { TRACE2("jni", "ExceptionClear called"); assert(hythread_is_suspend_enabled()); + tmn_suspend_disable(); + // It is important to check the VM shutdown state in suspend disabled mode + // to garantee that we will not clear raised shutdown exception + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) { + tmn_suspend_enable(); + return; + } #ifdef _DEBUG if (!exn_raised()) { @@ -815,17 +845,25 @@ tmn_suspend_enable(); } //ExceptionClear -void JNICALL FatalError(JNIEnv * UNREF env, const char *msg) +void JNICALL FatalError(JNIEnv * UNREF jni_env, const char *msg) { TRACE2("jni", "FatalError called"); assert(hythread_is_suspend_enabled()); - DIE("\nFATAL error occurred in a JNI native method:\n\t" << msg); + + fprintf(stdout, "\nFATAL ERROR occurred in native method: %s\n", msg); + st_print(stdout, hythread_self()); + + // Return 1 to be compatible with RI. + exit(1); } //FatalError -jobject JNICALL NewGlobalRef(JNIEnv * UNREF env, jobject obj) +jobject JNICALL NewGlobalRef(JNIEnv * jni_env, jobject obj) { TRACE2("jni", "NewGlobalRef called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning() || !obj) return NULL; if(!obj) { return 0; } @@ -844,33 +882,35 @@ return (jobject)new_handle; } //NewGlobalRef -void JNICALL DeleteGlobalRef(JNIEnv * UNREF env, jobject globalRef) +void JNICALL DeleteGlobalRef(JNIEnv * UNREF jni_env, jobject globalRef) { TRACE2("jni", "DeleteGlobalRef called"); assert(hythread_is_suspend_enabled()); + + if (globalRef == NULL) return; + #ifdef _DEBUG tmn_suspend_disable(); ObjectHandle h = (ObjectHandle)globalRef; TRACE2("jni", "DeleteGlobalRef class = " << h->object->vt()->clss); tmn_suspend_enable(); #endif - if (globalRef != NULL) { - oh_deallocate_global_handle((ObjectHandle)globalRef); - } + + oh_deallocate_global_handle((ObjectHandle)globalRef); } //DeleteGlobalRef -jobject JNICALL NewLocalRef(JNIEnv *env, jobject ref) +jobject JNICALL NewLocalRef(JNIEnv * jni_env, jobject ref) { TRACE2("jni", "NewLocalRef called"); assert(hythread_is_suspend_enabled()); - if (NULL == ref) - return NULL; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning() || ref == NULL) return NULL; jobject new_ref = oh_copy_to_local_handle(ref); if (NULL == new_ref) { - exn_raise_object( - (jthrowable)(((JNIEnv_Internal*)env)->vm->vm_env->java_lang_OutOfMemoryError)); + exn_raise_object(vm_env->java_lang_OutOfMemoryError); return NULL; } @@ -879,22 +919,24 @@ return new_ref; } //NewLocalRef -void JNICALL DeleteLocalRef(JNIEnv * UNREF env, jobject localRef) +void JNICALL DeleteLocalRef(JNIEnv * UNREF jni_env, jobject localRef) { TRACE2("jni", "DeleteLocalRef called"); assert(hythread_is_suspend_enabled()); + + if (localRef == NULL) return; + #ifdef _DEBUG tmn_suspend_disable(); ObjectHandle h = (ObjectHandle)localRef; TRACE2("jni", "DeleteLocalRef class = " << h->object->vt()->clss); tmn_suspend_enable(); #endif - if (localRef != NULL) { - oh_discard_local_handle((ObjectHandle)localRef); - } + + oh_discard_local_handle((ObjectHandle)localRef); } //DeleteLocalRef -jboolean JNICALL IsSameObject(JNIEnv * UNREF env, +jboolean JNICALL IsSameObject(JNIEnv * UNREF jni_env, jobject ref1, jobject ref2) { @@ -926,7 +968,7 @@ return result; } //IsSameObject -VMEXPORT jint JNICALL PushLocalFrame(JNIEnv * UNREF env, jint UNREF cap) +VMEXPORT jint JNICALL PushLocalFrame(JNIEnv * UNREF jni_env, jint UNREF cap) { TRACE2("jni", "PushLocalFrame called"); assert(hythread_is_suspend_enabled()); @@ -934,7 +976,7 @@ return 0; } -VMEXPORT jobject JNICALL PopLocalFrame(JNIEnv * UNREF env, jobject res) +VMEXPORT jobject JNICALL PopLocalFrame(JNIEnv * UNREF jni_env, jobject res) { TRACE2("jni", "PopLocalFrame called"); assert(hythread_is_suspend_enabled()); @@ -943,7 +985,7 @@ } -jint JNICALL EnsureLocalCapacity(JNIEnv* UNREF env, jint UNREF cap) +jint JNICALL EnsureLocalCapacity(JNIEnv * UNREF jni_env, jint UNREF cap) { TRACE2("jni", "EnsureLocalCapacity called"); assert(hythread_is_suspend_enabled()); @@ -951,18 +993,21 @@ } -jobject JNICALL AllocObject(JNIEnv *env, +jobject JNICALL AllocObject(JNIEnv * jni_env, jclass clazz) { TRACE2("jni", "AllocObject called"); assert(hythread_is_suspend_enabled()); - assert(clazz); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning() || clazz == NULL) return NULL; + Class* clss = jclass_to_struct_Class(clazz); if(clss->is_interface() || clss->is_abstract()) { // Can't instantiate interfaces and abtract classes. - ThrowNew_Quick(env, "java/lang/InstantiationException", clss->get_name()->bytes); - return 0; + ThrowNew_Quick(jni_env, "java/lang/InstantiationException", clss->get_name()->bytes); + return NULL; } tmn_suspend_disable(); //---------------------------------v @@ -970,8 +1015,7 @@ ManagedObject *new_obj = (ManagedObject *)class_alloc_new_object(clss); if (new_obj == NULL) { tmn_suspend_enable(); - return 0; - + return NULL; } new_handle->object = (ManagedObject *)new_obj; tmn_suspend_enable(); //---------------------------------^ @@ -981,7 +1025,7 @@ -jobject JNICALL NewObject(JNIEnv *env, +jobject JNICALL NewObject(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) @@ -990,10 +1034,10 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return NewObjectV(env, clazz, methodID, args); + return NewObjectV(jni_env, clazz, methodID, args); } //NewObject -jobject JNICALL NewObjectV(JNIEnv *env, +jobject JNICALL NewObjectV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) @@ -1001,12 +1045,12 @@ TRACE2("jni", "NewObjectV called"); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jobject result = NewObjectA(env, clazz, methodID, jvalue_args); + jobject result = NewObjectA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //NewObjectV -jobject JNICALL NewObjectA(JNIEnv *env, +jobject JNICALL NewObjectA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) @@ -1014,27 +1058,25 @@ TRACE2("jni", "NewObjectA called"); assert(hythread_is_suspend_enabled()); // Allocate the object. - jobject new_handle = AllocObject(env, clazz); + jobject new_handle = AllocObject(jni_env, clazz); if(!new_handle) { // Couldn't allocate the object. - return 0; + return NULL; } - CallNonvirtualVoidMethodA(env, new_handle, clazz, methodID, args); - if (ExceptionCheck(env)) - return NULL; - else - return new_handle; + CallNonvirtualVoidMethodA(jni_env, new_handle, clazz, methodID, args); + return ExceptionCheck(jni_env) ? NULL : new_handle; } //NewObjectA -jclass JNICALL GetObjectClass(JNIEnv * UNREF env, +jclass JNICALL GetObjectClass(JNIEnv * jni_env, jobject obj) { TRACE2("jni", "GetObjectClass called"); assert(hythread_is_suspend_enabled()); // The spec guarantees that the reference is not null. assert(obj); + ObjectHandle h = (ObjectHandle)obj; tmn_suspend_disable(); //---------------------------------v @@ -1051,7 +1093,7 @@ return (jobject)new_handle; } //GetObjectClass -jboolean JNICALL IsInstanceOf(JNIEnv *env, +jboolean JNICALL IsInstanceOf(JNIEnv * jni_env, jobject obj, jclass clazz) { @@ -1061,18 +1103,14 @@ return JNI_TRUE; } - jclass obj_class = GetObjectClass(env, obj); + jclass obj_class = GetObjectClass(jni_env, obj); Class* clss = jclass_to_struct_Class(clazz); Class* obj_clss = jclass_to_struct_Class(obj_class); Boolean isInstance = obj_clss->is_instanceof(clss); - if(isInstance) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } + return isInstance ? JNI_TRUE : JNI_FALSE; } //IsInstanceOf static bool @@ -1095,16 +1133,20 @@ #endif // !NDEBUG } -jstring JNICALL NewString(JNIEnv * UNREF env, +jstring JNICALL NewString(JNIEnv * jni_env, const jchar *unicodeChars, jsize length) { TRACE2("jni", "NewString called, length = " << length); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + return (jstring)string_create_from_unicode_h(unicodeChars, length); } //NewString -jsize JNICALL GetStringLength(JNIEnv * UNREF env, +jsize JNICALL GetStringLength(JNIEnv * UNREF jni_env, jstring string) { TRACE2("jni", "GetStringLength called"); @@ -1115,14 +1157,16 @@ return string_get_length_h((ObjectHandle)string); } //GetStringLength -const jchar *JNICALL GetStringChars(JNIEnv * UNREF env, +const jchar *JNICALL GetStringChars(JNIEnv * jni_env, jstring string, jboolean *isCopy) { TRACE2("jni", "GetStringChars called"); assert(hythread_is_suspend_enabled()); - if(!string) - return 0; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (!string || vm_env->IsVmShutdowning()) return NULL; + assert(check_is_jstring_class(string)); tmn_suspend_disable(); @@ -1133,7 +1177,7 @@ return chars; } //GetStringChars -void JNICALL ReleaseStringChars(JNIEnv * UNREF env, +void JNICALL ReleaseStringChars(JNIEnv * UNREF jni_env, jstring string, const jchar *chars) { @@ -1145,15 +1189,19 @@ STD_FREE((void*)chars); } //ReleaseStringChars -jstring JNICALL NewStringUTF(JNIEnv * UNREF env, +jstring JNICALL NewStringUTF(JNIEnv * jni_env, const char *bytes) { TRACE2("jni", "NewStringUTF called, bytes = " << bytes); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + return (jstring)string_create_from_utf8_h(bytes, (unsigned)strlen(bytes)); } //NewStringUTF -jsize JNICALL GetStringUTFLength(JNIEnv * UNREF env, +jsize JNICALL GetStringUTFLength(JNIEnv * UNREF jni_env, jstring string) { TRACE2("jni", "GetStringUTFLength called"); @@ -1164,21 +1212,22 @@ return string_get_utf8_length_h((ObjectHandle)string); } //GetStringUTFLength -const char *JNICALL GetStringUTFChars(JNIEnv * UNREF env, +const char *JNICALL GetStringUTFChars(JNIEnv * jni_env, jstring string, jboolean *isCopy) { TRACE2("jni", "GetStringUTFChars called"); - if(!string) - return 0; + assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning() || !string) return NULL; assert(check_is_jstring_class(string)); - assert(hythread_is_suspend_enabled()); const char* res = string_get_utf8_chars_h((ObjectHandle)string); if (isCopy) *isCopy = JNI_TRUE; return res; } //GetStringUTFChars -void JNICALL ReleaseStringUTFChars(JNIEnv * UNREF env, +void JNICALL ReleaseStringUTFChars(JNIEnv * UNREF jni_env, jstring string, const char *utf) { @@ -1190,18 +1239,22 @@ STD_FREE((void*)utf); } //ReleaseStringUTFChars -jint JNICALL RegisterNatives(JNIEnv * UNREF env, +jint JNICALL RegisterNatives(JNIEnv * jni_env, jclass clazz, const JNINativeMethod *methods, jint nMethods) { TRACE2("jni", "RegisterNatives called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return -1; + Class_Handle clss = jclass_to_struct_Class(clazz); return class_register_methods(clss, methods, nMethods) ? -1 : 0; } //RegisterNatives -jint JNICALL UnregisterNatives(JNIEnv * UNREF env, jclass clazz) +jint JNICALL UnregisterNatives(JNIEnv * jni_env, jclass clazz) { TRACE2("jni", "UnregisterNatives called"); assert(hythread_is_suspend_enabled()); @@ -1209,17 +1262,21 @@ return class_unregister_methods(clss) ? -1 : 0; } //UnregisterNatives -jint JNICALL MonitorEnter(JNIEnv * UNREF env, jobject obj) +jint JNICALL MonitorEnter(JNIEnv * jni_env, jobject obj) { TRACE2("jni", "MonitorEnter called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return -1; + jthread_monitor_enter(obj); return exn_raised() ? -1 : 0; } //MonitorEnter -jint JNICALL MonitorExit(JNIEnv * UNREF env, jobject obj) +jint JNICALL MonitorExit(JNIEnv * UNREF jni_env, jobject obj) { ASSERT_RAISE_AREA; @@ -1231,20 +1288,23 @@ -jint JNICALL GetJavaVM(JNIEnv *env_ext, JavaVM **vm) +jint JNICALL GetJavaVM(JNIEnv * jni_env, JavaVM **vm) { TRACE2("jni", "GetJavaVM called"); assert(hythread_is_suspend_enabled()); - JNIEnv_Internal *env = (JNIEnv_Internal *)env_ext; - *vm = env->vm; + *vm = ((JNIEnv_Internal *) jni_env)->vm; return JNI_OK; } //GetJavaVM -void JNICALL GetStringRegion(JNIEnv * UNREF env, jstring s, jsize off, jsize len, jchar *b) +void JNICALL GetStringRegion(JNIEnv * jni_env, jstring s, jsize off, jsize len, jchar *b) { TRACE2("jni", "GetStringRegion called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + assert(s); string_get_unicode_region_h((ObjectHandle)s, off, len, b); @@ -1257,7 +1317,7 @@ string_get_utf8_region_h((ObjectHandle)s, off, len, b); } -VMEXPORT void* JNICALL GetPrimitiveArrayCritical(JNIEnv* jenv, jarray array, jboolean* isCopy) +VMEXPORT void* JNICALL GetPrimitiveArrayCritical(JNIEnv * jni_env, jarray array, jboolean* isCopy) { TRACE2("jni", "GetPrimitiveArrayCritical called"); assert(hythread_is_suspend_enabled()); @@ -1269,35 +1329,36 @@ TRACE2("jni.pin", "pinning array " << array->object); gc_pin_object((Managed_Object_Handle*)array); switch (array_clss->get_name()->bytes[1]) { - case 'B': return GetByteArrayElements(jenv, array, isCopy); - case 'C': return GetCharArrayElements(jenv, array, isCopy); - case 'D': return GetDoubleArrayElements(jenv, array, isCopy); - case 'F': return GetFloatArrayElements(jenv, array, isCopy); - case 'I': return GetIntArrayElements(jenv, array, isCopy); - case 'J': return GetLongArrayElements(jenv, array, isCopy); - case 'S': return GetShortArrayElements(jenv, array, isCopy); - case 'Z': return GetBooleanArrayElements(jenv, array, isCopy); + case 'B': return GetByteArrayElements(jni_env, array, isCopy); + case 'C': return GetCharArrayElements(jni_env, array, isCopy); + case 'D': return GetDoubleArrayElements(jni_env, array, isCopy); + case 'F': return GetFloatArrayElements(jni_env, array, isCopy); + case 'I': return GetIntArrayElements(jni_env, array, isCopy); + case 'J': return GetLongArrayElements(jni_env, array, isCopy); + case 'S': return GetShortArrayElements(jni_env, array, isCopy); + case 'Z': return GetBooleanArrayElements(jni_env, array, isCopy); default: ABORT("Wrong array type descriptor"); return NULL; } } -VMEXPORT void JNICALL ReleasePrimitiveArrayCritical(JNIEnv* jenv, jarray array, void* carray, jint mode) +VMEXPORT void JNICALL ReleasePrimitiveArrayCritical(JNIEnv * jni_env, jarray array, void* carray, jint mode) { TRACE2("jni", "ReleasePrimitiveArrayCritical called"); assert(hythread_is_suspend_enabled()); + tmn_suspend_disable(); Class* array_clss = ((ObjectHandle)array)->object->vt()->clss; tmn_suspend_enable(); assert(array_clss->get_name()->bytes[0]=='['); switch (array_clss->get_name()->bytes[1]) { - case 'B': ReleaseByteArrayElements(jenv, array, (jbyte*)carray, mode); break; - case 'C': ReleaseCharArrayElements(jenv, array, (jchar*)carray, mode); break; - case 'D': ReleaseDoubleArrayElements(jenv, array, (jdouble*)carray, mode); break; - case 'F': ReleaseFloatArrayElements(jenv, array, (jfloat*)carray, mode); break; - case 'I': ReleaseIntArrayElements(jenv, array, (jint*)carray, mode); break; - case 'J': ReleaseLongArrayElements(jenv, array, (jlong*)carray, mode); break; - case 'S': ReleaseShortArrayElements(jenv, array, (jshort*)carray, mode); break; - case 'Z': ReleaseBooleanArrayElements(jenv, array, (jboolean*)carray, mode); break; + case 'B': ReleaseByteArrayElements(jni_env, array, (jbyte*)carray, mode); break; + case 'C': ReleaseCharArrayElements(jni_env, array, (jchar*)carray, mode); break; + case 'D': ReleaseDoubleArrayElements(jni_env, array, (jdouble*)carray, mode); break; + case 'F': ReleaseFloatArrayElements(jni_env, array, (jfloat*)carray, mode); break; + case 'I': ReleaseIntArrayElements(jni_env, array, (jint*)carray, mode); break; + case 'J': ReleaseLongArrayElements(jni_env, array, (jlong*)carray, mode); break; + case 'S': ReleaseShortArrayElements(jni_env, array, (jshort*)carray, mode); break; + case 'Z': ReleaseBooleanArrayElements(jni_env, array, (jboolean*)carray, mode); break; default: ABORT("Wrong array type descriptor"); break; } if (mode != JNI_COMMIT) { @@ -1306,100 +1367,109 @@ } } -const jchar* JNICALL GetStringCritical(JNIEnv *env, jstring s, jboolean* isCopy) +const jchar* JNICALL GetStringCritical(JNIEnv *jni_env, jstring s, jboolean* isCopy) { TRACE2("jni", "GetStringCritical called"); assert(hythread_is_suspend_enabled()); - return GetStringChars(env, s, isCopy); + return GetStringChars(jni_env, s, isCopy); } -void JNICALL ReleaseStringCritical(JNIEnv *env, jstring s, const jchar* cstr) +void JNICALL ReleaseStringCritical(JNIEnv * jni_env, jstring s, const jchar* cstr) { TRACE2("jni", "ReleaseStringCritical called"); assert(hythread_is_suspend_enabled()); - ReleaseStringChars(env, s, cstr); + ReleaseStringChars(jni_env, s, cstr); } -VMEXPORT jweak JNICALL NewWeakGlobalRef(JNIEnv *env, jobject obj) +VMEXPORT jweak JNICALL NewWeakGlobalRef(JNIEnv * jni_env, jobject obj) { TRACE2("jni", "NewWeakGlobalRef called"); assert(hythread_is_suspend_enabled()); - return NewGlobalRef(env, obj); + return NewGlobalRef(jni_env, obj); } -VMEXPORT void JNICALL DeleteWeakGlobalRef(JNIEnv *env, jweak obj) +VMEXPORT void JNICALL DeleteWeakGlobalRef(JNIEnv * jni_env, jweak obj) { TRACE2("jni", "DeleteWeakGlobalRef called"); assert(hythread_is_suspend_enabled()); - DeleteGlobalRef(env, obj); + DeleteGlobalRef(jni_env, obj); } -jboolean JNICALL ExceptionCheck(JNIEnv * UNREF env) +jboolean JNICALL ExceptionCheck(JNIEnv * jni_env) { TRACE2("jni", "ExceptionCheck called, exception status = " << exn_raised()); assert(hythread_is_suspend_enabled()); - if (exn_raised()) + + Global_Env * vm_env = jni_get_vm_env(jni_env); + + if (exn_raised() || vm_env->IsVmShutdowning()) return JNI_TRUE; else return JNI_FALSE; } -VMEXPORT jmethodID JNICALL FromReflectedMethod(JNIEnv *env, jobject method) +VMEXPORT jmethodID JNICALL FromReflectedMethod(JNIEnv * jni_env, jobject method) { TRACE2("jni", "FromReflectedMethod called"); Class* clss = jobject_to_struct_Class(method); - if (clss == VM_Global_State::loader_env->java_lang_reflect_Constructor_Class) + Global_Env * vm_env = jni_get_vm_env(jni_env); + + if (clss == vm_env->java_lang_reflect_Constructor_Class) { static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J"); - return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(env, method, m, 0)); + return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, method, m, 0)); } - else if (clss == VM_Global_State::loader_env->java_lang_reflect_Method_Class) + else if (clss == vm_env->java_lang_reflect_Method_Class) { static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J"); - return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(env, method, m, 0)); + return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, method, m, 0)); } - else - return NULL; + return NULL; } -VMEXPORT jfieldID JNICALL FromReflectedField(JNIEnv *env, jobject field) +VMEXPORT jfieldID JNICALL FromReflectedField(JNIEnv * jni_env, jobject field) { TRACE2("jni", "FromReflectedField called"); Class* clss = jobject_to_struct_Class(field); + Global_Env * vm_env = jni_get_vm_env(jni_env); - if (clss == VM_Global_State::loader_env->java_lang_reflect_Field_Class) + if (clss == vm_env->java_lang_reflect_Field_Class) { static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J"); - return (jfieldID) ((POINTER_SIZE_INT) CallLongMethodA(env, field, m, 0)); + return (jfieldID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, field, m, 0)); } - else - return NULL; + return NULL; } -VMEXPORT jobject JNICALL ToReflectedMethod(JNIEnv *env, jclass UNREF cls, jmethodID methodID, +VMEXPORT jobject JNICALL ToReflectedMethod(JNIEnv * jni_env, jclass UNREF cls, jmethodID methodID, jboolean isStatic) { TRACE2("jni", "ToReflectedMethod called"); + + Global_Env * vm_env = jni_get_vm_env(jni_env); Method *m = (Method*)methodID; - if ((bool)m->is_static() != (bool)isStatic) // True if flags are different + // True if flags are different + if ((bool)m->is_static() != (bool)isStatic || vm_env->IsVmShutdowning()) return NULL; if (m->is_init()) - return reflection_reflect_constructor(env, m); + return reflection_reflect_constructor(jni_env, m); else - return reflection_reflect_method(env, m); + return reflection_reflect_method(jni_env, m); } -VMEXPORT jobject JNICALL ToReflectedField(JNIEnv *env, jclass UNREF cls, jfieldID fieldID, +VMEXPORT jobject JNICALL ToReflectedField(JNIEnv * jni_env, jclass UNREF cls, jfieldID fieldID, jboolean isStatic) { TRACE2("jni", "ToReflectedField called"); + + Global_Env * vm_env = jni_get_vm_env(jni_env); Field *f = (Field*)fieldID; - if ((bool)f->is_static() != (bool)isStatic) // True if flags are different + if ((bool)f->is_static() != (bool)isStatic || vm_env->IsVmShutdowning()) // True if flags are different return NULL; - return reflection_reflect_field(env, fieldID); + return reflection_reflect_field(jni_env, fieldID); } jobject JNICALL NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) @@ -1727,7 +1797,6 @@ assert(hythread_is_suspend_enabled()); } - void unsafe_global_object_handles_init(JNIEnv * jni_env) { assert(!hythread_is_suspend_enabled()); tmn_suspend_enable(); @@ -1740,7 +1809,7 @@ 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()); + check_for_unexpected_exception(); + assert(hythread_is_suspend_enabled()); tmn_suspend_disable(); } Index: trunk/vm/vmcore/src/jni/jni_array.cpp =================================================================== --- trunk/vm/vmcore/src/jni/jni_array.cpp (revision 487462) +++ trunk/vm/vmcore/src/jni/jni_array.cpp (working copy) @@ -38,7 +38,7 @@ #include "jni_utils.h" #include "exceptions.h" -jsize JNICALL GetArrayLength(JNIEnv * UNREF env, +jsize JNICALL GetArrayLength(JNIEnv * UNREF jni_env, jarray array) { TRACE2("jni", "GetArrayLength called"); @@ -53,7 +53,7 @@ } //GetArrayLength -jarray JNICALL NewObjectArray(JNIEnv * UNREF env, +jarray JNICALL NewObjectArray(JNIEnv * jni_env, jsize length, jclass elementClass, jobject initialElement) @@ -61,6 +61,10 @@ ASSERT_RAISE_AREA; TRACE2("jni", "NewObjectArray called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle elem_handle = (ObjectHandle)initialElement; Class* clss = jclass_to_struct_Class(elementClass); @@ -68,7 +72,7 @@ Class *arr_clss = (Class *)class_get_array_of_class(clss); if(!arr_clss) { - return 0; + return NULL; } // esostrov: vm_new_vector() may throw an exception. Throwing (not rising) @@ -105,8 +109,8 @@ // only if the elem is non-null. if (elem != NULL) { ManagedObject **elems = (ManagedObject **)get_vector_element_address_ref(vector, 0); - Global_Env *global_env = VM_Global_State::loader_env; - if (global_env->compress_references) { + Global_Env * vm_env = VM_Global_State::loader_env; + if (vm_env->compress_references) { COMPRESSED_REFERENCE elem_offset = compress_reference((ManagedObject *)elem); COMPRESSED_REFERENCE *compressed_elems = (COMPRESSED_REFERENCE *)elems; for (int i = 0; i < length; i++) { @@ -128,21 +132,20 @@ -jobject JNICALL GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) +jobject JNICALL GetObjectArrayElement(JNIEnv * jni_env, jobjectArray array, jsize index) { TRACE2("jni", "GetObjectArrayElement called"); assert(hythread_is_suspend_enabled()); - if (array == NULL) { - // This should not happen. - ASSERT(0, "Input parameter 'array' is NULL"); - return 0; - } + assert(array); - jsize length = GetArrayLength(env, array); + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + jsize length = GetArrayLength(jni_env, array); if ((index < 0) || (index >= length)) { char msg[20]; sprintf(msg, "%d", index); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return 0; } @@ -165,39 +168,38 @@ -void JNICALL SetObjectArrayElement(JNIEnv *env, +void JNICALL SetObjectArrayElement(JNIEnv * jni_env, jobjectArray array, jsize index, jobject value) { TRACE2("jni", "SetObjectArrayElement called"); assert(hythread_is_suspend_enabled()); - if (array == NULL) { - // This should not happen. - ASSERT(0, "Input parameter 'array' is NULL"); - return; - } + assert(array); - jsize length = GetArrayLength(env, array); + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); if ((index < 0) || (index >= length)) { char msg[20]; sprintf(msg, "%d", index); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } if (value != NULL) { - jclass array_jclass = GetObjectClass(env, array); - jclass actual_element_jclass = GetObjectClass(env, value); + jclass array_jclass = GetObjectClass(jni_env, array); + jclass actual_element_jclass = GetObjectClass(jni_env, value); Class* array_class = jclass_to_struct_Class(array_jclass); Class* actual_element_class = jclass_to_struct_Class(actual_element_jclass); - DeleteLocalRef(env, array_jclass); - DeleteLocalRef(env, actual_element_jclass); + DeleteLocalRef(jni_env, array_jclass); + DeleteLocalRef(jni_env, actual_element_jclass); if (!actual_element_class->is_instanceof(array_class->get_array_element_class())) { - ThrowNew_Quick(env, "java/lang/ArrayStoreException", actual_element_class->get_name()->bytes); + ThrowNew_Quick(jni_env, "java/lang/ArrayStoreException", actual_element_class->get_name()->bytes); return; } } @@ -227,12 +229,15 @@ -jbooleanArray JNICALL NewBooleanArray(JNIEnv * UNREF env, jsize length) +jbooleanArray JNICALL NewBooleanArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewBooleanArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfBoolean_Class; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfBoolean_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -259,13 +264,15 @@ -jbyteArray JNICALL NewByteArray(JNIEnv * UNREF env, jsize length) +jbyteArray JNICALL NewByteArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewByteArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfByte_Class; - assert(clss); - + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfByte_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -292,12 +299,15 @@ -jcharArray JNICALL NewCharArray(JNIEnv * UNREF env, jsize length) +jcharArray JNICALL NewCharArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewCharArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfChar_Class; - + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfChar_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -324,12 +334,15 @@ -jshortArray JNICALL NewShortArray(JNIEnv * UNREF env, jsize length) +jshortArray JNICALL NewShortArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewShortArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfShort_Class; - + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfShort_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -357,11 +370,15 @@ -jintArray JNICALL NewIntArray(JNIEnv * UNREF env, jsize length) +jintArray JNICALL NewIntArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewIntArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfInt_Class; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfInt_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -388,11 +405,15 @@ -jlongArray JNICALL NewLongArray(JNIEnv * UNREF env, jsize length) +jlongArray JNICALL NewLongArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewLongArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfLong_Class; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfLong_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -419,11 +440,15 @@ -jfloatArray JNICALL NewFloatArray(JNIEnv * UNREF env, jsize length) +jfloatArray JNICALL NewFloatArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewFloatArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfFloat_Class; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfFloat_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -450,11 +475,15 @@ -jdoubleArray JNICALL NewDoubleArray(JNIEnv * UNREF env, jsize length) +jdoubleArray JNICALL NewDoubleArray(JNIEnv * jni_env, jsize length) { TRACE2("jni", "NewDoubleArray called"); assert(hythread_is_suspend_enabled()); - Class *clss = VM_Global_State::loader_env->ArrayOfDouble_Class; + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + + Class *clss = vm_env->ArrayOfDouble_Class; unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); @@ -489,12 +518,16 @@ // begin GetArrayElements functions -jboolean *JNICALL GetBooleanArrayElements(JNIEnv * UNREF env, +jboolean *JNICALL GetBooleanArrayElements(JNIEnv * jni_env, jbooleanArray array, jboolean *isCopy) { TRACE2("jni", "GetBooleanArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -529,12 +562,16 @@ -jbyte *JNICALL GetByteArrayElements(JNIEnv * UNREF env, +jbyte *JNICALL GetByteArrayElements(JNIEnv * jni_env, jbyteArray array, jboolean *isCopy) { TRACE2("jni", "GetByteArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -569,12 +606,16 @@ -jchar *JNICALL GetCharArrayElements(JNIEnv * UNREF env, +jchar *JNICALL GetCharArrayElements(JNIEnv * jni_env, jcharArray array, jboolean *isCopy) { TRACE2("jni", "GetCharArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -609,12 +650,16 @@ -jshort *JNICALL GetShortArrayElements(JNIEnv * UNREF env, +jshort *JNICALL GetShortArrayElements(JNIEnv * jni_env, jshortArray array, jboolean *isCopy) { TRACE2("jni", "GetShortArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -649,12 +694,16 @@ -jint *JNICALL GetIntArrayElements(JNIEnv *env, +jint *JNICALL GetIntArrayElements(JNIEnv * jni_env, jintArray array, jboolean *isCopy) { TRACE2("jni", "GetIntArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -670,7 +719,7 @@ Vector_Handle java_array = (Vector_Handle)h->object; return (jint *)get_vector_element_address_int32(java_array, 0); } else { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); jint *primitive_array = (jint *)STD_MALLOC(sizeof(jint) * length); @@ -690,12 +739,16 @@ -jlong *JNICALL GetLongArrayElements(JNIEnv * UNREF env, +jlong *JNICALL GetLongArrayElements(JNIEnv * jni_env, jlongArray array, jboolean *isCopy) { TRACE2("jni", "GetLongArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -730,12 +783,16 @@ -jfloat *JNICALL GetFloatArrayElements(JNIEnv *env, +jfloat *JNICALL GetFloatArrayElements(JNIEnv * jni_env, jfloatArray array, jboolean *isCopy) { TRACE2("jni", "GetFloatArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -751,7 +808,7 @@ Vector_Handle java_array = (Vector_Handle)h->object; return (jfloat *)get_vector_element_address_f32(java_array, 0); } else { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); jfloat *primitive_array = (jfloat *)STD_MALLOC(sizeof(jfloat) * length); @@ -771,12 +828,16 @@ -jdouble *JNICALL GetDoubleArrayElements(JNIEnv * UNREF env, +jdouble *JNICALL GetDoubleArrayElements(JNIEnv * jni_env, jdoubleArray array, jboolean *isCopy) { TRACE2("jni", "GetDoubleArrayElements called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -820,7 +881,7 @@ // begin ReleaseArrayElements functions -void JNICALL ReleaseBooleanArrayElements(JNIEnv *env, +void JNICALL ReleaseBooleanArrayElements(JNIEnv * jni_env, jbooleanArray array, jboolean *elems, jint mode) @@ -828,6 +889,10 @@ TRACE2("jni", "ReleaseBooleanArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -845,7 +910,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -870,7 +935,7 @@ -void JNICALL ReleaseByteArrayElements(JNIEnv *env, +void JNICALL ReleaseByteArrayElements(JNIEnv * jni_env, jbyteArray array, jbyte *elems, jint mode) @@ -879,6 +944,9 @@ assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -896,7 +964,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -920,7 +988,7 @@ -void JNICALL ReleaseCharArrayElements(JNIEnv *env, +void JNICALL ReleaseCharArrayElements(JNIEnv * jni_env, jcharArray array, jchar *elems, jint mode) @@ -928,6 +996,10 @@ TRACE2("jni", "ReleaseCharArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -945,7 +1017,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -970,7 +1042,7 @@ -void JNICALL ReleaseShortArrayElements(JNIEnv *env, +void JNICALL ReleaseShortArrayElements(JNIEnv * jni_env, jshortArray array, jshort *elems, jint mode) @@ -978,6 +1050,10 @@ TRACE2("jni", "ReleaseShortArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -995,7 +1071,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -1020,7 +1096,7 @@ -void JNICALL ReleaseIntArrayElements(JNIEnv *env, +void JNICALL ReleaseIntArrayElements(JNIEnv * jni_env, jintArray array, jint *elems, jint mode) @@ -1028,6 +1104,10 @@ TRACE2("jni", "ReleaseIntArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -1045,7 +1125,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -1070,7 +1150,7 @@ -void JNICALL ReleaseLongArrayElements(JNIEnv *env, +void JNICALL ReleaseLongArrayElements(JNIEnv * jni_env, jlongArray array, jlong *elems, jint mode) @@ -1078,6 +1158,10 @@ TRACE2("jni", "ReleaseLongArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -1095,7 +1179,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -1120,7 +1204,7 @@ -void JNICALL ReleaseFloatArrayElements(JNIEnv *env, +void JNICALL ReleaseFloatArrayElements(JNIEnv * jni_env, jfloatArray array, jfloat *elems, jint mode) @@ -1128,6 +1212,10 @@ TRACE2("jni", "ReleaseFloatArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -1145,7 +1233,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -1171,7 +1259,7 @@ -void JNICALL ReleaseDoubleArrayElements(JNIEnv *env, +void JNICALL ReleaseDoubleArrayElements(JNIEnv * jni_env, jdoubleArray array, jdouble *elems, jint mode) @@ -1179,6 +1267,10 @@ TRACE2("jni", "ReleaseDoubleArrayElements called"); assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)array; + + // It is better to be user frendly and don't crash if nothing should be released. + if (elems == NULL) return; + tmn_suspend_disable(); //---------------------------------v Vector_Handle java_array = (Vector_Handle)h->object; @@ -1196,7 +1288,7 @@ case 0: case JNI_COMMIT: { - jsize length = GetArrayLength(env, array); + jsize length = GetArrayLength(jni_env, array); ObjectHandle h = (ObjectHandle)array; tmn_suspend_disable(); //---------------------------------v @@ -1230,7 +1322,7 @@ // begin GetArrayRegion functions -void JNICALL GetBooleanArrayRegion (JNIEnv *env, +void JNICALL GetBooleanArrayRegion (JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1238,12 +1330,16 @@ { TRACE2("jni", "GetBooleanArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1259,7 +1355,7 @@ -void JNICALL GetByteArrayRegion (JNIEnv *env, +void JNICALL GetByteArrayRegion (JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1267,12 +1363,16 @@ { TRACE2("jni", "GetByteArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1288,7 +1388,7 @@ -void JNICALL GetCharArrayRegion(JNIEnv *env, +void JNICALL GetCharArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1296,12 +1396,16 @@ { TRACE2("jni", "GetCharArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1317,7 +1421,7 @@ -void JNICALL GetShortArrayRegion(JNIEnv *env, +void JNICALL GetShortArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1325,12 +1429,16 @@ { TRACE2("jni", "GetShortArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1346,7 +1454,7 @@ -void JNICALL GetIntArrayRegion(JNIEnv *env, +void JNICALL GetIntArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1354,12 +1462,16 @@ { TRACE2("jni", "GetIntArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1375,7 +1487,7 @@ -void JNICALL GetLongArrayRegion(JNIEnv *env, +void JNICALL GetLongArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1383,12 +1495,16 @@ { TRACE2("jni", "GetLongArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1404,7 +1520,7 @@ -void JNICALL GetFloatArrayRegion(JNIEnv *env, +void JNICALL GetFloatArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1412,12 +1528,16 @@ { TRACE2("jni", "GetFloatArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1433,7 +1553,7 @@ -void JNICALL GetDoubleArrayRegion(JNIEnv *env, +void JNICALL GetDoubleArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1441,12 +1561,16 @@ { TRACE2("jni", "GetDoubleArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1470,7 +1594,7 @@ // begin SetArrayRegion functions -void JNICALL SetBooleanArrayRegion(JNIEnv *env, +void JNICALL SetBooleanArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1478,12 +1602,16 @@ { TRACE2("jni", "SetBooleanArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1501,7 +1629,7 @@ -void JNICALL SetByteArrayRegion(JNIEnv *env, +void JNICALL SetByteArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1509,12 +1637,16 @@ { TRACE2("jni", "SetByteArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1532,7 +1664,7 @@ -void JNICALL SetCharArrayRegion(JNIEnv *env, +void JNICALL SetCharArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1540,12 +1672,16 @@ { TRACE2("jni", "SetCharArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1563,7 +1699,7 @@ -void JNICALL SetShortArrayRegion(JNIEnv *env, +void JNICALL SetShortArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1571,12 +1707,16 @@ { TRACE2("jni", "SetShortArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1594,7 +1734,7 @@ -void JNICALL SetIntArrayRegion(JNIEnv *env, +void JNICALL SetIntArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1602,12 +1742,16 @@ { TRACE2("jni", "SetIntArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1625,7 +1769,7 @@ -void JNICALL SetLongArrayRegion(JNIEnv *env, +void JNICALL SetLongArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1633,12 +1777,16 @@ { TRACE2("jni", "SetLongArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1656,7 +1804,7 @@ -void JNICALL SetFloatArrayRegion(JNIEnv *env, +void JNICALL SetFloatArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1664,12 +1812,16 @@ { TRACE2("jni", "SetFloatArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } @@ -1687,7 +1839,7 @@ -void JNICALL SetDoubleArrayRegion(JNIEnv *env, +void JNICALL SetDoubleArrayRegion(JNIEnv * jni_env, jobjectArray array, jsize start, jsize len, @@ -1695,12 +1847,16 @@ { TRACE2("jni", "SetDoubleArrayRegion called"); assert(hythread_is_suspend_enabled()); - jsize length = GetArrayLength(env, array); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + jsize length = GetArrayLength(jni_env, array); jsize end = start + len; if(start < 0 || len < 0 || end > length) { char msg[30]; sprintf(msg, "%d..%d", start, end); - ThrowNew_Quick(env, "java/lang/ArrayIndexOutOfBoundsException", msg); + ThrowNew_Quick(jni_env, "java/lang/ArrayIndexOutOfBoundsException", msg); return; } Index: trunk/vm/vmcore/src/jni/jni_field.cpp =================================================================== --- trunk/vm/vmcore/src/jni/jni_field.cpp (revision 487462) +++ trunk/vm/vmcore/src/jni/jni_field.cpp (working copy) @@ -37,18 +37,22 @@ #include "exceptions.h" -jfieldID JNICALL GetFieldID(JNIEnv *env, +jfieldID JNICALL GetFieldID(JNIEnv * jni_env, jclass clazz, const char *name, const char *sig) { TRACE2("jni", "GetFieldID called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Class* clss = jclass_to_struct_Class(clazz); Field *field = class_lookup_field_recursive(clss, name, sig); if (NULL == field || field->is_static()) { - ThrowNew_Quick(env, "java/lang/NoSuchFieldError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchFieldError", name); return 0; } TRACE2("jni", "GetFieldID " << clss->get_name()->bytes @@ -61,12 +65,16 @@ // non-standard -jfieldID JNICALL GetFieldID_Quick(JNIEnv * UNREF env, +jfieldID JNICALL GetFieldID_Quick(JNIEnv * jni_env, const char *class_name, const char *field_name, const char *sig) { assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + String *class_string = VM_Global_State::loader_env->string_pool.lookup(class_name); assert(hythread_is_suspend_enabled()); Class *clss = @@ -78,7 +86,7 @@ return (jfieldID)field; } //GetFieldID_Quick -jfieldID JNICALL GetStaticFieldID(JNIEnv *env, +jfieldID JNICALL GetStaticFieldID(JNIEnv * jni_env, jclass clazz, const char *name, const char *sig) @@ -86,11 +94,14 @@ TRACE2("jni", "GetStaticFieldID called"); assert(hythread_is_suspend_enabled()); + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Class* clss = jclass_to_struct_Class(clazz); Field *field = class_lookup_field_recursive(clss, name, sig); if(NULL == field || !field->is_static()) { - ThrowNew_Quick(env, "java/lang/NoSuchFieldError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchFieldError", name); return 0; } TRACE2("jni", "GetStaticFieldID " << clss->get_name()->bytes @@ -104,11 +115,14 @@ // begin GetField functions -jobject JNICALL GetObjectFieldOffset(JNIEnv* UNREF env, jobject obj, jint offset) +jobject JNICALL GetObjectFieldOffset(JNIEnv* UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -125,27 +139,31 @@ return (jobject)new_handle; } -jobject JNICALL GetObjectField(JNIEnv *env, +jobject JNICALL GetObjectField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetObjectField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return NULL; assert(!f->is_static()); - return GetObjectFieldOffset(env, obj, f->get_offset()); + return GetObjectFieldOffset(jni_env, obj, f->get_offset()); } //GetObjectField -jboolean JNICALL GetBooleanFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jboolean JNICALL GetBooleanFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -156,25 +174,29 @@ return val; } -jboolean JNICALL GetBooleanField(JNIEnv *env, +jboolean JNICALL GetBooleanField(JNIEnv *jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetBooleanField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetBooleanFieldOffset(env, obj, f->get_offset()); + return GetBooleanFieldOffset(jni_env, obj, f->get_offset()); } //GetBooleanField -jbyte JNICALL GetByteFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jbyte JNICALL GetByteFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -185,27 +207,31 @@ return val; } -jbyte JNICALL GetByteField(JNIEnv *env, +jbyte JNICALL GetByteField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetByteField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetByteFieldOffset(env, obj, f->get_offset()); + return GetByteFieldOffset(jni_env, obj, f->get_offset()); } //GetByteField -jchar JNICALL GetCharFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jchar JNICALL GetCharFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -216,27 +242,31 @@ return val; } -jchar JNICALL GetCharField(JNIEnv *env, +jchar JNICALL GetCharField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetCharField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetCharFieldOffset(env, obj, f->get_offset()); + return GetCharFieldOffset(jni_env, obj, f->get_offset()); } //GetCharField -jshort JNICALL GetShortFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jshort JNICALL GetShortFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -247,27 +277,31 @@ return val; } -jshort JNICALL GetShortField(JNIEnv *env, +jshort JNICALL GetShortField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetShortField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetShortFieldOffset(env, obj, f->get_offset()); + return GetShortFieldOffset(jni_env, obj, f->get_offset()); } //GetShortField -jint JNICALL GetIntFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jint JNICALL GetIntFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -278,27 +312,31 @@ return val; } -jint JNICALL GetIntField(JNIEnv *env, +jint JNICALL GetIntField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetIntField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetIntFieldOffset(env, obj, f->get_offset()); + return GetIntFieldOffset(jni_env, obj, f->get_offset()); } //GetIntField -jlong JNICALL GetLongFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jlong JNICALL GetLongFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -309,27 +347,31 @@ return val; } -jlong JNICALL GetLongField(JNIEnv *env, +jlong JNICALL GetLongField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetLongField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetLongFieldOffset(env, obj, f->get_offset()); + return GetLongFieldOffset(jni_env, obj, f->get_offset()); } //GetLongField -jfloat JNICALL GetFloatFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jfloat JNICALL GetFloatFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -340,27 +382,31 @@ return val; } -jfloat JNICALL GetFloatField(JNIEnv *env, +jfloat JNICALL GetFloatField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetFloatField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetFloatFieldOffset(env, obj, f->get_offset()); + return GetFloatFieldOffset(jni_env, obj, f->get_offset()); } //GetFloatField -jdouble JNICALL GetDoubleFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset) +jdouble JNICALL GetDoubleFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -371,19 +417,20 @@ return val; } -jdouble JNICALL GetDoubleField(JNIEnv *env, +jdouble JNICALL GetDoubleField(JNIEnv * jni_env, jobject obj, jfieldID fieldID) { TRACE2("jni", "GetDoubleField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(!f->is_static()); - return GetDoubleFieldOffset(env, obj, f->get_offset()); + return GetDoubleFieldOffset(jni_env, obj, f->get_offset()); } //GetDoubleField @@ -397,12 +444,15 @@ // begin SetField functions -void JNICALL SetObjectFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jobject value) +void JNICALL SetObjectFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jobject value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; ObjectHandle v = (ObjectHandle)value; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -420,28 +470,32 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetObjectField(JNIEnv *env, +void JNICALL SetObjectField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jobject value) { TRACE2("jni", "SetObjectField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetObjectFieldOffset(env, obj, f->get_offset(), value); + SetObjectFieldOffset(jni_env, obj, f->get_offset(), value); } //SetObjectField -void JNICALL SetBooleanFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jboolean value) +void JNICALL SetBooleanFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jboolean value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -450,30 +504,34 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetBooleanField(JNIEnv *env, +void JNICALL SetBooleanField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jboolean value) { TRACE2("jni", "SetBooleanField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetBooleanFieldOffset(env, obj, f->get_offset(), value); + SetBooleanFieldOffset(jni_env, obj, f->get_offset(), value); } //SetBooleanField -void JNICALL SetByteFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jbyte value) +void JNICALL SetByteFieldOffset(JNIEnv * jni_env, jobject obj, jint offset, jbyte value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; - if(VM_Global_State::loader_env->compact_fields) + if(vm_env->compact_fields) *(jbyte *)(java_ref + offset) = value; else *(jint *)(java_ref + offset) = value; @@ -481,28 +539,32 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetByteField(JNIEnv *env, +void JNICALL SetByteField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jbyte value) { TRACE2("jni", "SetByteField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetByteFieldOffset(env, obj, f->get_offset(), value); + SetByteFieldOffset(jni_env, obj, f->get_offset(), value); } //SetByteField -void JNICALL SetCharFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jchar value) +void JNICALL SetCharFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jchar value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -511,32 +573,36 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetCharField(JNIEnv *env, +void JNICALL SetCharField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jchar value) { TRACE2("jni", "SetCharField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetCharFieldOffset(env, obj, f->get_offset(), value); + SetCharFieldOffset(jni_env, obj, f->get_offset(), value); } //SetCharField -void JNICALL SetShortFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jshort value) +void JNICALL SetShortFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jshort value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; - if (VM_Global_State::loader_env->compact_fields) + if (vm_env->compact_fields) *(jshort *)(java_ref + offset) = value; else *(jint *)(java_ref + offset) = value; @@ -544,28 +610,32 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetShortField(JNIEnv *env, +void JNICALL SetShortField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jshort value) { TRACE2("jni", "SetShortField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetShortFieldOffset(env, obj, f->get_offset(), value); + SetShortFieldOffset(jni_env, obj, f->get_offset(), value); } //SetShortField -void JNICALL SetIntFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jint value) +void JNICALL SetIntFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jint value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -574,28 +644,32 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetIntField(JNIEnv *env, +void JNICALL SetIntField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jint value) { TRACE2("jni", "SetIntField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetIntFieldOffset(env, obj, f->get_offset(), value); + SetIntFieldOffset(jni_env, obj, f->get_offset(), value); } //SetIntField -void JNICALL SetLongFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jlong value) +void JNICALL SetLongFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jlong value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -604,27 +678,31 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetLongField(JNIEnv *env, +void JNICALL SetLongField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jlong value) { TRACE2("jni", "SetLongField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetLongFieldOffset(env, obj, f->get_offset(), value); + SetLongFieldOffset(jni_env, obj, f->get_offset(), value); } //SetLongField -void JNICALL SetFloatFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jfloat value) +void JNICALL SetFloatFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jfloat value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -633,28 +711,32 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetFloatField(JNIEnv *env, +void JNICALL SetFloatField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jfloat value) { TRACE2("jni", "SetFloatField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetFloatFieldOffset(env, obj, f->get_offset(), value); + SetFloatFieldOffset(jni_env, obj, f->get_offset(), value); } //SetFloatField -void JNICALL SetDoubleFieldOffset(JNIEnv * UNREF env, jobject obj, jint offset, jdouble value) +void JNICALL SetDoubleFieldOffset(JNIEnv * UNREF jni_env, jobject obj, jint offset, jdouble value) { assert(hythread_is_suspend_enabled()); ObjectHandle h = (ObjectHandle)obj; + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; @@ -663,20 +745,21 @@ tmn_suspend_enable(); //---------------------------------^ } -void JNICALL SetDoubleField(JNIEnv *env, +void JNICALL SetDoubleField(JNIEnv * jni_env, jobject obj, jfieldID fieldID, jdouble value) { TRACE2("jni", "SetDoubleField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + Field *f = (Field *)fieldID; assert(f); - assert(IsInstanceOf(env, obj, struct_Class_to_jclass(f->get_class()))); + assert(IsInstanceOf(jni_env, obj, struct_Class_to_jclass(f->get_class()))); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(!f->is_static()); - SetDoubleFieldOffset(env, obj, f->get_offset(), value); + SetDoubleFieldOffset(jni_env, obj, f->get_offset(), value); } //SetDoubleField @@ -693,15 +776,19 @@ #include "jit_runtime_support_common.h" #endif -jobject JNICALL GetStaticObjectField(JNIEnv *env, +jobject JNICALL GetStaticObjectField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticObjectField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return NULL; assert(f->is_static()); tmn_suspend_disable(); //---------------------------------v ManagedObject **field_addr = (ManagedObject **)f->get_address(); @@ -721,113 +808,145 @@ return (jobject)new_handle; } //GetStaticObjectField -jboolean JNICALL GetStaticBooleanField(JNIEnv *env, +jboolean JNICALL GetStaticBooleanField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticBooleanField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jboolean *field_addr = (jboolean *)f->get_address(); return *field_addr; } //GetStaticBooleanField -jbyte JNICALL GetStaticByteField(JNIEnv *env, +jbyte JNICALL GetStaticByteField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticByteField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jbyte *field_addr = (jbyte *)f->get_address(); return *field_addr; } //GetStaticByteField -jchar JNICALL GetStaticCharField(JNIEnv *env, +jchar JNICALL GetStaticCharField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticCharField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jchar *field_addr = (jchar *)f->get_address(); return *field_addr; } //GetStaticCharField -jshort JNICALL GetStaticShortField(JNIEnv *env, +jshort JNICALL GetStaticShortField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticShortField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jshort *field_addr = (jshort *)f->get_address(); return *field_addr; } //GetStaticShortField -jint JNICALL GetStaticIntField(JNIEnv *env, +jint JNICALL GetStaticIntField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticIntField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jint *field_addr = (jint *)f->get_address(); return *field_addr; } //GetStaticIntField -jlong JNICALL GetStaticLongField(JNIEnv *env, +jlong JNICALL GetStaticLongField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticLongField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jlong *field_addr = (jlong *)f->get_address(); return *field_addr; } //GetStaticLongField -jfloat JNICALL GetStaticFloatField(JNIEnv *env, +jfloat JNICALL GetStaticFloatField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticFloatField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jfloat *field_addr = (jfloat *)f->get_address(); return *field_addr; } //GetStaticFloatField -jdouble JNICALL GetStaticDoubleField(JNIEnv *env, +jdouble JNICALL GetStaticDoubleField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID) { TRACE2("jni", "GetStaticDoubleField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return 0; + if (!ensure_initialised(jni_env, f->get_class())) return 0; assert(f->is_static()); jdouble *field_addr = (jdouble *)f->get_address(); return *field_addr; @@ -845,16 +964,20 @@ // begin SetStaticField functions -void JNICALL SetStaticObjectField(JNIEnv *env, +void JNICALL SetStaticObjectField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jobject value) { TRACE2("jni", "SetStaticObjectField called, id = " << fieldID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); tmn_suspend_disable(); //---------------------------------v ManagedObject **field_addr = (ManagedObject **)f->get_address(); @@ -871,88 +994,108 @@ } //SetStaticObjectField -void JNICALL SetStaticBooleanField(JNIEnv *env, +void JNICALL SetStaticBooleanField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jboolean value) { TRACE2("jni", "SetStaticBooleanField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jboolean *field_addr = (jboolean *)f->get_address(); *field_addr = value; } //SetStaticBooleanField -void JNICALL SetStaticByteField(JNIEnv *env, +void JNICALL SetStaticByteField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jbyte value) { TRACE2("jni", "SetStaticByteField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jbyte *field_addr = (jbyte *)f->get_address(); jint *field_addr_int = (jint *)f->get_address(); - if (VM_Global_State::loader_env->compact_fields) + if (vm_env->compact_fields) *field_addr = value; else *field_addr_int = value; } //SetStaticByteField -void JNICALL SetStaticCharField(JNIEnv *env, +void JNICALL SetStaticCharField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jchar value) { TRACE2("jni", "SetStaticCharField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jchar *field_addr = (jchar *)f->get_address(); *field_addr = value; } //SetStaticCharField -void JNICALL SetStaticShortField(JNIEnv *env, +void JNICALL SetStaticShortField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jshort value) { TRACE2("jni", "SetStaticShortField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jshort *field_addr = (jshort *)f->get_address(); jint *field_addr_int = (jint *)f->get_address(); - if (VM_Global_State::loader_env->compact_fields) + if (vm_env->compact_fields) *field_addr = value; else *field_addr_int = value; } //SetStaticShortField -void JNICALL SetStaticIntField(JNIEnv *env, +void JNICALL SetStaticIntField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jint value) { TRACE2("jni", "SetStaticIntField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jint *field_addr = (jint *)f->get_address(); *field_addr = value; @@ -960,48 +1103,60 @@ -void JNICALL SetStaticLongField(JNIEnv *env, +void JNICALL SetStaticLongField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jlong value) { TRACE2("jni", "SetStaticLongField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jlong *field_addr = (jlong *)f->get_address(); *field_addr = value; } //SetStaticLongField -void JNICALL SetStaticFloatField(JNIEnv *env, +void JNICALL SetStaticFloatField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jfloat value) { TRACE2("jni", "SetStaticFloatField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jfloat *field_addr = (jfloat *)f->get_address(); *field_addr = value; } //SetStaticFloatField -void JNICALL SetStaticDoubleField(JNIEnv *env, +void JNICALL SetStaticDoubleField(JNIEnv * jni_env, jclass UNREF clazz, jfieldID fieldID, jdouble value) { TRACE2("jni", "SetStaticDoubleField called, id = " << fieldID << " value = " << value); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + Field *f = (Field *)fieldID; assert(f); - if (!ensure_initialised(env, f->get_class())) return; + if (!ensure_initialised(jni_env, f->get_class())) return; assert(f->is_static()); jdouble *field_addr = (jdouble *)f->get_address(); *field_addr = value; Index: trunk/vm/vmcore/src/jni/jni_method.cpp =================================================================== --- trunk/vm/vmcore/src/jni/jni_method.cpp (revision 487462) +++ trunk/vm/vmcore/src/jni/jni_method.cpp (working copy) @@ -57,7 +57,7 @@ } // lookup_method_clinit -jmethodID JNICALL GetMethodID(JNIEnv *env, +jmethodID JNICALL GetMethodID(JNIEnv * jni_env, jclass clazz, const char *name, const char *descr) @@ -66,13 +66,16 @@ assert(hythread_is_suspend_enabled()); assert(clazz); + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + Class* clss = jclass_to_struct_Class(clazz); Method *method; if ('<' == *name) { if (!strcmp(name + 1, "init>")) { method = lookup_method_init(clss, descr); } else { - ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchMethodError", name); return NULL; } } else { @@ -80,7 +83,7 @@ } if(!method || method->is_static()) { - ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchMethodError", name); return NULL; } TRACE2("jni", "GetMethodID " << clss->get_name()->bytes @@ -91,21 +94,24 @@ -jmethodID JNICALL GetStaticMethodID(JNIEnv *env, +jmethodID JNICALL GetStaticMethodID(JNIEnv * jni_env, jclass clazz, const char *name, const char *descr) { TRACE2("jni", "GetStaticMethodID called"); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + Class* clss = jclass_to_struct_Class(clazz); - Method *method; if ('<' == *name) { if (!strcmp(name + 1, "clinit>") && !strcmp(descr, "()V")) { method = lookup_method_clinit(clss); } else { - ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchMethodError", name); return NULL; } } else { @@ -113,7 +119,7 @@ } if(!method || !method->is_static()) { - ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); + ThrowNew_Quick(jni_env, "java/lang/NoSuchMethodError", name); return NULL; } TRACE2("jni", "GetStaticMethodID " << clss->get_name()->bytes @@ -146,7 +152,7 @@ // begin CallMethodA functions -static void call_method_no_ref_result(JNIEnv *env, +static void call_method_no_ref_result(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args, @@ -166,12 +172,12 @@ // class_parse_methods() in Class_File_Loader.cpp, // and to add similar functionality to interpreter if (method->is_abstract()) { - ThrowNew_Quick (env, "java/lang/AbstractMethodError", + ThrowNew_Quick (jni_env, "java/lang/AbstractMethodError", "attempt to invoke abstract method"); return; } - if (!ensure_initialised(env, method->get_class())) + if (!ensure_initialised(jni_env, method->get_class())) return; unsigned num_args = method->get_num_args(); @@ -187,70 +193,78 @@ -void JNICALL CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +void JNICALL CallVoidMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallVoidMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - CallVoidMethodV(env, obj, methodID, args); + CallVoidMethodV(jni_env, obj, methodID, args); } //CallVoidMethod -void JNICALL CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void JNICALL CallVoidMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallVoidMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - CallVoidMethodA(env, obj, methodID, jvalue_args); + CallVoidMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); } //CallVoidMethodV -void JNICALL CallVoidMethodA(JNIEnv *env, +void JNICALL CallVoidMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallVoidMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); - call_method_no_ref_result(env, obj, methodID, args, 0, FALSE); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + call_method_no_ref_result(jni_env, obj, methodID, args, 0, FALSE); } //CallVoidMethodA -jobject JNICALL CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jobject JNICALL CallObjectMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallObjectMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallObjectMethodV(env, obj, methodID, args); + return CallObjectMethodV(jni_env, obj, methodID, args); } //CallObjectMethod -jobject JNICALL CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jobject JNICALL CallObjectMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallObjectMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jobject result = CallObjectMethodA(env, obj, methodID, jvalue_args); + jobject result = CallObjectMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallObjectMethodV -jobject JNICALL CallObjectMethodA(JNIEnv *env, +jobject JNICALL CallObjectMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallObjectMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + jvalue result; Method *method = (Method *)methodID; // resolve to actual vtable entry below @@ -264,12 +278,12 @@ // class_parse_methods() in Class_File_Loader.cpp, // and to add similar functionality to interpreter if (method->is_abstract()) { - ThrowNew_Quick (env, "java/lang/AbstractMethodError", + ThrowNew_Quick (jni_env, "java/lang/AbstractMethodError", "attempt to invoke abstract method"); return NULL; } - if (!ensure_initialised(env, method->get_class())) + if (!ensure_initialised(jni_env, method->get_class())) return NULL; unsigned num_args = method->get_num_args(); @@ -287,301 +301,335 @@ -jboolean JNICALL CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jboolean JNICALL CallBooleanMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallBooleanMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallBooleanMethodV(env, obj, methodID, args); + return CallBooleanMethodV(jni_env, obj, methodID, args); } //CallBooleanMethod -jboolean JNICALL CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jboolean JNICALL CallBooleanMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallBooleanMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jboolean result = CallBooleanMethodA(env, obj, methodID, jvalue_args); + jboolean result = CallBooleanMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallBooleanMethodV -jboolean JNICALL CallBooleanMethodA(JNIEnv *env, +jboolean JNICALL CallBooleanMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallBooleanMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.z; } //CallBooleanMethodA -jbyte JNICALL CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jbyte JNICALL CallByteMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallByteMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallByteMethodV(env, obj, methodID, args); + return CallByteMethodV(jni_env, obj, methodID, args); } //CallByteMethod -jbyte JNICALL CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jbyte JNICALL CallByteMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallByteMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jbyte result = CallByteMethodA(env, obj, methodID, jvalue_args); + jbyte result = CallByteMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallByteMethodV -jbyte JNICALL CallByteMethodA(JNIEnv *env, +jbyte JNICALL CallByteMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallByteMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.b; } //CallByteMethodA -jchar JNICALL CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) + + +jchar JNICALL CallCharMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallCharMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallCharMethodV(env, obj, methodID, args); + return CallCharMethodV(jni_env, obj, methodID, args); } //CallCharMethod -jchar JNICALL CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jchar JNICALL CallCharMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallCharMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jchar result = CallCharMethodA(env, obj, methodID, jvalue_args); + jchar result = CallCharMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallCharMethodV -jchar JNICALL CallCharMethodA(JNIEnv *env, +jchar JNICALL CallCharMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallCharMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.c; } //CallCharMethodA -jshort JNICALL CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jshort JNICALL CallShortMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallShortMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallShortMethodV(env, obj, methodID, args); + return CallShortMethodV(jni_env, obj, methodID, args); } //CallShortMethod -jshort JNICALL CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jshort JNICALL CallShortMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallShortMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jshort result = CallShortMethodA(env, obj, methodID, jvalue_args); + jshort result = CallShortMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallShortMethodV -jshort JNICALL CallShortMethodA(JNIEnv *env, +jshort JNICALL CallShortMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallShortMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.s; } //CallShortMethodA -jint JNICALL CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jint JNICALL CallIntMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallIntMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallIntMethodV(env, obj, methodID, args); + return CallIntMethodV(jni_env, obj, methodID, args); } //CallIntMethod -jint JNICALL CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jint JNICALL CallIntMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallIntMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jint result = CallIntMethodA(env, obj, methodID, jvalue_args); + jint result = CallIntMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallIntMethodV -jint JNICALL CallIntMethodA(JNIEnv *env, +jint JNICALL CallIntMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallIntMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.i; } //CallIntMethodA -jlong JNICALL CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jlong JNICALL CallLongMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallLongMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallLongMethodV(env, obj, methodID, args); + return CallLongMethodV(jni_env, obj, methodID, args); } //CallLongMethod -jlong JNICALL CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jlong JNICALL CallLongMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallLongMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jlong result = CallLongMethodA(env, obj, methodID, jvalue_args); + jlong result = CallLongMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallLongMethodV -jlong JNICALL CallLongMethodA(JNIEnv *env, +jlong JNICALL CallLongMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallLongMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.j; } //CallLongMethodA -jfloat JNICALL CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jfloat JNICALL CallFloatMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallFloatMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallFloatMethodV(env, obj, methodID, args); + return CallFloatMethodV(jni_env, obj, methodID, args); } //CallFloatMethod -jfloat JNICALL CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jfloat JNICALL CallFloatMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallFloatMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jfloat result = CallFloatMethodA(env, obj, methodID, jvalue_args); + jfloat result = CallFloatMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallFloatMethodV -jfloat JNICALL CallFloatMethodA(JNIEnv *env, +jfloat JNICALL CallFloatMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallFloatMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.f; } //CallFloatMethodA -jdouble JNICALL CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jdouble JNICALL CallDoubleMethod(JNIEnv * jni_env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallDoubleMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallDoubleMethodV(env, obj, methodID, args); + return CallDoubleMethodV(jni_env, obj, methodID, args); } //CallDoubleMethod -jdouble JNICALL CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jdouble JNICALL CallDoubleMethodV(JNIEnv * jni_env, jobject obj, jmethodID methodID, va_list args) { TRACE2("jni", "CallDoubleMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jdouble result = CallDoubleMethodA(env, obj, methodID, jvalue_args); + jdouble result = CallDoubleMethodA(jni_env, obj, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallDoubleMethodV -jdouble JNICALL CallDoubleMethodA(JNIEnv *env, +jdouble JNICALL CallDoubleMethodA(JNIEnv * jni_env, jobject obj, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallDoubleMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, FALSE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, FALSE); return result.d; } //CallDoubleMethodA @@ -597,7 +645,7 @@ // begin CallNonvirtualMethodA functions -void JNICALL CallNonvirtualVoidMethod(JNIEnv *env, +void JNICALL CallNonvirtualVoidMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -607,12 +655,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - CallNonvirtualVoidMethodV(env, obj, clazz, methodID, args); + CallNonvirtualVoidMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualVoidMethod -void JNICALL CallNonvirtualVoidMethodV(JNIEnv *env, +void JNICALL CallNonvirtualVoidMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -621,13 +669,13 @@ TRACE2("jni", "CallNonvirtualVoidMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - CallNonvirtualVoidMethodA(env, obj, clazz, methodID, jvalue_args); + CallNonvirtualVoidMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); } //CallNonvirtualVoidMethodV -void JNICALL CallNonvirtualVoidMethodA(JNIEnv *env, +void JNICALL CallNonvirtualVoidMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -635,12 +683,16 @@ { TRACE2("jni", "CallNonvirtualVoidMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); - call_method_no_ref_result(env, obj, methodID, args, 0, TRUE); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + call_method_no_ref_result(jni_env, obj, methodID, args, 0, TRUE); } //CallNonvirtualVoidMethodA -jobject JNICALL CallNonvirtualObjectMethod(JNIEnv *env, +jobject JNICALL CallNonvirtualObjectMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -650,12 +702,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualObjectMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualObjectMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualObjectMethod -jobject JNICALL CallNonvirtualObjectMethodV(JNIEnv *env, +jobject JNICALL CallNonvirtualObjectMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -664,14 +716,14 @@ TRACE2("jni", "CallNonvirtualObjectMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jobject result = CallNonvirtualObjectMethodA(env, obj, clazz, methodID, jvalue_args); + jobject result = CallNonvirtualObjectMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualObjectMethodV -jobject JNICALL CallNonvirtualObjectMethodA(JNIEnv *env, +jobject JNICALL CallNonvirtualObjectMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -679,9 +731,13 @@ { TRACE2("jni", "CallNonvirtualObjectMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + jvalue result; Method *method = (Method *)methodID; - if (!ensure_initialised(env, method->get_class())) + if (!ensure_initialised(jni_env, method->get_class())) return NULL; unsigned num_args = method->get_num_args(); jvalue *all_args = (jvalue*) STD_ALLOCA(num_args * sizeof(jvalue)); @@ -691,14 +747,14 @@ memcpy(all_args + 1, args, (num_args - 1) * sizeof(jvalue)); tmn_suspend_disable(); vm_execute_java_method_array(methodID, &result, all_args); - tmn_suspend_enable(); + tmn_suspend_enable(); return result.l; } //CallNonvirtualObjectMethodA -jboolean JNICALL CallNonvirtualBooleanMethod(JNIEnv *env, +jboolean JNICALL CallNonvirtualBooleanMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -708,12 +764,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualBooleanMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualBooleanMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualBooleanMethod -jboolean JNICALL CallNonvirtualBooleanMethodV(JNIEnv *env, +jboolean JNICALL CallNonvirtualBooleanMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -722,14 +778,14 @@ TRACE2("jni", "CallNonvirtualBooleanMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jboolean result = CallNonvirtualBooleanMethodA(env, obj, clazz, methodID, jvalue_args); + jboolean result = CallNonvirtualBooleanMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualBooleanMethodV -jboolean JNICALL CallNonvirtualBooleanMethodA(JNIEnv *env, +jboolean JNICALL CallNonvirtualBooleanMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -737,14 +793,18 @@ { TRACE2("jni", "CallNonvirtualBooleanMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.z; } //CallNonvirtualBooleanMethodA -jbyte JNICALL CallNonvirtualByteMethod(JNIEnv *env, +jbyte JNICALL CallNonvirtualByteMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -754,12 +814,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualByteMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualByteMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualByteMethod -jbyte JNICALL CallNonvirtualByteMethodV(JNIEnv *env, +jbyte JNICALL CallNonvirtualByteMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -768,14 +828,14 @@ TRACE2("jni", "CallNonvirtualByteMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jbyte result = CallNonvirtualByteMethodA(env, obj, clazz, methodID, jvalue_args); + jbyte result = CallNonvirtualByteMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualByteMethodV -jbyte JNICALL CallNonvirtualByteMethodA(JNIEnv *env, +jbyte JNICALL CallNonvirtualByteMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -783,14 +843,18 @@ { TRACE2("jni", "CallNonvirtualByteMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.b; } //CallNonvirtualByteMethodA -jchar JNICALL CallNonvirtualCharMethod(JNIEnv *env, +jchar JNICALL CallNonvirtualCharMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -800,12 +864,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualCharMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualCharMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualCharMethod -jchar JNICALL CallNonvirtualCharMethodV(JNIEnv *env, +jchar JNICALL CallNonvirtualCharMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -814,14 +878,14 @@ TRACE2("jni", "CallNonvirtualCharMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jchar result = CallNonvirtualCharMethodA(env, obj, clazz, methodID, jvalue_args); + jchar result = CallNonvirtualCharMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualCharMethodV -jchar JNICALL CallNonvirtualCharMethodA(JNIEnv *env, +jchar JNICALL CallNonvirtualCharMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -829,14 +893,18 @@ { TRACE2("jni", "CallNonvirtualCharMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.c; } //CallNonvirtualCharMethodA -jshort JNICALL CallNonvirtualShortMethod(JNIEnv *env, +jshort JNICALL CallNonvirtualShortMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -846,12 +914,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualShortMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualShortMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualShortMethod -jshort JNICALL CallNonvirtualShortMethodV(JNIEnv *env, +jshort JNICALL CallNonvirtualShortMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -860,14 +928,14 @@ TRACE2("jni", "CallNonvirtualShortMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jshort result = CallNonvirtualShortMethodA(env, obj, clazz, methodID, jvalue_args); + jshort result = CallNonvirtualShortMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualShortMethodV -jshort JNICALL CallNonvirtualShortMethodA(JNIEnv *env, +jshort JNICALL CallNonvirtualShortMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -875,14 +943,18 @@ { TRACE2("jni", "CallNonvirtualShortMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.s; } //CallNonvirtualShortMethodA -jint JNICALL CallNonvirtualIntMethod(JNIEnv *env, +jint JNICALL CallNonvirtualIntMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -892,12 +964,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualIntMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualIntMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualIntMethod -jint JNICALL CallNonvirtualIntMethodV(JNIEnv *env, +jint JNICALL CallNonvirtualIntMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -906,14 +978,14 @@ TRACE2("jni", "CallNonvirtualIntMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jint result = CallNonvirtualIntMethodA(env, obj, clazz, methodID, jvalue_args); + jint result = CallNonvirtualIntMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualIntMethodV -jint JNICALL CallNonvirtualIntMethodA(JNIEnv *env, +jint JNICALL CallNonvirtualIntMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -921,14 +993,18 @@ { TRACE2("jni", "CallNonvirtualIntMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.i; } //CallNonvirtualIntMethodA -jlong JNICALL CallNonvirtualLongMethod(JNIEnv *env, +jlong JNICALL CallNonvirtualLongMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -938,12 +1014,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualLongMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualLongMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualLongMethod -jlong JNICALL CallNonvirtualLongMethodV(JNIEnv *env, +jlong JNICALL CallNonvirtualLongMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -952,14 +1028,14 @@ TRACE2("jni", "CallNonvirtualLongMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jlong result = CallNonvirtualLongMethodA(env, obj, clazz, methodID, jvalue_args); + jlong result = CallNonvirtualLongMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualLongMethodV -jlong JNICALL CallNonvirtualLongMethodA(JNIEnv *env, +jlong JNICALL CallNonvirtualLongMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -967,14 +1043,18 @@ { TRACE2("jni", "CallNonvirtualLongMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.j; } //CallNonvirtualLongMethodA -jfloat JNICALL CallNonvirtualFloatMethod(JNIEnv *env, +jfloat JNICALL CallNonvirtualFloatMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -984,12 +1064,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualFloatMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualFloatMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualFloatMethod -jfloat JNICALL CallNonvirtualFloatMethodV(JNIEnv *env, +jfloat JNICALL CallNonvirtualFloatMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -998,29 +1078,33 @@ TRACE2("jni", "CallNonvirtualFloatMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jfloat result = CallNonvirtualFloatMethodA(env, obj, clazz, methodID, jvalue_args); + jfloat result = CallNonvirtualFloatMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualFloatMethodV -jfloat JNICALL CallNonvirtualFloatMethodA(JNIEnv *env, - jobject obj, - jclass UNREF clazz, - jmethodID methodID, - jvalue *args) +jfloat JNICALL CallNonvirtualFloatMethodA(JNIEnv * jni_env, + jobject obj, + jclass UNREF clazz, + jmethodID methodID, + jvalue *args) { TRACE2("jni", "CallNonvirtualFloatMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.f; } //CallNonvirtualFloatMethodA -jdouble JNICALL CallNonvirtualDoubleMethod(JNIEnv *env, +jdouble JNICALL CallNonvirtualDoubleMethod(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -1030,12 +1114,12 @@ assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallNonvirtualDoubleMethodV(env, obj, clazz, methodID, args); + return CallNonvirtualDoubleMethodV(jni_env, obj, clazz, methodID, args); } //CallNonvirtualDoubleMethod -jdouble JNICALL CallNonvirtualDoubleMethodV(JNIEnv *env, +jdouble JNICALL CallNonvirtualDoubleMethodV(JNIEnv * jni_env, jobject obj, jclass clazz, jmethodID methodID, @@ -1044,14 +1128,14 @@ TRACE2("jni", "CallNonvirtualDoubleMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jdouble result = CallNonvirtualDoubleMethodA(env, obj, clazz, methodID, jvalue_args); + jdouble result = CallNonvirtualDoubleMethodA(jni_env, obj, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallNonvirtualDoubleMethodV -jdouble JNICALL CallNonvirtualDoubleMethodA(JNIEnv *env, +jdouble JNICALL CallNonvirtualDoubleMethodA(JNIEnv * jni_env, jobject obj, jclass UNREF clazz, jmethodID methodID, @@ -1059,8 +1143,12 @@ { TRACE2("jni", "CallNonvirtualDoubleMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_method_no_ref_result(env, obj, methodID, args, &result, TRUE); + call_method_no_ref_result(jni_env, obj, methodID, args, &result, TRUE); return result.d; } //CallNonvirtualDoubleMethodA @@ -1075,7 +1163,7 @@ // begin CallStaticMethodA functions -static void call_static_method_no_ref_result(JNIEnv *env, +static void call_static_method_no_ref_result(JNIEnv * jni_env, jclass UNREF clazz, jmethodID methodID, jvalue *args, @@ -1083,7 +1171,7 @@ { assert(hythread_is_suspend_enabled()); Method *method = (Method *)methodID; - if (!ensure_initialised(env, method->get_class())) + if (!ensure_initialised(jni_env, method->get_class())) return; tmn_suspend_disable(); vm_execute_java_method_array(methodID, result, args); @@ -1092,39 +1180,43 @@ -jobject JNICALL CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jobject JNICALL CallStaticObjectMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticObjectMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticObjectMethodV(env, clazz, methodID, args); + return CallStaticObjectMethodV(jni_env, clazz, methodID, args); } //CallStaticObjectMethod -jobject JNICALL CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jobject JNICALL CallStaticObjectMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticObjectMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jobject result = CallStaticObjectMethodA(env, clazz, methodID, jvalue_args); + jobject result = CallStaticObjectMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticObjectMethodV -jobject JNICALL CallStaticObjectMethodA(JNIEnv *env, +jobject JNICALL CallStaticObjectMethodA(JNIEnv * jni_env, jclass UNREF clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticObjectMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return NULL; + jvalue result; Method *method = (Method *)methodID; - if (!ensure_initialised(env, method->get_class())) + if (!ensure_initialised(jni_env, method->get_class())) return NULL; unsigned num_args = method->get_num_args(); jvalue *all_args = (jvalue*) STD_ALLOCA(num_args * sizeof(jvalue)); @@ -1139,332 +1231,368 @@ -jboolean JNICALL CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jboolean JNICALL CallStaticBooleanMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticBooleanMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticBooleanMethodV(env, clazz, methodID, args); + return CallStaticBooleanMethodV(jni_env, clazz, methodID, args); } //CallStaticBooleanMethod -jboolean JNICALL CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jboolean JNICALL CallStaticBooleanMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticBooleanMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jboolean result = CallStaticBooleanMethodA(env, clazz, methodID, jvalue_args); + jboolean result = CallStaticBooleanMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticBooleanMethodV -jboolean JNICALL CallStaticBooleanMethodA(JNIEnv *env, +jboolean JNICALL CallStaticBooleanMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticBooleanMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.z; } //CallStaticBooleanMethodA -jbyte JNICALL CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jbyte JNICALL CallStaticByteMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticByteMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticByteMethodV(env, clazz, methodID, args); + return CallStaticByteMethodV(jni_env, clazz, methodID, args); } //CallStaticByteMethod -jbyte JNICALL CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jbyte JNICALL CallStaticByteMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticByteMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jbyte result = CallStaticByteMethodA(env, clazz, methodID, jvalue_args); + jbyte result = CallStaticByteMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticByteMethodV -jbyte JNICALL CallStaticByteMethodA(JNIEnv *env, +jbyte JNICALL CallStaticByteMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticByteMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.b; } //CallStaticByteMethodA -jchar JNICALL CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jchar JNICALL CallStaticCharMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticCharMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticCharMethodV(env, clazz, methodID, args); + return CallStaticCharMethodV(jni_env, clazz, methodID, args); } //CallStaticCharMethod -jchar JNICALL CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jchar JNICALL CallStaticCharMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticCharMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jchar result = CallStaticCharMethodA(env, clazz, methodID, jvalue_args); + jchar result = CallStaticCharMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticCharMethodV -jchar JNICALL CallStaticCharMethodA(JNIEnv *env, +jchar JNICALL CallStaticCharMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticCharMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.c; } //CallStaticCharMethodA -jshort JNICALL CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jshort JNICALL CallStaticShortMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticShortMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticShortMethodV(env, clazz, methodID, args); + return CallStaticShortMethodV(jni_env, clazz, methodID, args); } //CallStaticShortMethod -jshort JNICALL CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jshort JNICALL CallStaticShortMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticShortMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jshort result = CallStaticShortMethodA(env, clazz, methodID, jvalue_args); + jshort result = CallStaticShortMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticShortMethodV -jshort JNICALL CallStaticShortMethodA(JNIEnv *env, +jshort JNICALL CallStaticShortMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticShortMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.s; } //CallStaticShortMethodA -jint JNICALL CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jint JNICALL CallStaticIntMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticIntMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticIntMethodV(env, clazz, methodID, args); + return CallStaticIntMethodV(jni_env, clazz, methodID, args); } //CallStaticIntMethod -jint JNICALL CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jint JNICALL CallStaticIntMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticIntMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jint result = CallStaticIntMethodA(env, clazz, methodID, jvalue_args); + jint result = CallStaticIntMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticIntMethodV -jint JNICALL CallStaticIntMethodA(JNIEnv *env, +jint JNICALL CallStaticIntMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticIntMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.i; } //CallStaticIntMethodA -jlong JNICALL CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jlong JNICALL CallStaticLongMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticLongMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticLongMethodV(env, clazz, methodID, args); + return CallStaticLongMethodV(jni_env, clazz, methodID, args); } //CallStaticLongMethod -jlong JNICALL CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jlong JNICALL CallStaticLongMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticLongMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jlong result = CallStaticLongMethodA(env, clazz, methodID, jvalue_args); + jlong result = CallStaticLongMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticLongMethodV -jlong JNICALL CallStaticLongMethodA(JNIEnv *env, +jlong JNICALL CallStaticLongMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticLongMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.j; } //CallStaticLongMethodA -jfloat JNICALL CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jfloat JNICALL CallStaticFloatMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticFloatMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticFloatMethodV(env, clazz, methodID, args); + return CallStaticFloatMethodV(jni_env, clazz, methodID, args); } //CallStaticFloatMethod -jfloat JNICALL CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jfloat JNICALL CallStaticFloatMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticFloatMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jfloat result = CallStaticFloatMethodA(env, clazz, methodID, jvalue_args); + jfloat result = CallStaticFloatMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticFloatMethodV -jfloat JNICALL CallStaticFloatMethodA(JNIEnv *env, +jfloat JNICALL CallStaticFloatMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticFloatMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.f; } //CallStaticFloatMethodA -jdouble JNICALL CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jdouble JNICALL CallStaticDoubleMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticDoubleMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - return CallStaticDoubleMethodV(env, clazz, methodID, args); + return CallStaticDoubleMethodV(jni_env, clazz, methodID, args); } //CallStaticDoubleMethod -jdouble JNICALL CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jdouble JNICALL CallStaticDoubleMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticDoubleMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - jdouble result = CallStaticDoubleMethodA(env, clazz, methodID, jvalue_args); + jdouble result = CallStaticDoubleMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); return result; } //CallStaticDoubleMethodV -jdouble JNICALL CallStaticDoubleMethodA(JNIEnv *env, +jdouble JNICALL CallStaticDoubleMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticDoubleMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return 0; + jvalue result; - call_static_method_no_ref_result(env, clazz, methodID, args, &result); + call_static_method_no_ref_result(jni_env, clazz, methodID, args, &result); return result.d; } //CallStaticDoubleMethodA -void JNICALL CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +void JNICALL CallStaticVoidMethod(JNIEnv * jni_env, jclass clazz, jmethodID methodID, ...) { TRACE2("jni", "CallStaticVoidMethod called, id = " << methodID); assert(hythread_is_suspend_enabled()); va_list args; va_start(args, methodID); - CallStaticVoidMethodV(env, clazz, methodID, args); + CallStaticVoidMethodV(jni_env, clazz, methodID, args); } //CallStaticVoidMethod -void JNICALL CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +void JNICALL CallStaticVoidMethodV(JNIEnv * jni_env, jclass clazz, jmethodID methodID, va_list args) { TRACE2("jni", "CallStaticVoidMethodV called, id = " << methodID); assert(hythread_is_suspend_enabled()); jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args); - CallStaticVoidMethodA(env, clazz, methodID, jvalue_args); + CallStaticVoidMethodA(jni_env, clazz, methodID, jvalue_args); STD_FREE(jvalue_args); } //CallStaticVoidMethodV -void JNICALL CallStaticVoidMethodA(JNIEnv *env, +void JNICALL CallStaticVoidMethodA(JNIEnv * jni_env, jclass clazz, jmethodID methodID, jvalue *args) { TRACE2("jni", "CallStaticVoidMethodA called, id = " << methodID); assert(hythread_is_suspend_enabled()); - call_static_method_no_ref_result(env, clazz, methodID, args, 0); + + Global_Env * vm_env = jni_get_vm_env(jni_env); + if (vm_env->IsVmShutdowning()) return; + + call_static_method_no_ref_result(jni_env, clazz, methodID, args, 0); } //CallStaticVoidMethodA Index: trunk/vm/vmcore/src/stack/stack_trace.cpp =================================================================== --- trunk/vm/vmcore/src/stack/stack_trace.cpp (revision 487462) +++ trunk/vm/vmcore/src/stack/stack_trace.cpp (working copy) @@ -19,7 +19,6 @@ * @version $Revision: 1.1.2.1.4.3 $ */ - #include "m2n.h" #include "stack_iterator.h" #include "stack_trace.h" @@ -29,6 +28,7 @@ #include "method_lookup.h" #include "cci.h" #include "class_member.h" +#include "open/hythread.h" void get_file_and_line(Method_Handle mh, void *ip, bool is_ip_past, const char **file, int *line) { Method *method = (Method*)mh; @@ -211,16 +211,50 @@ buf->AppendBlock("\n"); } -void st_print(FILE* f) +void st_print_all(FILE* f) { + hythread_t native_thread; + hythread_iterator_t iterator; + + assert(hythread_is_suspend_enabled()); + + hythread_suspend_all(&iterator, NULL); + while(native_thread = hythread_iterator_next(&iterator)) { + st_print(f, native_thread); + } + hythread_resume_all(NULL); +} + +void st_print(FILE* f, hythread_t thread) { - fprintf(f, "Stack Trace (%p):\n", p_TLS_vmthread); - StackIterator* si = si_create_from_native(); + VM_thread * vm_thread; + + assert(hythread_is_suspend_enabled()); + + vm_thread = get_vm_thread(thread); + + if (vm_thread == NULL) { + // Do not print native stack. + return; + } + if (vm_thread != p_TLS_vmthread) { + hythread_suspend_other(thread); + } + + // TODO: print real java name + fprintf(f, "The stack trace of the %p java thread:\n", vm_thread); + + if (interpreter_enabled()) { + interpreter.stack_dump(vm_thread); + return; + } + + StackIterator* si = si_create_from_native(vm_thread); unsigned depth = 0; while (!si_is_past_end(si)) { - fprintf(f, " [%p] %p(%c): ", p_TLS_vmthread, si_get_ip(si), (si_is_native(si) ? 'n' : 'm')); Method_Handle m = si_get_method(si); if (m) { + fprintf(f, " [%p] %p(%c): ", vm_thread, si_get_ip(si), (si_is_native(si) ? 'n' : 'm')); CodeChunkInfo* cci = si_get_code_chunk_info(si); if ( cci != NULL ) { uint32 inlined_depth = si_get_inline_depth(si); @@ -234,18 +268,19 @@ } } fprintf(f, "%s.%s%s\n", class_get_name(method_get_class(m)), method_get_name(m), method_get_descriptor(m)); - }else{ - fprintf(f, "*null*\n"); } depth++; si_goto_previous(si); } si_free(si); - fprintf(f, "End Stack Trace (%p, depth=%d)\n", p_TLS_vmthread, depth); + + if (vm_thread != p_TLS_vmthread) { + hythread_resume(thread); + } + fprintf(f, "\n"); fflush(f); - } void st_print() { - st_print(stderr); + st_print(stderr, hythread_self()); } Index: trunk/vm/vmcore/src/thread/thread_generic.cpp =================================================================== --- trunk/vm/vmcore/src/thread/thread_generic.cpp (revision 487462) +++ trunk/vm/vmcore/src/thread/thread_generic.cpp (working copy) @@ -233,23 +233,12 @@ return JNI_OK; /** TODO: Check if we need these actions!!! - jint monitor_count; - jobject * monitor_objects; - #ifndef NDEBUG hythread_t tm_native_thread = jthread_get_native_thread(); assert(tm_native_thread); assert(tm_native_thread == hythread_self()); #endif - // 2) release all owned monitors if any. - status = jthread_get_owned_monitors(java_thread, &monitor_count, &monitor_objects); - // TODO: how to deal with OutOfMemoryError? - assert(status != TM_ERROR_NONE); - for (int i = 0; i < monitor_count; i++) { - jthread_monitor_notify_all(monitor_objects[i]); - jthread_monitor_exit(monitor_objects[i]); - } // 3) Remove tm_thread_t pointer from java.lang.Thread object. vm_jthread_set_tm_data(jthread java_thread, NULL); */ Index: trunk/vm/vmcore/src/thread/thread_manager.cpp =================================================================== --- trunk/vm/vmcore/src/thread/thread_manager.cpp (revision 487462) +++ trunk/vm/vmcore/src/thread/thread_manager.cpp (working copy) @@ -184,19 +184,49 @@ void* vm_jthread_get_tm_data(jthread thread) { - JNIEnv *jenv = p_TLS_vmthread->jni_env; - jclass jThreadClass = jenv->GetObjectClass(thread); - jfieldID field_id = jenv->GetFieldID(jThreadClass, "vm_thread", "J"); - POINTER_SIZE_INT data = (POINTER_SIZE_INT)jenv->GetLongField(thread, field_id); + static int offset = -1; + Class * clazz; + Field * field; + ManagedObject * thread_obj; + Byte * java_ref; + POINTER_SIZE_INT val; - return (void *)data; + hythread_suspend_disable(); + + thread_obj = ((ObjectHandle)thread)->object; + if (offset == -1) { + clazz = thread_obj->vt()->clss; + field = class_lookup_field_recursive(clazz, "vm_thread", "J"); + offset = field->get_offset(); + } + java_ref = (Byte *)thread_obj; + val = *(POINTER_SIZE_INT *)(java_ref + offset); + + hythread_suspend_enable(); + + return (void *)val; } -void vm_jthread_set_tm_data(jthread jt, void* nt) { - JNIEnv *jenv = p_TLS_vmthread->jni_env; - jclass jthreadclass = jenv->GetObjectClass(jt); - jfieldID field_id = jenv->GetFieldID(jthreadclass, "vm_thread", "J"); - jenv->SetLongField(jt, field_id, (jlong)(POINTER_SIZE_INT)nt); +void vm_jthread_set_tm_data(jthread thread, void* val) { + static int offset = -1; + Class * clazz; + Field * field; + ManagedObject * thread_obj; + Byte * java_ref; + + hythread_suspend_disable(); + + thread_obj = ((ObjectHandle)thread)->object; + if (offset == -1) { + clazz = thread_obj->vt()->clss; + field = class_lookup_field_recursive(clazz, "vm_thread", "J"); + offset = field->get_offset(); + } + + java_ref = (Byte *)thread_obj; + *(jlong *)(java_ref + offset) = (jlong)(POINTER_SIZE_INT)val; + + hythread_suspend_enable(); } int vm_objects_are_equal(jobject obj1, jobject obj2){ Index: trunk/vm/vmcore/src/util/em64t/base/compile_em64t.cpp =================================================================== --- trunk/vm/vmcore/src/util/em64t/base/compile_em64t.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/em64t/base/compile_em64t.cpp (working copy) @@ -149,7 +149,7 @@ return addr; } - const int STUB_SIZE = 357; + const int STUB_SIZE = 416; char * stub = (char *) malloc_fixed_code_for_jit(STUB_SIZE, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_DEFAULT, CAA_Allocate); addr = stub; @@ -187,34 +187,29 @@ // compile the method stub = call(stub, (char *)&compile_jit_a_method); - // rethrow exception if it panding - stub = push(stub, rax_opnd); - stub = call(stub, (char *)&exn_rethrow_if_pending); - stub = pop(stub, rax_opnd); + // pop m2n from the stack + const int32 bytes_to_m2n_bottom = stack_size - m2n_get_size(); + stub = m2n_gen_pop_m2n(stub, false, 0, bytes_to_m2n_bottom, 1); // restore gp inputs from the stack - // NOTE: m2n_gen_pop_m2n must not destroy inputs - stub = pop(stub, rdi_opnd); - stub = pop(stub, rdi_opnd); - stub = pop(stub, rsi_opnd); - stub = pop(stub, rdx_opnd); - stub = pop(stub, rcx_opnd); - stub = pop(stub, r8_opnd); - stub = pop(stub, r9_opnd); + stub = mov(stub, rdi_opnd, M_Base_Opnd(rsp_reg, 8)); + stub = mov(stub, rsi_opnd, M_Base_Opnd(rsp_reg, 16)); + stub = mov(stub, rdx_opnd, M_Base_Opnd(rsp_reg, 24)); + stub = mov(stub, rcx_opnd, M_Base_Opnd(rsp_reg, 32)); + stub = mov(stub, r8_opnd, M_Base_Opnd(rsp_reg, 40)); + stub = mov(stub, r9_opnd, M_Base_Opnd(rsp_reg, 48)); // restore fp inputs from the stack - stub = movq(stub, xmm0_opnd, M_Base_Opnd(rsp_reg, 0)); - stub = movq(stub, xmm1_opnd, M_Base_Opnd(rsp_reg, 8)); - stub = movq(stub, xmm2_opnd, M_Base_Opnd(rsp_reg, 16)); - stub = movq(stub, xmm3_opnd, M_Base_Opnd(rsp_reg, 24)); - stub = movq(stub, xmm4_opnd, M_Base_Opnd(rsp_reg, 32)); - stub = movq(stub, xmm5_opnd, M_Base_Opnd(rsp_reg, 40)); - stub = movq(stub, xmm6_opnd, M_Base_Opnd(rsp_reg, 48)); - stub = movq(stub, xmm7_opnd, M_Base_Opnd(rsp_reg, 56)); - // pop m2n from the stack - const int32 bytes_to_m2n_bottom = 72; - stub = m2n_gen_pop_m2n(stub, false, 0, bytes_to_m2n_bottom, 1); + stub = movq(stub, xmm0_opnd, M_Base_Opnd(rsp_reg, 56)); + stub = movq(stub, xmm1_opnd, M_Base_Opnd(rsp_reg, 64)); + stub = movq(stub, xmm2_opnd, M_Base_Opnd(rsp_reg, 72)); + stub = movq(stub, xmm3_opnd, M_Base_Opnd(rsp_reg, 80)); + stub = movq(stub, xmm4_opnd, M_Base_Opnd(rsp_reg, 88)); + stub = movq(stub, xmm5_opnd, M_Base_Opnd(rsp_reg, 96)); + stub = movq(stub, xmm6_opnd, M_Base_Opnd(rsp_reg, 104)); + stub = movq(stub, xmm7_opnd, M_Base_Opnd(rsp_reg, 112)); + // adjust stack pointer - stub = alu(stub, add_opc, rsp_opnd, Imm_Opnd(bytes_to_m2n_bottom + m2n_get_size())); + stub = alu(stub, add_opc, rsp_opnd, Imm_Opnd(stack_size)); // transfer control to the compiled code stub = jump(stub, rax_opnd); Index: trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp =================================================================== --- trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp (working copy) @@ -193,12 +193,6 @@ stub = push(stub, ecx_opnd); // compile the method stub = call(stub, (char *)&compile_jit_a_method); - - // rethrow exception if it panding - stub = push(stub, eax_opnd); - stub = call(stub, (char *)&exn_rethrow_if_pending); - stub = pop(stub, eax_opnd); - // remove ecx from the stack stub = pop(stub, ecx_opnd); // pop m2n from the stack 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 487462) +++ trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (working copy) @@ -911,9 +911,9 @@ #endif char *ss = stub; - ss = pop(ss, ecx_opnd); + ss = pop(ss, edx_opnd); ss = m2n_gen_pop_m2n(ss, false, 0, 0, 2); - ss = push(ss, ecx_opnd); + ss = push(ss, edx_opnd); ss = ret(ss); assert((ss - stub) <= stub_size); Index: trunk/vm/vmcore/src/util/linux/signals_em64t.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_em64t.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/linux/signals_em64t.cpp (working copy) @@ -54,6 +54,7 @@ #include "open/gc.h" +#include "init.h" #include "exceptions.h" #include "exceptions_jit.h" #include "vm_threads.h" @@ -566,10 +567,8 @@ sa.sa_sigaction = &null_java_divide_by_zero_handler; sigaction(SIGFPE, &sa, NULL); - extern void interrupt_handler(int); - signal(SIGINT, (void (*)(int)) interrupt_handler); - extern void quit_handler(int); - signal(SIGQUIT, (void (*)(int)) quit_handler); + signal(SIGINT, (void (*)(int)) vm_interrupt_handler); + signal(SIGQUIT, (void (*)(int)) vm_dump_handler); /* install abort_handler to print out call stack on assertion failures */ sigemptyset(&sa.sa_mask); Index: trunk/vm/vmcore/src/util/linux/signals_ia32.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (working copy) @@ -54,7 +54,8 @@ #include "environment.h" #include "open/gc.h" - + +#include "init.h" #include "exceptions.h" #include "exceptions_jit.h" #include "vm_threads.h" @@ -767,10 +768,8 @@ sa.sa_sigaction = &general_signal_handler; sigaction(SIGFPE, &sa, NULL); - extern void interrupt_handler(int); - signal(SIGINT, (void (*)(int)) interrupt_handler); - extern void quit_handler(int); - signal(SIGQUIT, (void (*)(int)) quit_handler); + signal(SIGINT, (void (*)(int)) vm_interrupt_handler); + signal(SIGQUIT, (void (*)(int)) vm_dump_handler); /* install abort_handler to print out call stack on assertion failures */ sigemptyset(&sa.sa_mask); Index: trunk/vm/vmcore/src/util/linux/signals_ipf.cpp =================================================================== --- trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (working copy) @@ -54,7 +54,8 @@ #include "environment.h" #include "open/gc.h" - + +#include "init.h" #include "exceptions.h" #include "vm_threads.h" #include "open/vm_util.h" @@ -402,10 +403,8 @@ sa.sa_sigaction = &null_java_divide_by_zero_handler; sigaction(SIGFPE, &sa, NULL); - extern void interrupt_handler(int); - signal(SIGINT, (void (*)(int)) interrupt_handler); - extern void quit_handler(int); - signal(SIGQUIT, (void (*)(int)) quit_handler); + signal(SIGINT, (void (*)(int)) vm_interrupt_handler); + signal(SIGQUIT, (void (*)(int)) vm_dump_handler); /* install abort_handler to print out call stack on assertion failures */ sigemptyset(&sa.sa_mask); Index: trunk/vm/vmcore/src/util/win/nt_platform_utils.cpp =================================================================== --- trunk/vm/vmcore/src/util/win/nt_platform_utils.cpp (revision 487462) +++ trunk/vm/vmcore/src/util/win/nt_platform_utils.cpp (working copy) @@ -30,6 +30,7 @@ #include #include +#include "init.h" #include "platform_utils.h" #include "open/vm_util.h" #include "exception_filter.h" @@ -39,20 +40,16 @@ switch (ctrlType) { case CTRL_BREAK_EVENT: - extern void quit_handler(int); - quit_handler(0); + vm_dump_handler(0); return TRUE; case CTRL_C_EVENT: case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - extern void interrupt_handler(int); - interrupt_handler(0); + vm_interrupt_handler(0); return TRUE; - default: - ABORT("Unexpected event"); } - return FALSE; + return FALSE; } void initialize_signals(){