当前位置: 首页 > news >正文

OpenJDK 17 方法链接与同步方法入口点生成机制深度解析

引言

在 Java 虚拟机中,方法调用是一个复杂而精妙的过程。今天我们将深入探讨 OpenJDK 17 中方法链接如何找到正确的入口点,以及同步方法的 synchronized 参数是如何传递的。通过分析模板解释器的源码,揭开 JVM 方法调用的神秘面纱。

一、方法链接的整体流程

当 JVM 第一次调用一个方法时,会进行方法链接(Linking),这个过程在 Method::link_method 中完成:

cpp

void Method::link_method(const methodHandle& h_method, TRAPS) {if (_i2i_entry != NULL) return;assert(_code == NULL, "nothing compiled yet");// 设置解释器入口点address entry = Interpreter::entry_for_method(h_method);set_interpreter_entry(entry);// 处理本地方法if (is_native() && !has_native_function()) {set_native_function(/* 错误处理入口 */);}// 生成适配器(void) make_adapters(h_method, CHECK);
}

关键的一步是 Interpreter::entry_for_method(h_method),它决定了方法执行时应该使用哪个入口点。

二、方法类型判定:MethodKind 的作用

JVM 通过 method_kind 函数根据方法的特性确定其类型:

cpp

AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHandle& m) {// 抽象方法if (m->is_abstract()) return abstract;// 方法句柄原语vmIntrinsics::ID iid = m->intrinsic_id();if (iid != vmIntrinsics::_none) {// 处理各种内在方法(intrinsics)if (m->is_method_handle_intrinsic()) {// 方法句柄处理}switch (iid) {case vmIntrinsics::_updateCRC32: return java_util_zip_CRC32_update;case vmIntrinsics::_dsin: return java_lang_math_sin;// ... 其他内在方法}}// 本地方法if (m->is_native()) {return m->is_synchronized() ? native_synchronized : native;}// 同步方法if (m->is_synchronized()) {return zerolocals_synchronized;}// 空方法、getter、setter等特殊情况if (m->is_empty_method()) return empty;if (m->is_getter()) return getter;if (m->is_setter()) return setter;// 普通方法return zerolocals;
}

三、synchronized 参数的传递机制

synchronized 参数的传递是通过 MethodKind 枚举值实现的:

1. 参数传递链路

text

方法调用 → 方法链接 → 检查访问标志 → 确定 MethodKind → 传递 synchronized 参数

2. 关键代码分析

在 generate_method_entry 方法中:

cpp

address TemplateInterpreterGenerator::generate_method_entry(MethodKind kind) {bool native = false;bool synchronized = false;address entry_point = NULL;switch (kind) {case Interpreter::zerolocals:             // 普通非同步方法break;case Interpreter::zerolocals_synchronized: // 同步方法synchronized = true;      // 这里设置 synchronized = truebreak;case Interpreter::native:                 // 本地方法native = true;break;case Interpreter::native_synchronized:    // 同步本地方法native = true; synchronized = true;      // 这里也设置 synchronized = truebreak;// ... 其他情况}if (entry_point) return entry_point;if (native) {entry_point = generate_native_entry(synchronized);  // 传递参数} else {entry_point = generate_normal_entry(synchronized);  // 传递参数}return entry_point;
}

3. synchronized 参数的使用

在 generate_normal_entry 中,根据 synchronized 参数生成不同的代码:

cpp

address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {// ... 前置处理代码// 根据 synchronized 参数决定是否生成同步代码if (synchronized) {// 分配监控器并锁定方法lock_method();} else {// 非同步方法,只有断言检查
#ifdef ASSERT{Label L;__ movl(rax, access_flags);__ testl(rax, JVM_ACC_SYNCHRONIZED);__ jcc(Assembler::zero, L);__ stop("method needs synchronization");__ bind(L);}
#endif}// ... 后续代码
}

四、入口点表初始化

在系统初始化时,通过 generate_all 方法生成所有类型方法的入口点:

cpp

void TemplateInterpreterGenerator::generate_all() {// ... 其他初始化// 生成各种方法的入口点
#define method_entry(kind)                                              \{ CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \}method_entry(zerolocals)              // 普通方法method_entry(zerolocals_synchronized) // 同步方法method_entry(native)                  // 本地方法method_entry(native_synchronized)     // 同步本地方法// ... 其他方法类型#undef method_entry
}

五、同步方法的具体实现

对于同步方法,lock_method() 会生成获取对象监视器的代码。在方法执行前获取锁,在方法返回前释放锁,确保线程安全。

总结

OpenJDK 17 的方法链接机制通过以下步骤实现 synchronized 参数的传递:

  1. 方法链接时检查方法的访问标志(access_flags

  2. 根据 JVM_ACC_SYNCHRONIZED 标志确定对应的 MethodKind

  3. 在 generate_method_entry 中将 MethodKind 转换为 synchronized 布尔参数

  4. 最终传递给 generate_normal_entry 生成相应的同步或非同步代码

这种设计确保了:

  • 同步方法有正确的锁机制

  • 非同步方法没有不必要的性能开销

  • 代码生成逻辑清晰可维护

  • 支持各种特殊方法类型的内在优化

理解这一机制对于深入掌握 JVM 工作原理和进行性能优化具有重要意义。

##源码

// Generic interpreted method entry to (asm) interpreter
//
address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {// determine code generation flagsbool inc_counter  = UseCompiler || CountCompiledCalls || LogTouchedMethods;// ebx: Method*// rbcp: sender spaddress entry_point = __ pc();const Address constMethod(rbx, Method::const_offset());const Address access_flags(rbx, Method::access_flags_offset());const Address size_of_parameters(rdx,ConstMethod::size_of_parameters_offset());const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());// get parameter size (always needed)__ movptr(rdx, constMethod);__ load_unsigned_short(rcx, size_of_parameters);// rbx: Method*// rcx: size of parameters// rbcp: sender_sp (could differ from sp+wordSize if we were called via c2i )__ load_unsigned_short(rdx, size_of_locals); // get size of locals in words__ subl(rdx, rcx); // rdx = no. of additional locals// YYY
//   __ incrementl(rdx);
//   __ andl(rdx, -2);// see if we've got enough room on the stack for locals plus overhead.generate_stack_overflow_check();//yym-gaizao// 在generate_normal_entry函数中添加汇编代码{// 保存所有可能被破坏的寄存器__ push(rbx);__ push(rcx);__ push(rdx);__ push(rsi);__ push(rdi);__ push(r8);__ push(r9);__ push(r10);__ push(r11);// 设置参数 (Method*)__ movptr(rdi, rbx);  // Method* 作为第一个参数// 确保16字节栈对齐__ subptr(rsp, 8);#if 0// 调用安全的调试函数__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, TemplateInterpreterGenerator::print_debug_info_safe)));#endif// 恢复栈指针__ addptr(rsp, 8);// 恢复寄存器__ pop(r11);__ pop(r10);__ pop(r9);__ pop(r8);__ pop(rdi);__ pop(rsi);__ pop(rdx);__ pop(rcx);__ pop(rbx);}// get return address__ pop(rax);// compute beginning of parameters__ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));// rdx - # of additional locals// allocate space for locals// explicitly initialize locals{Label exit, loop;__ testl(rdx, rdx);__ jcc(Assembler::lessEqual, exit); // do nothing if rdx <= 0__ bind(loop);__ push((int) NULL_WORD); // initialize local variables__ decrementl(rdx); // until everything initialized__ jcc(Assembler::greater, loop);__ bind(exit);}// initialize fixed part of activation framegenerate_fixed_frame(false);// make sure method is not native & not abstract
#ifdef ASSERT__ movl(rax, access_flags);{Label L;__ testl(rax, JVM_ACC_NATIVE);__ jcc(Assembler::zero, L);__ stop("tried to execute native method as non-native");__ bind(L);}{Label L;__ testl(rax, JVM_ACC_ABSTRACT);__ jcc(Assembler::zero, L);__ stop("tried to execute abstract method in interpreter");__ bind(L);}
#endif// Since at this point in the method invocation the exception// handler would try to exit the monitor of synchronized methods// which hasn't been entered yet, we set the thread local variable// _do_not_unlock_if_synchronized to true. The remove_activation// will check this flag.const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);NOT_LP64(__ get_thread(thread));const Address do_not_unlock_if_synchronized(thread,in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));__ movbool(do_not_unlock_if_synchronized, true);__ profile_parameters_type(rax, rcx, rdx);// increment invocation count & check for overflowLabel invocation_counter_overflow;if (inc_counter) {generate_counter_incr(&invocation_counter_overflow);}Label continue_after_compile;__ bind(continue_after_compile);// check for synchronized interpreted methodsbang_stack_shadow_pages(false);// reset the _do_not_unlock_if_synchronized flagNOT_LP64(__ get_thread(thread));__ movbool(do_not_unlock_if_synchronized, false);// check for synchronized methods// Must happen AFTER invocation_counter check and stack overflow check,// so method is not locked if overflows.if (synchronized) {// Allocate monitor and lock methodlock_method();} else {// no synchronization necessary
#ifdef ASSERT{Label L;__ movl(rax, access_flags);__ testl(rax, JVM_ACC_SYNCHRONIZED);__ jcc(Assembler::zero, L);__ stop("method needs synchronization");__ bind(L);}
#endif}// start execution
#ifdef ASSERT{Label L;const Address monitor_block_top (rbp,frame::interpreter_frame_monitor_block_top_offset * wordSize);__ movptr(rax, monitor_block_top);__ cmpptr(rax, rsp);__ jcc(Assembler::equal, L);__ stop("broken stack frame setup in interpreter");__ bind(L);}
#endif// jvmti support__ notify_method_entry();__ dispatch_next(vtos);// invocation counter overflowif (inc_counter) {// Handle overflow of counter and compile method__ bind(invocation_counter_overflow);generate_counter_overflow(continue_after_compile);}return entry_point;
}// Generate method entries
address TemplateInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) {// determine code generation flagsbool native = false;bool synchronized = false;address entry_point = NULL;switch (kind) {case Interpreter::zerolocals             :                                          break;case Interpreter::zerolocals_synchronized:                synchronized = true;      break;case Interpreter::native                 : native = true;                           break;case Interpreter::native_synchronized    : native = true; synchronized = true;      break;case Interpreter::empty                  : break;case Interpreter::getter                 : break;case Interpreter::setter                 : break;case Interpreter::abstract               : entry_point = generate_abstract_entry(); break;case Interpreter::java_lang_math_sin     : // fall thrucase Interpreter::java_lang_math_cos     : // fall thrucase Interpreter::java_lang_math_tan     : // fall thrucase Interpreter::java_lang_math_abs     : // fall thrucase Interpreter::java_lang_math_log     : // fall thrucase Interpreter::java_lang_math_log10   : // fall thrucase Interpreter::java_lang_math_sqrt    : // fall thrucase Interpreter::java_lang_math_pow     : // fall thrucase Interpreter::java_lang_math_exp     : // fall thrucase Interpreter::java_lang_math_fmaD    : // fall thrucase Interpreter::java_lang_math_fmaF    : entry_point = generate_math_entry(kind);      break;case Interpreter::java_lang_ref_reference_get: entry_point = generate_Reference_get_entry(); break;case Interpreter::java_util_zip_CRC32_update: native = true; entry_point = generate_CRC32_update_entry();  break;case Interpreter::java_util_zip_CRC32_updateBytes: // fall thrucase Interpreter::java_util_zip_CRC32_updateByteBuffer: native = true; entry_point = generate_CRC32_updateBytes_entry(kind); break;case Interpreter::java_util_zip_CRC32C_updateBytes: // fall thrucase Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer: entry_point = generate_CRC32C_updateBytes_entry(kind); break;
#ifdef IA32// On x86_32 platforms, a special entry is generated for the following four methods.// On other platforms the normal entry is used to enter these methods.case Interpreter::java_lang_Float_intBitsToFloat: native = true; entry_point = generate_Float_intBitsToFloat_entry(); break;case Interpreter::java_lang_Float_floatToRawIntBits: native = true; entry_point = generate_Float_floatToRawIntBits_entry(); break;case Interpreter::java_lang_Double_longBitsToDouble: native = true; entry_point = generate_Double_longBitsToDouble_entry(); break;case Interpreter::java_lang_Double_doubleToRawLongBits: native = true; entry_point = generate_Double_doubleToRawLongBits_entry(); break;
#elsecase Interpreter::java_lang_Float_intBitsToFloat:case Interpreter::java_lang_Float_floatToRawIntBits:case Interpreter::java_lang_Double_longBitsToDouble:case Interpreter::java_lang_Double_doubleToRawLongBits:native = true;break;
#endif // !IA32default:fatal("unexpected method kind: %d", kind);break;}if (entry_point) {return entry_point;}// We expect the normal and native entry points to be generated first so we can reuse them.if (native) {entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native);if (entry_point == NULL) {entry_point = generate_native_entry(synchronized);}} else {entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals);if (entry_point == NULL) {entry_point = generate_normal_entry(synchronized);}}return entry_point;
}void TemplateInterpreterGenerator::generate_all() {{ CodeletMark cm(_masm, "slow signature handler");AbstractInterpreter::_slow_signature_handler = generate_slow_signature_handler();}{ CodeletMark cm(_masm, "error exits");_unimplemented_bytecode    = generate_error_exit("unimplemented bytecode");_illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified");}#ifndef PRODUCTif (TraceBytecodes) {CodeletMark cm(_masm, "bytecode tracing support");Interpreter::_trace_code =EntryPoint(generate_trace_code(atos),generate_trace_code(itos),generate_trace_code(ltos),generate_trace_code(ftos),generate_trace_code(dtos),generate_trace_code(vtos));}
#endif // !PRODUCT{ CodeletMark cm(_masm, "return entry points");Interpreter::_return_entry[0] = EntryPoint();for (int i = 1; i < Interpreter::number_of_return_entries; i++) {Interpreter::_return_entry[i] =EntryPoint(generate_return_entry_for(atos, i, sizeof(u2)),generate_return_entry_for(itos, i, sizeof(u2)),generate_return_entry_for(ltos, i, sizeof(u2)),generate_return_entry_for(ftos, i, sizeof(u2)),generate_return_entry_for(dtos, i, sizeof(u2)),generate_return_entry_for(vtos, i, sizeof(u2)));}}{ CodeletMark cm(_masm, "invoke return entry points");// These states are in order specified in TosState, except btos/ztos/ctos/stos which// are the same as itos since there is no top of stack optimization for these typesconst TosState states[] = {ilgl, ilgl, ilgl, ilgl, itos, ltos, ftos, dtos, atos, vtos, ilgl};const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic);const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface);const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic);assert(invoke_length >= 0 && invoke_length < Interpreter::number_of_return_entries, "invariant");assert(invokeinterface_length >= 0 && invokeinterface_length < Interpreter::number_of_return_entries, "invariant");for (int i = itos; i < Interpreter::number_of_return_addrs; i++) {TosState state = states[i];assert(state != ilgl, "states array is wrong above");// Reuse generated entry pointsInterpreter::_invoke_return_entry[i]          = Interpreter::_return_entry[invoke_length].entry(state);Interpreter::_invokeinterface_return_entry[i] = Interpreter::_return_entry[invokeinterface_length].entry(state);Interpreter::_invokedynamic_return_entry[i]   = generate_return_entry_for(state, invokedynamic_length, sizeof(u4));}// set itos entry points for btos/ztos/ctos/stosfor (int i = 0; i < itos; i++) {Interpreter::_invoke_return_entry[i]          = Interpreter::_invoke_return_entry[itos];Interpreter::_invokeinterface_return_entry[i] = Interpreter::_invokeinterface_return_entry[itos];Interpreter::_invokedynamic_return_entry[i]   = Interpreter::_invokedynamic_return_entry[itos];}}{ CodeletMark cm(_masm, "earlyret entry points");Interpreter::_earlyret_entry =EntryPoint(generate_earlyret_entry_for(atos),generate_earlyret_entry_for(itos),generate_earlyret_entry_for(ltos),generate_earlyret_entry_for(ftos),generate_earlyret_entry_for(dtos),generate_earlyret_entry_for(vtos));}{ CodeletMark cm(_masm, "result handlers for native calls");// The various result converter stublets.int is_generated[Interpreter::number_of_result_handlers];memset(is_generated, 0, sizeof(is_generated));for (int i = 0; i < Interpreter::number_of_result_handlers; i++) {BasicType type = types[i];if (!is_generated[Interpreter::BasicType_as_index(type)]++) {Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type);}}}{ CodeletMark cm(_masm, "safepoint entry points");Interpreter::_safept_entry =EntryPoint(generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)));}{ CodeletMark cm(_masm, "exception handling");// (Note: this is not safepoint safe because thread may return to compiled code)generate_throw_exception();}{ CodeletMark cm(_masm, "throw exception entrypoints");Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler();Interpreter::_throw_ArrayStoreException_entry            = generate_klass_exception_handler("java/lang/ArrayStoreException");Interpreter::_throw_ArithmeticException_entry            = generate_exception_handler("java/lang/ArithmeticException", "/ by zero");Interpreter::_throw_ClassCastException_entry             = generate_ClassCastException_handler();Interpreter::_throw_NullPointerException_entry           = generate_exception_handler("java/lang/NullPointerException", NULL);Interpreter::_throw_StackOverflowError_entry             = generate_StackOverflowError_handler();}#define method_entry(kind)                                              \{ CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \}// all non-native method kindsmethod_entry(zerolocals)method_entry(zerolocals_synchronized)method_entry(empty)method_entry(getter)method_entry(setter)method_entry(abstract)method_entry(java_lang_math_sin  )method_entry(java_lang_math_cos  )method_entry(java_lang_math_tan  )method_entry(java_lang_math_abs  )method_entry(java_lang_math_sqrt )method_entry(java_lang_math_log  )method_entry(java_lang_math_log10)method_entry(java_lang_math_exp  )method_entry(java_lang_math_pow  )method_entry(java_lang_math_fmaF )method_entry(java_lang_math_fmaD )method_entry(java_lang_ref_reference_get)AbstractInterpreter::initialize_method_handle_entries();// all native method kinds (must be one contiguous block)Interpreter::_native_entry_begin = Interpreter::code()->code_end();method_entry(native)method_entry(native_synchronized)Interpreter::_native_entry_end = Interpreter::code()->code_end();method_entry(java_util_zip_CRC32_update)method_entry(java_util_zip_CRC32_updateBytes)method_entry(java_util_zip_CRC32_updateByteBuffer)method_entry(java_util_zip_CRC32C_updateBytes)method_entry(java_util_zip_CRC32C_updateDirectByteBuffer)method_entry(java_lang_Float_intBitsToFloat);method_entry(java_lang_Float_floatToRawIntBits);method_entry(java_lang_Double_longBitsToDouble);method_entry(java_lang_Double_doubleToRawLongBits);#undef method_entry// Bytecodesset_entry_points_for_all_bytes();// installation of code in other places in the runtime// (ExcutableCodeManager calls not needed to copy the entries)set_safepoints_for_all_bytes();{ CodeletMark cm(_masm, "deoptimization entry points");Interpreter::_deopt_entry[0] = EntryPoint();Interpreter::_deopt_entry[0].set_entry(vtos, generate_deopt_entry_for(vtos, 0));for (int i = 1; i < Interpreter::number_of_deopt_entries; i++) {Interpreter::_deopt_entry[i] =EntryPoint(generate_deopt_entry_for(atos, i),generate_deopt_entry_for(itos, i),generate_deopt_entry_for(ltos, i),generate_deopt_entry_for(ftos, i),generate_deopt_entry_for(dtos, i),generate_deopt_entry_for(vtos, i));}address return_continuation = Interpreter::_normal_table.entry(Bytecodes::_return).entry(vtos);vmassert(return_continuation != NULL, "return entry not generated yet");Interpreter::_deopt_reexecute_return_entry = generate_deopt_entry_for(vtos, 0, return_continuation);}}// Called when the method_holder is getting linked. Setup entrypoints so the method
// is ready to be called from interpreter, compiler, and vtables.
void Method::link_method(const methodHandle& h_method, TRAPS) {// If the code cache is full, we may reenter this function for the// leftover methods that weren't linked.if (_i2i_entry != NULL) {return;}assert( _code == NULL, "nothing compiled yet" );// Setup interpreter entrypointassert(this == h_method(), "wrong h_method()" );assert(adapter() == NULL, "init'd to NULL");address entry = Interpreter::entry_for_method(h_method);assert(entry != NULL, "interpreter entry must be non-null");// Sets both _i2i_entry and _from_interpreted_entryset_interpreter_entry(entry);// Don't overwrite already registered native entries.if (is_native() && !has_native_function()) {set_native_function(SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),!native_bind_event_is_interesting);}// Setup compiler entrypoint.  This is made eagerly, so we do not need// special handling of vtables.  An alternative is to make adapters more// lazily by calling make_adapter() from from_compiled_entry() for the// normal calls.  For vtable calls life gets more complicated.  When a// call-site goes mega-morphic we need adapters in all methods which can be// called from the vtable.  We need adapters on such methods that get loaded// later.  Ditto for mega-morphic itable calls.  If this proves to be a// problem we'll make these lazily later.(void) make_adapters(h_method, CHECK);// ONLY USE the h_method now as make_adapter may have blocked
}static address    entry_for_kind(MethodKind k)                { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; }static address    entry_for_method(const methodHandle& m)     { return entry_for_kind(method_kind(m)); }// Entry pointsAbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHandle& m) {// Abstract method?if (m->is_abstract()) return abstract;// Method handle primitive?vmIntrinsics::ID iid = m->intrinsic_id();if (iid != vmIntrinsics::_none) {if (m->is_method_handle_intrinsic()) {assert(MethodHandles::is_signature_polymorphic(iid), "must match an intrinsic");MethodKind kind = (MethodKind)(method_handle_invoke_FIRST +vmIntrinsics::as_int(iid) -static_cast<int>(vmIntrinsics::FIRST_MH_SIG_POLY));assert(kind <= method_handle_invoke_LAST, "parallel enum ranges");return kind;}switch (iid) {
#ifndef ZERO// Use optimized stub code for CRC32 native methods.case vmIntrinsics::_updateCRC32:       return java_util_zip_CRC32_update;case vmIntrinsics::_updateBytesCRC32:  return java_util_zip_CRC32_updateBytes;case vmIntrinsics::_updateByteBufferCRC32: return java_util_zip_CRC32_updateByteBuffer;// Use optimized stub code for CRC32C methods.case vmIntrinsics::_updateBytesCRC32C: return java_util_zip_CRC32C_updateBytes;case vmIntrinsics::_updateDirectByteBufferCRC32C: return java_util_zip_CRC32C_updateDirectByteBuffer;case vmIntrinsics::_intBitsToFloat:    return java_lang_Float_intBitsToFloat;case vmIntrinsics::_floatToRawIntBits: return java_lang_Float_floatToRawIntBits;case vmIntrinsics::_longBitsToDouble:  return java_lang_Double_longBitsToDouble;case vmIntrinsics::_doubleToRawLongBits: return java_lang_Double_doubleToRawLongBits;
#endif // ZEROcase vmIntrinsics::_dsin:              return java_lang_math_sin;case vmIntrinsics::_dcos:              return java_lang_math_cos;case vmIntrinsics::_dtan:              return java_lang_math_tan;case vmIntrinsics::_dabs:              return java_lang_math_abs;case vmIntrinsics::_dlog:              return java_lang_math_log;case vmIntrinsics::_dlog10:            return java_lang_math_log10;case vmIntrinsics::_dpow:              return java_lang_math_pow;case vmIntrinsics::_dexp:              return java_lang_math_exp;case vmIntrinsics::_fmaD:              return java_lang_math_fmaD;case vmIntrinsics::_fmaF:              return java_lang_math_fmaF;case vmIntrinsics::_Reference_get:     return java_lang_ref_reference_get;case vmIntrinsics::_dsqrt:// _dsqrt will be selected for both Math::sqrt and StrictMath::sqrt, but the latter// is native. Keep treating it like a native method in the interpreterassert(m->name() == vmSymbols::sqrt_name() &&(m->klass_name() == vmSymbols::java_lang_Math() ||m->klass_name() == vmSymbols::java_lang_StrictMath()), "must be");return m->is_native() ? native : java_lang_math_sqrt;case vmIntrinsics::_Object_init:if (RegisterFinalizersAtInit && m->code_size() == 1) {// We need to execute the special return bytecode to check for// finalizer registration so create a normal frame.return zerolocals;}break;default: break;}}// Native method?if (m->is_native()) {assert(!m->is_method_handle_intrinsic(), "overlapping bits here, watch out");return m->is_synchronized() ? native_synchronized : native;}// Synchronized?if (m->is_synchronized()) {return zerolocals_synchronized;}// Empty method?if (m->is_empty_method()) {return empty;}// Getter method?if (m->is_getter()) {return getter;}// Setter method?if (m->is_setter()) {return setter;}// Note: for now: zero locals for all non-empty methodsreturn zerolocals;
}

http://www.dtcms.com/a/414342.html

相关文章:

  • qt-C++笔记之自定义绘制:QWidget中的paintEvent 与 QGraphicsItem中的paint
  • 项目:智能排队控制系统
  • LeetCode:71.字符串解码
  • LeetCode:66.搜索旋转排序数组
  • 阿帕奇网站搭建六安做网站的
  • wordpress去除评论表单电子商务seo优化
  • deepseek kotlin flow快生产者和慢消费者解决策略
  • 20.NFS iSCSI服务器
  • uniapp 搭建vue项目,快速搭建项目
  • 自动网页浏览助手:基于 Selenium + GLM-4V 的百度自动搜索与内容提取系统
  • 网站地图什么时候提交好网站自响应
  • 深度学习笔记(一)——线性回归、Softmax回归、多层感知机、环境和分布偏移
  • 网站建设教程要去d湖南岚鸿询 问2022年企业年报网上申报流程
  • js构造函数—11
  • Kotlin轻量级互斥锁Mutext与轻量级信号量Semaphore异同比较
  • 【MySQL✨】MySQL 入门之旅 · 第十篇:数据库备份与恢复
  • k8s里三种探针的使用场景
  • 8.基于 Ingress-nginx-controller 实现 k8s 七层代理
  • Kling-Audio-Eval - 高质量视频到音频生成评估数据集
  • LeetCode 812.最大三角形的面积
  • 做网站都需要服务器吗域名类型
  • js逆向实战:爬取淘宝男装商品
  • 前端3.0
  • 机器视觉检测中,最小尺寸多少像素可以检测到?重点解析传统算法和深度学习,对比度很致命
  • 不同浏览器中高效维护需要登录网站的登录态
  • 【C++list】底层结构、迭代器核心原理与常用接口实现全解析
  • socket编程 netstat 大小端 rpc 协程 io yield
  • 网站建设与维护百度百科自己做app的软件
  • 制作公司网站要多少费用呢二手书交易网站策划书
  • 【vue3】watch、watchEffect、watchPostEffect和watchSyncEffect的区别详解