目录
五、 安全点信息统计 -XX:+PrintSafepointStatistics
安全点(英文Saftpoint)
一、原理
JVM的Safepoint充分利用Linux中断机制。即在函数的安全点位置插入1条(mips上是2条)从固定地址的数据加载(读)指令,正常情况下这个地址为可读可写,而当JVM需要暂停用户线程时(比如GC),JVM把这个固定地址设置成不可读,那么线程执行到此处时就会触发异常。而jvm注册了sig_handler,可以捕获这个异常,然后根据异常类型和地址信息来判断是否为Safepoint异常并则通知当前线程停止运行。这个固定地址通常是一个内存页位置,触发的异常类型 为SIGSEGV。当GC任务完成后,JVM再把这个固定地址设置为可读即可。
二、生成的Safepoint具体指令
//参看mips_64.ad中的 instruct safePoint_poll()
lui t9,0x1 //加载地址0x10000到t9寄存器。0x10000即为当前系统平台的PAGE_SIZE
lw at,0(t9) //非法指令,直接触发异常信号SIGSEGV
三、 捕获异常并停止线程
//参看os_linux_mips.cpp中的 JVM_handle_linux_signal(...)
if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address) info->si_addr)) {// 捕获信号为SIGSEGV 并且异常地址为0x1000?
// Block current thread until the memory serialize page permission restored.
os::block_on_serialize_page_trap(); //挂起当前线程
return true;
}
}
四、安全点恢复
//参看safepoint.cpp oid SafepointSynchronize::end()
// Start suspended threads
for(JavaThread *current = Threads::first(); current; current = current->next()) {
ThreadSafepointState* cur_state = current->safepoint_state();
assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint");
cur_state->restart();
}
五、 安全点信息统计 -XX:+PrintSafepointStatistics
vmop [threads: total initially_running wait_to_block] [time: spin block sync cleanup vmop] page_trap_count
0.382: ParallelGCSystemGC [ 7 0 0 ] [ 0 0 0 0 83 ] 0
0.470: no vm operation [ 5 0 0 ] [ 0 0 0 0 12 ] 0
safepoint的执行一共可以分为四个阶段:
Spin阶段:因为jvm在决定进入全局safepoint的时候,有的线程在安全点上,而有的线程不在安全点上,这个阶段是等待未在安全点上的用户线程进入安全点。
Block阶段:即使进入safepoint,用户线程这时候仍然是running状态,保证用户不在继续执行,需要将用户线程阻塞。
Cleanup阶段: 这个阶段是JVM做的一些内部的清理工作。
VM Operation 阶段: JVM执行的一些全局性工作,例如GC,代码反优化。