重庆家居网站制作公司,wordpress指定关键词自动内链,河北网站备案多久,花店网页模板html1. 信号处理与桩代码#xff08;Stub#xff09;
当线程访问安全点轮询页#xff08;Polling Page#xff09;时#xff1a;
触发 SIGSEGV 信号#xff1a;访问只读的轮询页会引发 SIGSEGV 异常。信号处理函数#xff1a;pd_hotspot_signal_handl…1. 信号处理与桩代码Stub
当线程访问安全点轮询页Polling Page时
触发 SIGSEGV 信号访问只读的轮询页会引发 SIGSEGV 异常。信号处理函数pd_hotspot_signal_handler 检测到 SafepointMechanism::is_poll_address 为真调用 SharedRuntime::get_poll_stub 获取桩代码入口地址如 polling_page_safepoint_handler_blob。篡改 PCos::Posix::ucontext_set_pc(uc, stub) 将线程的 程序计数器PC 设置为桩代码地址。 2. 桩代码的职责
桩代码如 polling_page_safepoint_handler_blob是平台相关的汇编代码其核心逻辑为 asm
复制 // 伪代码示例 call SafepointSynchronize::handle_polling_page_exception ; 调用安全点处理函数 ret
直接调用桩代码通过 call 指令直接调用 SafepointSynchronize::handle_polling_page_exception。触发阻塞handle_polling_page_exception 最终通过 SafepointSynchronize::block 让线程阻塞在安全点。 3. 关键调用链
信号处理与安全点处理的完整路径
信号处理函数 (javaSignalHandler)→ PosixSignals::pd_hotspot_signal_handler→ 检测到安全点轮询页SafepointMechanism::is_poll_address→ SharedRuntime::get_poll_stub(pc) 获取桩代码地址→ 篡改 PC 到桩代码如 polling_page_safepoint_handler_blob→ 桩代码执行→ SafepointSynchronize::handle_polling_page_exception→ SafepointMechanism::process→ SafepointSynchronize::block→ 线程阻塞等待安全点 4. 核心设计思想
信号驱动通过操作系统的内存保护机制轮询页不可访问触发信号将控制权交给 JVM。间接跳转信号处理函数不直接调用安全点逻辑而是通过修改线程执行路径PC跳转到桩代码。桩代码桥接桩代码作为 桥梁将信号处理上下文与 JVM 内部安全点处理逻辑连接。 5. 普通线程阻塞的触发
所有 Java 线程无论是用户线程、JIT 编译代码线程还是解释器执行的线程访问轮询页时都会触发此流程。统一入口无论线程原本在执行什么最终都会通过桩代码调用 handle_polling_page_exception确保所有线程在安全点处阻塞。 总结
信号处理函数不直接调用handle_polling_page_exception 由 桩代码 直接调用而非信号处理函数本身。间接触发阻塞通过篡改 PC 到桩代码再由桩代码触发安全点处理逻辑最终实现线程阻塞。统一安全点处理所有 Java 线程通过此机制在安全点同步确保 GC 等操作的安全执行。
##源码 address SharedRuntime::get_poll_stub(address pc) {address stub;// Look up the code blobCodeBlob *cb CodeCache::find_blob(pc);// Should be an nmethodguarantee(cb ! NULL cb-is_compiled(), safepoint polling: pc must refer to an nmethod);// Look up the relocation informationassert(((CompiledMethod*)cb)-is_at_poll_or_poll_return(pc),safepoint polling: type must be poll);#ifdef ASSERTif (!((NativeInstruction*)pc)-is_safepoint_poll()) {tty-print_cr(bad pc: PTR_FORMAT, p2i(pc));Disassembler::decode(cb);fatal(Only polling locations are used for safepoint);}
#endifbool at_poll_return ((CompiledMethod*)cb)-is_at_poll_return(pc);bool has_wide_vectors ((CompiledMethod*)cb)-has_wide_vectors();if (at_poll_return) {assert(SharedRuntime::polling_page_return_handler_blob() ! NULL,polling page return stub not created yet);stub SharedRuntime::polling_page_return_handler_blob()-entry_point();} else if (has_wide_vectors) {assert(SharedRuntime::polling_page_vectors_safepoint_handler_blob() ! NULL,polling page vectors safepoint stub not created yet);stub SharedRuntime::polling_page_vectors_safepoint_handler_blob()-entry_point();} else {assert(SharedRuntime::polling_page_safepoint_handler_blob() ! NULL,polling page safepoint stub not created yet);stub SharedRuntime::polling_page_safepoint_handler_blob()-entry_point();}log_debug(safepoint)(... found polling page %s exception at pc INTPTR_FORMAT , stub INTPTR_FORMAT,at_poll_return ? return : loop,(intptr_t)pc, (intptr_t)stub);return stub;
}bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,ucontext_t* uc, JavaThread* thread) {if (sig SIGILL ((info-si_addr (caddr_t)check_simd_fault_instr)|| info-si_addr (caddr_t)check_vfp_fault_instr|| info-si_addr (caddr_t)check_vfp3_32_fault_instr|| info-si_addr (caddr_t)check_mp_ext_fault_instr)) {// skip faulty instruction instruction that sets return value to// success and set return value to failure.os::Posix::ucontext_set_pc(uc, (address)info-si_addr 8);uc-uc_mcontext.arm_r0 0;return true;}address stub NULL;address pc NULL;bool unsafe_access false;if (info ! NULL uc ! NULL thread ! NULL) {pc (address) os::Posix::ucontext_get_pc(uc);// Handle ALL stack overflow variations hereif (sig SIGSEGV) {address addr (address) info-si_addr;// check if fault address is within thread stackif (thread-is_in_full_stack(addr)) {// stack overflowStackOverflow* overflow_state thread-stack_overflow_state();if (overflow_state-in_stack_yellow_reserved_zone(addr)) {overflow_state-disable_stack_yellow_reserved_zone();if (thread-thread_state() _thread_in_Java) {// Throw a stack overflow exception. Guard pages will be reenabled// while unwinding the stack.stub SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);} else {// Thread was in the vm or native code. Return and try to finish.return true;}} else if (overflow_state-in_stack_red_zone(addr)) {// Fatal red zone violation. Disable the guard pages and fall through// to handle_unexpected_exception way down below.overflow_state-disable_stack_red_zone();tty-print_raw_cr(An irrecoverable stack overflow has occurred.);} else {// Accessing stack address below sp may cause SEGV if current// thread has MAP_GROWSDOWN stack. This should only happen when// current thread was created by user code with MAP_GROWSDOWN flag// and then attached to VM. See notes in os_linux.cpp.if (thread-osthread()-expanding_stack() 0) {thread-osthread()-set_expanding_stack();if (os::Linux::manually_expand_stack(thread, addr)) {thread-osthread()-clear_expanding_stack();return true;}thread-osthread()-clear_expanding_stack();} else {fatal(recursive segv. expanding stack.);}}}}if (thread-thread_state() _thread_in_Java) {// Java thread running in Java code find exception handler if any// a fault inside compiled code, the interpreter, or a stubif (sig SIGSEGV SafepointMechanism::is_poll_address((address)info-si_addr)) {stub SharedRuntime::get_poll_stub(pc);} else if (sig SIGBUS) {// BugId 4454115: A read from a MappedByteBuffer can fault// here if the underlying file has been truncated.// Do not crash the VM in such a case.CodeBlob* cb CodeCache::find_blob_unsafe(pc);CompiledMethod* nm (cb ! NULL) ? cb-as_compiled_method_or_null() : NULL;if ((nm ! NULL nm-has_unsafe_access()) || (thread-doing_unsafe_access() UnsafeCopyMemory::contains_pc(pc))) {unsafe_access true;}} else if (sig SIGSEGV MacroAssembler::uses_implicit_null_check(info-si_addr)) {// Determination of interpreter/vtable stub/compiled code null exceptionCodeBlob* cb CodeCache::find_blob_unsafe(pc);if (cb ! NULL) {stub SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);}} else if (sig SIGILL *(int *)pc NativeInstruction::zombie_illegal_instruction) {// Zombiestub SharedRuntime::get_handle_wrong_method_stub();}} else if ((thread-thread_state() _thread_in_vm ||thread-thread_state() _thread_in_native) sig SIGBUS thread-doing_unsafe_access()) {unsafe_access true;}// jni_fast_GetPrimitiveField can trap at certain pcs if a GC kicks in// and the heap gets shrunk before the field access.if (sig SIGSEGV || sig SIGBUS) {address addr JNI_FastGetField::find_slowcase_pc(pc);if (addr ! (address)-1) {stub addr;}}}if (unsafe_access stub NULL) {// it can be an unsafe access and we havent found// any other suitable exception reason,// so assume it is an unsafe access.address next_pc pc Assembler::InstructionSize;if (UnsafeCopyMemory::contains_pc(pc)) {next_pc UnsafeCopyMemory::page_error_continue_pc(pc);}
#ifdef __thumb__if (uc-uc_mcontext.arm_cpsr PSR_T_BIT) {next_pc (address)((intptr_t)next_pc | 0x1);}
#endifstub SharedRuntime::handle_unsafe_access(thread, next_pc);}if (stub ! NULL) {
#ifdef __thumb__if (uc-uc_mcontext.arm_cpsr PSR_T_BIT) {intptr_t p (intptr_t)pc | 0x1;pc (address)p;// Clear Thumb mode bit if were redirected into the ARM ISA based codeif (((intptr_t)stub 0x1) 0) {uc-uc_mcontext.arm_cpsr ~PSR_T_BIT;}} else {// No Thumb2 compiled stubs are triggered from ARM ISA compiled JITd code today.// The support needs to be added if that changesassert((((intptr_t)stub 0x1) 0), cant return to Thumb code);}
#endif// save all thread context in case we need to restore itif (thread ! NULL) thread-set_saved_exception_pc(pc);os::Posix::ucontext_set_pc(uc, stub);return true;}return false;
}
##源码
(gdb) bt
#0 SafepointSynchronize::block (thread0x7ffff02c8200) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/safepoint.cpp:692
#1 0x00007ffff6966332 in SafepointMechanism::process (thread0x7ffff02c8200, allow_suspendfalse)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/safepointMechanism.cpp:125
#2 0x00007ffff5daa6e5 in SafepointMechanism::process_if_requested (thread0x7ffff02c8200, allow_suspendfalse)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/safepointMechanism.inline.hpp:99
#3 0x00007ffff5daaf6d in ThreadBlockInVMPreprocessInFlightMutexRelease::~ThreadBlockInVMPreprocess (this0x7fffd0dfecc8, __in_chrgoptimized out)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/interfaceSupport.inline.hpp:264
#4 0x00007ffff5daad70 in ThreadBlockInVM::~ThreadBlockInVM (this0x7fffd0dfecc0, __in_chrgoptimized out)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/interfaceSupport.inline.hpp:289
#5 0x00007ffff696f9ed in ServiceThread::service_thread_entry (jt0x7ffff02c8200, __the_thread__0x7ffff02c8200)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/serviceThread.cpp:191
#6 0x00007ffff6b5d26c in JavaThread::thread_main_inner (this0x7ffff02c8200) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1305
#7 0x00007ffff6b5d102 in JavaThread::run (this0x7ffff02c8200) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1288
#8 0x00007ffff6b5a805 in Thread::call_run (this0x7ffff02c8200) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:394
#9 0x00007ffff6874aeb in thread_native_entry (thread0x7ffff02c8200) at /home/yym/openjdk17/jdk17-master/src/hotspot/os/linux/os_linux.cpp:720
#10 0x00007ffff7c94ac3 in start_thread (argoptimized out) at ./nptl/pthread_create.c:442
#11 0x00007ffff7d26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81