safe point 顾明思意,就是安全点,当需要jvm做一些操作的时候,需要把当前正在运行的线程进入一个安全点的状态(也可以说停止状态),这样才能做一些安全的操作,比如线程的dump,堆栈的信息。
在jvm里面通常vm_thread(我们一直在谈论的做一些属于vm 份内事情的线程) 和cms_thread(内存回收的线程)做的操作,是需要将其他的线程通过调用SafepointSynchronize::begin 和 SafepointSynchronize:end来实现让其他的线程进入或者退出safe point 的状态。
通常safepoint 的有三种状态
_not_synchronized |
说明没有任何打断现在所有线程运行的操作,也就是vm thread, cms thread 没有接到操作的指令 |
_synchronizing |
vm thread,cms thread 接到操作指令,正在等待所有线程进入safe point |
_synchronized |
所有线程进入safe point, vm thread, cms thread 可以开始指令操作 |
Java线程的状态
通常在java 进程中的Java 的线程有几个不同的状态,如何让这些线程进入safepoint 的状态中,jvm是采用不同的方式
a. 正在解释执行
由于java是解释性语言,而线程在解释java 字节码的时候,需要dispatch table,记录方法地址进行跳转的,那么这样让线程进入停止状态就比较容易了,只要替换掉dispatch table 就可以了,让线程知道当前进入softpoint 状态。
java里会设置3个DispatchTable, _active_table, _normal_table, _safept_table
_active_table 正在解释运行的线程使用的dispatch table
_normal_table 就是正常运行的初始化的dispatch table
_safept_table safe point需要的dispatch table
解释运行的线程一直都在使用_active_table,关键处就是在进入saftpoint 的时候,用_safept_table替换_active_table, 在退出saftpoint 的时候,使用_normal_table来替换_active_table
具体实现可以查看源码
b. 运行在native code
如果线程运行在native code的时候,vm thread是不需要等待线程执行完的,只需要在从nativecode 返回的时候去判断一下 _state 的状态就可以了。
在方法体里就是前面博客也出现过的 SafepointSynchronize::do_call_back()
判断了_state 不是_not_synchronized状态
为了能让线程从native code 回到java 的时候为了能读到/设置正确线程的状态,通常的解决方法使用memory barrier,java 使用OrderAccess::fence(); 在汇编里使用__asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); 保证从内存里读到正确的值,但是这种方法严重影响系统的性能,于是java使用了每个线程都有独立的内存页来设置状态。通过使用使用参数-XX:+UseMembar 参数使用memory
barrier,默认是不打开的,也就是使用独立的内存页来设置状态。
c. 运行编译的代码
1. Poling page 页面
Poling page是在jvm初始化启动的时候会初始化的一个单独的内存页面,这个页面是让运行的编译过的代码的线程进入停止状态的关键。
在linux里面使用了mmap初始化,源码如下
2. 编译
java 的JIT 会直接编译一些热门的源码到机器码,直接执行而不需要在解释执行从而提高效率,在编译的代码中,当函数或者方法块返回的时候会去访问一个内存poling页面.
x86架构下
在前面提到的SafepointSynchronize::begin 函数源码中
这里提到了2个参数 UseCompilerSafepoints和DeferPollingPageLoopCount,在默认的情况下这2个参数是true和-1
函数体将会调用os:make_polling_page_unreadable();在linux os 下具体实现是调用了mprotect(bottom,size,prot) 使polling 内存页变成不可读。
3. 信号
到当编译好的程序尝试在去访问这个不可读的polling页面的时候,在系统级别会产生一个错误信号SIGSEGV,可以参考笔者的一篇博客中曾经讲过java的信号处理,可以知道信号SIGSEGV的处理函数在x86体系下见下源码:
在linux x86,64 bit的体系中,poll stub 的地址就是SafepointSynchronize::handle_polling_page_exception 详细程序可见shareRuntime_x86_64.cpp
回到safepoint.cpp中,SafepointSynchronize::handle_polling_page_exception通过取出线程的safepoint_stat,调用函数void ThreadSafepointState::handle_polling_page_exception,最后通过调用SafepointSynchronize::block(thread()); 来block当前线程。
d. block 状态
当线程进入block状态的时候,继续保持block状态。
分享到:
相关推荐
在 Kubernetes 环境中,运行 Java 程序时,无法使用 jmap 和 jstack 命令进行性能分析和诊断。这种情况下,无法获取 Java 进程的 pid,导致无法使用 jmap 和 jstack 命令。 解决方案: 1. 了解 Linux 特殊进程 在 ...
JMAP是Java自带的一个命令行工具,它提供了对Java堆内存的详细分析功能,可以帮助我们诊断内存泄漏。JMAP的主要功能包括: 1. **生成堆转储文件**:通过`jmap -dump:format=b,file=<filename> <pid>`命令,我们可以...
JVM性能调优监控工具jps、jstack、jmap、jhat、...jps、jstack、jmap、jhat、jstat 等 JVM 性能调优监控工具对于 Java 程序员来说是必备的,能够帮助我们解决各种 JVM 性能问题,提高 Java 应用程序的性能和稳定性。
jstack工具目前仅在Solaris和Linux的JDK版本中提供。 jconsole jconsole是一个基于Java Management Extensions (JMX)的实时图形化监测工具。该工具利用了内建到JVM中的JMX指令,提供实时的性能和资源的监控,包括...
jmap、jstack、jstat组合使用定位jvm问题
上述工具共同构成了Java开发者和运维人员的有力武器库,帮助他们在面对复杂多变的JVM问题时能够迅速定位、分析并解决问题。每一种工具都有其独特的优势和适用场景,了解并熟练运用它们,将极大地提升处理Java应用...
本文主要介绍了四个Java命令行工具:jps、jmap、jstack和jstat,它们是Java性能分析和故障排查的基础。 1. **jps (Java Process Status)**: 用于查看运行在本地机器上的Java进程ID,这对于其他命令来说是必需的输入...
本篇将重点介绍几种常用的JVM监控工具,包括jstack、jconsole、jinfo、jmap以及jdb和jstat。 首先,`jstack`是一个用于打印Java线程堆栈跟踪的工具。当应用出现死锁或者线程阻塞时,jstack可以帮助我们查看各个线程...
**jmap Eclipse内存分析工具详解** 在Java开发中,内存管理是至关重要的,尤其是在大型应用或者长时间运行的服务中,内存泄漏可能导致系统性能下降甚至崩溃。为了有效地检测和诊断内存问题,Oracle提供了`jmap`...
通过jstack与jmap分析一次线上故障.pdf
本文将详细探讨Java内存分析、dump分析、jmap和jstack工具的使用,以及如何利用这些工具进行堆栈分析。 首先,Java内存分析主要关注的是程序运行时的内存分配和管理。Java内存分为堆内存(Heap)、栈内存(Stack)...
为了监控Java应用的性能,可以使用`jps`(Java进程状态)列出运行中的Java进程,`jstat`(JVM统计监测工具)查看JVM的统计信息,`jmap`(内存映射工具)生成堆转储,以及`jhat`(堆分析工具)分析堆转储。...
jstack命令是一个强大的工具,用于分析Java程序的崩溃原因和堆栈信息。它可以将core文件转换为人类可读的格式,方便开发者快速定位问题所在。如果Java程序崩溃生成core文件,jstack工具可以用来获得core文件的Java栈...
4. **其他开发工具**:OpenJDK 1.8.0还包括其他的开发工具,如`jmap`用于内存映射,`jhat`用于分析堆转储,`jinfo`获取Java配置信息,`jstack`用于查看线程堆栈跟踪,以及`jconsole`图形化监控工具等。这些工具对于...
`JDK`自带了一些实用工具,如`jps`(Java进程查看器),`jinfo`(获取Java进程配置信息),`jmap`(内存映射工具),`jstack`(线程堆栈跟踪)等。这些工具可以帮助开发者进行性能监控和问题排查。 除此之外,`...
同时,JDK还包含`javadoc`工具用于生成API文档,`jps`、`jstack`、`jmap`等用于监控和诊断Java进程。 总之,"最新Java JDK 8安装版(Linux 64位)"为Linux开发者提供了稳定可靠的开发环境,结合其新特性和改进的API...
此外,`jps`、`jstat`、`jmap`和`jstack`等JDK附带的诊断工具在性能监控和问题排查中非常有用。 在Linux环境下,Java的性能调优主要包括JVM参数的调整。JVM参数分为启动参数(-X)和标准参数(-XX)两类,例如`-Xms`和`...
在Java开发中,理解JDK提供的工具非常重要,例如`javac`用于编译Java源代码,`javadoc`生成API文档,`jar`工具用于打包和管理类库,还有`jps`、`jmap`、`jconsole`等用于诊断和监控Java应用程序。 Java SE 8引入了...
总结,IBM内存分析工具是Java开发者诊断和优化内存问题的得力助手,结合jmap命令,可以深入到内存管理的底层,有效提升应用的稳定性和性能。通过熟练掌握这些工具和技巧,可以更好地应对复杂的内存管理挑战。