void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { assert(method->method_holder()->verify_itable_index(index), ""); assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); assert(interf->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); set_f1(interf); set_f2(index); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
// Check if there are any JVM TI prefixes which have been applied to the native method name. // If any are found, remove them before attemping the look up of the // native implementation again. // See SetNativeMethodPrefix in the JVM TI Spec for more details. address NativeLookup::lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS) { ResourceMark rm(THREAD); int prefix_count; char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); char* in_name = method->name()->as_C_string(); char* wrapper_name = in_name; // last applied prefix will be first -- go backwards for (int i = prefix_count-1; i >= 0; i--) { char* prefix = prefixes[i]; size_t prefix_len = strlen(prefix); if (strncmp(prefix, wrapper_name, prefix_len) == 0) { // has this prefix remove it wrapper_name += prefix_len; } } if (wrapper_name != in_name) { // we have a name for a wrapping method int wrapper_name_len = (int)strlen(wrapper_name); TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len); if (wrapper_symbol != NULL) { KlassHandle kh(method->method_holder()); methodOop wrapper_method = Klass::cast(kh())->lookup_method(wrapper_symbol, method->signature()); if (wrapper_method != NULL && !wrapper_method->is_native()) { // we found a wrapper method, use its native entry method->set_is_prefixed_native(); return lookup_entry(wrapper_method, in_base_library, THREAD); } } } return NULL; }
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { klassOop interf = method->method_holder(); assert(instanceKlass::cast(interf)->is_interface(), "must be an interface"); set_f1(interf); set_f2(index); set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
// Fill in the StackFrameInfo at the given index in frames_array void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array, const methodHandle& method, TRAPS) { if (_need_method_info) { Handle stackFrame(THREAD, frames_array->obj_at(index)); fill_stackframe(stackFrame, method); } else { frames_array->obj_at_put(index, method->method_holder()->java_mirror()); } }
address NativeLookup::lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) { address entry; // Compute complete JNI name for style stringStream st; if (os_style) os::print_jni_name_prefix_on(&st, args_size); st.print_raw(pure_name); st.print_raw(long_name); if (os_style) os::print_jni_name_suffix_on(&st, args_size); char* jni_name = st.as_string(); // If the loader is null we have a system class, so we attempt a lookup in // the native Java library. This takes care of any bootstrapping problems. // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_00024NativeLibrary_find // gets found the first time around - otherwise an infinite loop can occure. This is // another VM/library dependency Handle loader(THREAD, instanceKlass::cast(method->method_holder())->class_loader()); if (loader.is_null()) { entry = lookup_special_native(jni_name); if (entry == NULL) { entry = (address) os::dll_lookup(os::native_java_library(), jni_name); } if (entry != NULL) { in_base_library = true; return entry; } } // Otherwise call static method findNative in ClassLoader KlassHandle klass (THREAD, SystemDictionary::ClassLoader_klass()); Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL); JavaValue result(T_LONG); JavaCalls::call_static(&result, klass, vmSymbols::findNative_name(), vmSymbols::classloader_string_long_signature(), // Arguments loader, name_arg, CHECK_NULL); entry = (address) (intptr_t) result.get_jlong(); if (entry == NULL) { // findNative didn't find it, if there are any agent libraries look in them AgentLibrary* agent; for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) { entry = (address) os::dll_lookup(agent->os_lib(), jni_name); if (entry != NULL) { return entry; } } } return entry; }
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { assert(!is_secondary_entry(), ""); klassOop interf = method->method_holder(); assert(instanceKlass::cast(interf)->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); set_f1(interf); set_f2(index); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
void JavaCalls::call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS) { assert(method->name() == vmSymbols::object_initializer_name(), "Should only be called for default constructor"); assert(method->signature() == vmSymbols::void_method_signature(), "Should only be called for default constructor"); InstanceKlass* ik = method->method_holder(); if (ik->is_initialized() && ik->has_vanilla_constructor()) { // safe to skip constructor call } else { static JavaValue result(T_VOID); JavaCallArguments args(receiver); call(&result, method, &args, CHECK); } }
address NativeLookup::lookup(methodHandle method, bool& in_base_library, TRAPS) { if (!method->has_native_function()) { address entry = lookup_base(method, in_base_library, CHECK_NULL); method->set_native_function(entry, Method::native_bind_event_is_interesting); // -verbose:jni printing if (PrintJNIResolving) { ResourceMark rm(THREAD); tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]", method->method_holder()->external_name(), method->name()->as_C_string()); } } return method->native_function(); }
/** * 为给定的本地java方法寻找对应的函数入口地址 */ address NativeLookup::lookup(methodHandle method, bool& in_base_library, TRAPS) { if (!method->has_native_function()) { printf("%s[%d] [tid: %lu]: 试图查找本地方法[%s.%s]..\n", __FILE__, __LINE__, pthread_self(), Klass::cast(method->method_holder())->external_name(), method->name()->as_C_string()); address entry = lookup_base(method, in_base_library, CHECK_NULL); method->set_native_function(entry, methodOopDesc::native_bind_event_is_interesting); // -verbose:jni printing if (PrintJNIResolving) { ResourceMark rm(THREAD); tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]", Klass::cast(method->method_holder())->external_name(), method->name()->as_C_string()); } } return method->native_function(); }
// Fill StackFrameInfo with declaringClass and bci and initialize memberName void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method) { java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror()); java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci()); }
void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh, unsigned char* bytecodes) { // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes // and the breakpoint bytecode are converted to their original bytecodes. BytecodeStream bs(mh); unsigned char* p = bytecodes; Bytecodes::Code code; bool is_rewritten = mh->method_holder()->is_rewritten(); while ((code = bs.next()) >= 0) { assert(Bytecodes::is_java_code(code), "sanity check"); assert(code != Bytecodes::_breakpoint, "sanity check"); // length of bytecode (mnemonic + operands) address bcp = bs.bcp(); int len = bs.instruction_size(); assert(len > 0, "length must be > 0"); // copy the bytecodes *p = (unsigned char) (bs.is_wide()? Bytecodes::_wide : code); if (len > 1) { memcpy(p+1, bcp+1, len-1); } // During linking the get/put and invoke instructions are rewritten // with an index into the constant pool cache. The original constant // pool index must be returned to caller. Rewrite the index. if (is_rewritten && len > 1) { bool is_wide = false; switch (code) { case Bytecodes::_getstatic : // fall through case Bytecodes::_putstatic : // fall through case Bytecodes::_getfield : // fall through case Bytecodes::_putfield : // fall through case Bytecodes::_invokevirtual : // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface : { assert(len == 3 || (code == Bytecodes::_invokeinterface && len == 5) || (code == Bytecodes::_invokedynamic && len == 5), "sanity check"); int cpci = Bytes::get_native_u2(bcp+1); bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic); ConstantPoolCacheEntry* entry; if (is_invokedynamic) { cpci = Bytes::get_native_u4(bcp+1); entry = mh->constants()->invokedynamic_cp_cache_entry_at(cpci); } else { // cache cannot be pre-fetched since some classes won't have it yet entry = mh->constants()->cache()->entry_at(cpci); } int i = entry->constant_pool_index(); assert(i < mh->constants()->length(), "sanity check"); Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering if (is_invokedynamic) *(p+3) = *(p+4) = 0; break; } case Bytecodes::_ldc_w: is_wide = true; // fall through case Bytecodes::_ldc: { if (bs.raw_code() == Bytecodes::_fast_aldc || bs.raw_code() == Bytecodes::_fast_aldc_w) { int cpci = is_wide ? Bytes::get_native_u2(bcp+1) : (u1)(*(bcp+1)); int i = mh->constants()->object_to_cp_index(cpci); assert(i < mh->constants()->length(), "sanity check"); if (is_wide) { Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering } else { *(p+1) = (u1)i; } } break; } } } p += len; } }
void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { // either the method is a miranda or its holder should accept the given index assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), ""); // index >= 0; FIXME: inline and customize set_direct_or_vtable_call set_direct_or_vtable_call(invoke_code, method, index); }
void CodeBuffer::finalize_oop_references(methodHandle mh) { No_Safepoint_Verifier nsv; GrowableArray<oop> oops; // Make sure that immediate metadata records something in the OopRecorder for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { // pull code out of each section CodeSection* cs = code_section(n); if (cs->is_empty()) continue; // skip trivial section RelocIterator iter(cs); while (iter.next()) { if (iter.type() == relocInfo::metadata_type) { metadata_Relocation* md = iter.metadata_reloc(); if (md->metadata_is_immediate()) { Metadata* m = md->metadata_value(); if (oop_recorder()->is_real(m)) { if (m->is_methodData()) { m = ((MethodData*)m)->method(); } if (m->is_method()) { m = ((Method*)m)->method_holder(); } if (m->is_klass()) { append_oop_references(&oops, (Klass*)m); } else { // XXX This will currently occur for MDO which don't // have a backpointer. This has to be fixed later. m->print(); ShouldNotReachHere(); } } } } } } if (!oop_recorder()->is_unused()) { for (int i = 0; i < oop_recorder()->metadata_count(); i++) { Metadata* m = oop_recorder()->metadata_at(i); if (oop_recorder()->is_real(m)) { if (m->is_methodData()) { m = ((MethodData*)m)->method(); } if (m->is_method()) { m = ((Method*)m)->method_holder(); } if (m->is_klass()) { append_oop_references(&oops, (Klass*)m); } else { m->print(); ShouldNotReachHere(); } } } } // Add the class loader of Method* for the nmethod itself append_oop_references(&oops, mh->method_holder()); // Add any oops that we've found Thread* thread = Thread::current(); for (int i = 0; i < oops.length(); i++) { oop_recorder()->find_index((jobject)thread->handle_area()->allocate_handle(oops.at(i))); } }