1. 原来jdk自带了这么好玩的工具——使用 jstack定位死循环
线程快照是java虚拟机内每一个线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现问题的位置;常见的问题有
命令格式
jstack的option参数并不多,真正用到的也就三个,接下来我们一个个介绍一下
- -F :当线程挂起(Suspended)时,使用jstack -l pid命令是不会打印堆栈信息的,使用-F则可以强制输出线程堆栈;但是会停止但
- -l :打印的信息除了堆栈外,还会显示锁芹梁返的附加信息;
- -m :同时输出java和C/C++的堆栈信息;在java的系统类库里面,有很多方法都是native修饰的,这些native修饰的方法你在java层面是看不到源码的,因为这些方法都是C/C++实现嫌饥的;
在线程的堆栈中,需要特别留意以下几种状态:
不带option参数的命令
打印结果如下
第一行各个单词的解析,
这里我们使用2个窗口,分别使用以下2个命令来测试
通过2个窗口对比可以看到,加了-l的命令多打印了锁的信息;
一般情况下,如果程序出错了, 都不会直接在生产环境的服务器上找错误,这个时候就可以用到一个非常实用的功能,将堆栈快照导出来,然后到别的电脑上看,命令如下
执行后,就可以看到文件已经导出来了
通过cat命令可以看到,里面的内容和我们在命令行输出的内容是一样的
首先我们准备好一个死循环的线程,在线程内定一个while的死循环,并且给这个线程起个名字为:yexindogn,阿里巴巴的开发规范里面有一个规定,就是每个线程必须起一个名字,起名字就是为了 以后程序出问题的时候好找错误;
接着我们将此代码打成jar包扔到linux服务器上运行,直接输入 java -jar Test.jar 命令即可运行,运行后我们可以看到控制台一直在输出112这个字符,这就代表程序已经在运行了;
接着在看下CPU的运行情况,使用top命令查看cpu占用情况,排在第一位的是进程号为30328的进程,占用了6.6%的cpu; 这边我使用了2个命令行连到同一台服务器,一个窗口用来运行刚刚的jar包,另一个窗口用来查找错误;
知道进程号了,接着就是找线程了,输入以下命令
打印结果如下,这里有一点需要注意,在我们加上-Hp指令后,PID展示就是线程的id了,这时候我们看到占用CPU最高的线程id是30365;
还有另一种方式,就是使用ps命令来查找线程
通过这个命令我们可以看到这边占用最高的线程id也是30365 ;
以上的方式我们成功找到了占用cpu高的线程id是30365,但这个id是十进制的,在这里需要先转为16进制,输入命令
计算出对应的16进制为:769d
当然也可以用其他的计算工具,比如mac系统自带计算器就支持进制之间的转换
在命令行输入以下命令,这种方法更加快速,推荐使用
其中,grep 命令是查找结果为769d的内容,-A 20 表示打印匹配所在行的后20行内容。直接帮我们定位到所在线程的堆栈,结果如下
当然也可以用下面的死办法,先打印出所有的堆栈快照;
打印结果如下
接着我用刚刚计算出来的16进制复制出来在这里搜索一下,经过查看就知道是我们刚刚起了名字为yexindong的线程出错了,出错的位置在Test.java的第13行代码
我们看看java代码,确实是第13行这里的死循环导致的
首先打开任务管理器,因为默认windows的任务管理器是不显示进程pid的,所以我们需要设置一下,选择 查看 选择列(S)...
选中PID进程表示符后点击确定按钮
然后我们就可以看到占用CPU最高的java进程PID为:976
因为windows不能直接查看java进程中的线程信息,所以我们需要借助一个工具,渣指这个工具是微软自己开发的,叫做Process Explorer ,网上很多,需要的童鞋请自行网络,打开后找到pid为976的进程右击选择 属性
在弹出的窗口中找到线程这一栏,它的排序默认就是按照cpu占用的率倒序排列的,所以最上面的就是占用cpu最高的线程了,记住它的线程id:3548
刚刚拿到的进程id是十进制的,但是我们导出的jstack信息里面,线程id是以16进制来展示的,所以我们要先将这个线程id为3548转为16进制的,使用windows自带的计算器即可,在快捷命令行输入calc
计算器打开后将其设置为程序员使用的计算器
接着输入线程id3548,在按一下16进制,就会自动进行转换,结果为ddc,记住这个16进制;
在命令行输入以下指令导出进程的堆栈快照信息
几秒钟后,快照导出了,静静地躺在文件夹里,等待着我们打开
用Notepad++打开导出的文件,搜索刚刚计算出来的16进制ddc,就可以定位到线程出错的位置了
有些童鞋可能会觉得用这个jstack命令麻烦了,那java在代码里面可不可以打印出堆栈呢?你别说,还真有,就是这个方法:Thread.getAllStackTraces();光说不练假把式,来个demo测试一下吧
执行后打印结果如下,由此可以看到,将当前进程的所有线程都打印出来了,但是这边只打印了简单的堆栈信息,对于开发人员来说,已经起到了监控作用;
作为调优和找错的工具来说,可以说jstack是用的最多的一个工具了,但是由于局限性,现在已经慢慢被替换掉了;大家更倾向于使用阿里巴巴开发的工具arthas;感兴趣的童鞋可以了解下!
2. 通过top和jstack确定哪些线程耗尽了CPU这些线程在做什么
背景
有时,线上集群load会突然飙升,无法响应正常请求。
那么引起load飙升的线程究竟在做什么?哪些线程霸占了CPU?可以通过top和jstack命令进行定位。
2. 定位步骤
1. 使用终端1进入目标机器,执行top命令,默认是进程视图,其中PID是进程号,截图如下:
在这里,我们只能看到java进程占用CPU达到115%,那么究竟是那些线程非常耗CPU呢?
2. 由于我们要看到线程,在终端1,按下“H”键或者“shift+h”,top视图会切换到线程视图,其中PID是线程号,截图如下:
可以发现红框内的线程的CPU使用率非常高,占用CPU时间达燃卖到1秒左右,显然不正常,但是这些线程在做什么?
3.
打开终端2,使用举姿jstack命令输出这一时刻的线程栈,保存到文件,命名为jstack.log。注意:输出线程栈和保存top命令快照尽量同时进行。
4. 由于jstack.log文件记录的线程ID是16进制,需要将top命令展示的线程号转换为16进制,以15100为皮答逗例,在linux下输入命令:printf 0x%x 15100,得到15100的十六进制为0x3afc
5. 在jstack.log中搜索0x3afc关键字,可以清晰看到该线程在做刷新地址列表,如下图:
3. 总结
以前碰到集群load飙升时,有时会束手无策,不知从何查起。以后再发生类似问题时,可以使用这个方法,看下究竟是那些线程在长时间占用CPU,尽快定位问题和解决问题。
3. jstack 分析出线程id 如何找到进程吗
jstack 分析出线程id 如何找到进程
jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。
如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。
另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。
需要注意的问题:
l 不同的 JAVA虚机的线程 DUMP的创建方法和文件格式是不一样的,不同的 JVM版本, mp信息也有差别。
l 在实际运行中,往往一次 mp的信息,还不足以确认问题。建议产生三次 mp信息,如果每次 mp都指向同一个问题,我们才确定问题的典型性。
2、命令格式
$jstack [ option ] pid
$jstack [ option ] executable core
$jstack [ option ] [server-id@]remote-hostname-or-IP
参数说明:
pid: java应用程序的进程号,一般可以通过jps来获得;
executable:产生core mp的java可执行程序;
core:打印出的core文件;
remote-hostname-or-ip:远程debug服务器的名称或IP;
server-id: 唯一id,假如一台主机上多个远程debug服务;
示例:
$jstack –l 23561
线程分析:
一般情况下,通过jstack输出的线程信息主要包括:jvm自身线程、用户线程等。其中jvm线程会在jvm启动时就会存在。对于用户线程则是在用户访问时才会生成。
4. JDK命令介绍
命令jps用于列出java进程,直接运行jps不加任何参数,可以列出Java程序的进程ID以及Main函数等名称。
参数-q指定jps只输出进程ID,而不输出类的短名称
参数-m用于输出传递给Java进程(主函数)的参数
参数 -l用于输出主函数的完整路径
参数 -v可以显示传递给JVM的参数
jstat是一个可以用于观察Java应用程序运行时信息的工具。它的功能非常强大,可以通过它,查看堆信息的详细使用情况。主要用于监控虚拟机的各种运行状态信息,如类的装载、内存、垃圾回收、JIT编译器等,在没有GUI的服务器上,这款工具是首选的一款监控工具。
基本使用语法为:
选项option可以由以下值构成:
-class:显示ClassLoader的相关信息。
-compiler:显示JIT编译的相关信息。
-gc:显示与GC相关的堆信息。
-gccapacity:显示各个代的容量及使用情况。
-gccause:显示垃圾收集相关信息(同-gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因。
-gcnew:显示新生代信息。
-gcnewcapacity:显示新生代大小与使用情况。
-gcold:显示老年代与永久代的信息。
-gcoldcapacity:显示老年代的大小。
-gcmetacapacity:显示元空间的大小。(在java8之前是使用-gcpermcapacity显示永久代的大小)
-gcutil:显示垃圾收集信息。
-printcompilation:输出JIT编译的方法信息。
以上选项可以输入 jstat -options 查看。
-t 参数可以在输出信息前加一个 Timestamp 列,显示程序的运行时间。
-h 参数可以在周期性数据输出时,输出多少行数据后,跟着输出一个表头信息。
vmid 参数就是Java进程id。
interval 参数用于指定输出统计数据的周期,单位为毫秒。
count 用于指定一共输出多少次数据。
jinfo 可以用来查看正在运行的Java运行程序的扩展参数,甚至支持在运行时修改部分参数。可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息。
jmap 可以生成Java应用程序的堆快照和对象的统计信息。基本语法为:
option 选项如下:
-mp 生成java堆转储快照。格式为: -mp:[live,]format=b,file=,其中live子参数说明是否只mp出存活的对象
-finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效
-heap 显示java堆详细信息,如使用哪种收集器、参数配置、分代情况等,在Linux/Solaris平台下有效
-histo 显示堆中对象统计信息,包含类、实例对象、合集容量
-permstat 以ClassLoader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效
-F 当虚拟机进程对-mp选项没有相应时。可使用这个选项强制生成mp快照。只在Linux/Solaris平台下有效
使用 jhat 工具可以用于分析Java应用程序的堆快照内容。jhat 在分析完成后,使用HTTP服务器展示其分析结果。在浏览器中访问 http://localhost:7000/
jstack 可用于导出Java应用程序的线程堆栈。语法为:
-l选项用于打印锁的附加信息。
jstack 工具会在控制台输出程序中所有的锁信息,可以使用重定向将输出保存到文件。
通过 jstack 工具不仅可以得到线程堆栈,它还能自动进行死锁检查,输出找到的死锁信息。
之前所述的工具中,只涉及到监控本机的Java应用程序。而在这些工具中,一些监控工具也支持对远程计算机的监控(如:jps、jstat)。为了启用远程监控,则需要配合使用jstatd工具。
命令jstatd是一个RMI服务端程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信。jstatd服务器将本机的Java应用程序信息传递到远程计算机。
JConsole(Java Monitoring and ManagementConsole)工具时JDK自带的图形化性能监控工具。通过JConsole工具,可以查看Java应用程序的运行概况,监控堆信息、永久区使用情况、类加载情况等。
5. 监控tomcat内存线程数
可以使用以下方式监控 Tomcat 内存和搜核唤线程数:
监控 Tomcat 进程的内存使用情况,可以使用系统工具如 top(Linux/Unix)或 Task Manager(Windows),或者使用第三方监控工具如 jstat, jmap, VisualVM 等。
监控 Tomcat 线程数,可以使用 jstack 命令获取线程信息,然后统计线程数。例如,在 Linux/Unix 系统中,可以使用以下命令获取 Tomcat 进程的线程信息:
jstack -l <pid> | grep "java.lang.Thread.State" | wc -l
其中 <pid> 是 Tomcat 进程的进程号。该世凯命令会输出当前 Tomcat 进程中的线程数。
另外,也可以使用 Tomcat 内置的管理工具来监控内存和线程数。例如,在 Tomcat 8 或以上版本中,可以使用 Tomcat 自带的 Manager App 来监控 Tomcat 内存和线程数。在 Manager App 的首页上,可以看到 Tomcat 当前的内存使用情况和活动线程数。如果需要更详细的信息,可以点击页面上的 Server Status 或 Thread Pool 链接氏销,查看更详细的信息。
6. cmd查看java进程命令
jstack命令。在cmd中,利用jstack命令可以查看java的全部进程并枣并兄对其进行修改。cmd称为Windows命令处理器,有时也被称为蔽行命令shell或cmd提示符,命令提示符即cmd.exe,是一个32位的命令行程序,微软Windows系统基于Windows上的命令解释程序,类似于微软的DOS操作凳袭系统。
7. 利用 jstack 分析 mp文件
知识点:
1.Linux 的命令 vmstat l,查慎念看上下文切换次数 , cs 表示 content switch
2.jstack pid 查看 默认 进历凳程的mp 文件 ,
1)用 jps 查肢孝旅看 我们运行的项目pid,然后 jstack pid > 文件
2)grep java.lang.Thread.State m17|awk '{print $2$3$4$5}'|sort|uniq -c
3)vim 查询相关字符串 ,用小字母的n,可以查看下一个匹配的字符串
4)确定问题症状后,再分析。
8. 怎样使用jstack诊断Java应用程序故障
1. 首先来了解一下jstack这个命令的作用,jstack 是一个可以敏慧返回在应用程序上运行的各种各样线程的一个完整转储的实用程序,您可以使用它查明问题。jstack [-l] <pid>,jpid可以通过使用jps命令来查看当前Java程序的jpid值,-l是可选参数,它可以显示线程阻塞/死锁情况。
/**
* 死锁例子
* @author crane.ding
* @since 2011-3-20
*/
public class DeadLock {
public static void main(String[] args) {
final Object obj_1 = new Object(), obj_2 = new Object();
Thread t1 = new Thread("t1"){
@Override
public void run() {
synchronized (obj_1) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
synchronized (obj_2) {
System.out.println("thread t1 done.");
}
}
}
};
Thread t2 = new Thread("t2"){
@Override
public void run() {
synchronized (obj_2) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
synchronized (obj_1) {
System.out.println("thread t2 done.");
}
}
}
};
t1.start();
t2.start();
}
}
2. 以上DeadLock类是一个死锁的例子,假使在不知情的情况下,运行DeadLock后,发现等了N久厅穗都没有在屏幕打印线程完成信息。这个时候就可以使用jps查看该程序的扮拿卜jpid值和使用jstack来生产堆栈结果问题。
$ java -cp deadlock.jar DeadLock &
$
$ jps
3076 Jps
448 DeadLock
$ jstack -l 448 > deadlock.jstack
结果文件deadlock.jstack内容如下:
2011-03-20 23:05:20
Full thread mp Java HotSpot(TM) Client VM (19.1-b02 mixed mode, sharing):
"DestroyJavaVM" prio=6 tid=0x00316800 nid=0x9fc waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"t2" prio=6 tid=0x02bcf000 nid=0xc70 waiting for monitor entry [0x02f6f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.demo.DeadLock$2.run(DeadLock.java:40)
- waiting to lock <0x22a297a8> (a java.lang.Object)
- locked <0x22a297b0> (a java.lang.Object)
Locked ownable synchronizers:
- None
"t1" prio=6 tid=0x02bce400 nid=0xba0 waiting for monitor entry [0x02f1f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.demo.DeadLock$1.run(DeadLock.java:25)
- waiting to lock <0x22a297b0> (a java.lang.Object)
- locked <0x22a297a8> (a java.lang.Object)
Locked ownable synchronizers:
- None
"Low Memory Detector" daemon prio=6 tid=0x02bb9400 nid=0xa6c runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"CompilerThread0" daemon prio=10 tid=0x02bb2800 nid=0xcb8 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" daemon prio=10 tid=0x02bb1000 nid=0x7f4 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" daemon prio=10 tid=0x02bd2800 nid=0xd80 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" daemon prio=8 tid=0x02bab000 nid=0xe1c in Object.wait() [0x02d3f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
Locked ownable synchronizers:
- None
"Reference Handler" daemon prio=10 tid=0x02ba6800 nid=0xbe0 in Object.wait() [0x02cef000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x229e1048> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0x229e1048> (a java.lang.ref.Reference$Lock)
Locked ownable synchronizers:
- None
"VM Thread" prio=10 tid=0x02b6a400 nid=0x568 runnable
"VM Periodic Task Thread" prio=10 tid=0x02bc8400 nid=0x75c waiting on condition
JNI global references: 878
Found one Java-level deadlock:
=============================
"t2":
waiting to lock monitor 0x02baaeec (object 0x22a297a8, a java.lang.Object),
which is held by "t1"
"t1":
waiting to lock monitor 0x02baa2bc (object 0x22a297b0, a java.lang.Object),
which is held by "t2"
Java stack information for the threads listed above:
===================================================
"t2":
at com.demo.DeadLock$2.run(DeadLock.java:40)
- waiting to lock <0x22a297a8> (a java.lang.Object)
- locked <0x22a297b0> (a java.lang.Object)
"t1":
at com.demo.DeadLock$1.run(DeadLock.java:25)
- waiting to lock <0x22a297b0> (a java.lang.Object)
- locked <0x22a297a8> (a java.lang.Object)
Found 1 deadlock.
3.从这个结果文件看到发现了一个死锁,具体是线程t2在等待线程t1,而线程t1在等待线程t2造成的,同时也记录了线程的堆栈和代码行数,通过这个堆栈和行数就可以去检查对应的代码块,从而发现问题和解决问题。
9. kill-3生成的线程堆栈怎么查看
第一步:在终端运行Java程序
第二步:通过命令 pidof java 找到已经启动的java进程的ID,选择需要查看的java程序的进程ID
第三步:使用命令 kill -3 <java进行的 pid> 打印出java程序的线程堆栈信息
第四步:通常情况下运行的项目可能会比较大,那么这个时候打印的堆栈信息可能会有几千到几万行,为了方便查看,我们往往需要将输出内容进行重定向
使用linux下的重定向命令方式即可:例如: demo.sh > run.log 2>&1 将输出信息重定向到 run.log中。
注:在操作系统中,0 1 2分别对应着不同的含义, 如下:
0 : 标准输入,即:C中的stdin , java中的System.in
1 : 标准输出, 即:C中的stdout ,java中的System.out
2 : 错误输出, 即:C中的stderr , java中的System.err
Demo:
----------------------------------------------------------------------------------------------
Sources Code :
public class PrintThreadTrace {
Object obj1 = new Object();
Object obj2 = new Object();
public void func1(){
synchronized (obj1){
func2();
}
}
public void func2(){
synchronized (obj2){
while(true){
System.out.print("");
}
}
}
public static void main(String[] args){
PrintThreadTrace ptt = new PrintThreadTrace();
ptt.func1();
}
}
----------------------------------------------------------------------------------------------------------------
按照步骤操作后的打印输出信息:
Full thread mp Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):
"Service Thread" daemon prio=10 tid=0x00007fdc880a9000 nid=0x12a4 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x00007fdc880a7000 nid=0x12a3 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x00007fdc880a4000 nid=0x12a2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"JDWP Command Reader" daemon prio=10 tid=0x00007fdc50001000 nid=0x1299 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"JDWP Event Helper Thread" daemon prio=10 tid=0x00007fdc880a1800 nid=0x1298 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x00007fdc8809e000 nid=0x1297 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x00007fdc88091000 nid=0x1296 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x00007fdc88071800 nid=0x1295 in Object.wait() [0x00007fdc77ffe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" daemon prio=10 tid=0x00007fdc8806f800 nid=0x1294 in Object.wait() [0x00007fdc7c10b000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x00007fdc8800b800 nid=0x128e runnable [0x00007fdc8fef7000]
java.lang.Thread.State: RUNNABLE
at com.wenchain.study.PrintThreadTrace.func2(PrintThreadTrace.java:20)
- locked <0x00000000ecc04b20> (a java.lang.Object)
at com.wenchain.study.PrintThreadTrace.func1(PrintThreadTrace.java:13)
- locked <0x00000000ecc04b10> (a java.lang.Object)
at com.wenchain.study.PrintThreadTrace.main(PrintThreadTrace.java:27)
"VM Thread" prio=10 tid=0x00007fdc8806b000 nid=0x1293 runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007fdc88021000 nid=0x128f runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007fdc88023000 nid=0x1290 runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007fdc88024800 nid=0x1291 runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007fdc88026800 nid=0x1292 runnable
"VM Periodic Task Thread" prio=10 tid=0x00007fdc880b3800 nid=0x12a5 waiting on condition
JNI global references: 1391
Heap
PSYoungGen total 17920K, used 1270K [0x00000000ecb00000, 0x00000000ede80000, 0x0000000100000000)
eden space 15872K, 8% used [0x00000000ecb00000,0x00000000ecc3d898,0x00000000eda80000)
from space 2048K, 0% used [0x00000000edc80000,0x00000000edc80000,0x00000000ede80000)
to space 2048K, 0% used [0x00000000eda80000,0x00000000eda80000,0x00000000edc80000)
ParOldGen total 39424K, used 0K [0x00000000c6200000, 0x00000000c8880000, 0x00000000ecb00000)
object space 39424K, 0% used [0x00000000c6200000,0x00000000c6200000,0x00000000c8880000)
PSPermGen total 21504K, used 2619K [0x00000000c1000000, 0x00000000c2500000, 0x00000000c6200000)
object space 21504K, 12% used [0x00000000c1000000,0x00000000c128edd8,0x00000000c2500000)
----------------------------------------------------------------------------------------------------------------------------
上面的信息中包含了当前JVM中所有运行的线程信息,其中在示例中我们启动的线程为main线程,其余的都是JVM自己创建的。
在打印的信息中,我们可以清楚的看见当前线程的调用上下文,可以很清楚的知道程序的运行情况。
并且我们在最后面还能看见当前虚拟机中的内存使用情况,青年世代,老年世代的信息等等...
PS: 在JDK1.5以上,我们可以通过在Java程序中调用Thread.getStackTrace()方法来进行堆栈的自动打印,使得线程堆栈的打印时机可编程控制。
文章知识点与官方知识档案匹配
Java技能树首页概览
89841 人正在系统学习中
点击阅读全文
打开CSDN,阅读体验更佳
jstack-查看Java进程的线程堆栈信息,锁定高消耗资源代码
jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下: jstack[option]pid jstack[option]executable core jstack[option][server-id@]remote-hostname-or-ip 命令行参数选项说明如下: ...
011Java并发包018查看线程堆栈信息_执笔未来的博客
java.util.concurrent.ScheledThreadPoolExecutor$DelayedWorkQueue.take(ScheledThreadPoolExecutor.java:1088) java.util.concurrent.ScheledThreadPoolExecutor$DelayedWorkQueue.take(ScheledThreadPoolExecutor.java:809) java.util.concurre...
最新发布 jstack -- java堆栈常用排查指令
jstack -- java堆栈常用排查指令
继续访问
热门推荐 jstack 命令查看JAVA线程堆栈
JAVA堆栈信息实际生产中,可能由于开发以及测试未能全面覆盖的代码质量、性能问题,而引致线程挂起甚至崩溃。可能就需要查看堆栈信息来排查问题了。jps -lvmjps -lvm 用于查看当前机器上运行的java进程。C:\Users\Administrator>jps -lvm 7348 -Dosgi.requiredJavaVersion=1.8 -Dosgi.instance.area.defa
继续访问
Java多线程——查看线程堆栈信息
Java多线程——查看线程堆栈信息 摘要:本文主要介绍了查看线程堆栈信息的方法。 使用Thread类的getAllStackTraces()方法 方法定义 可以看到getAllStackTraces()方法的返回值是一个Map对象,key是Thread的实例,value是一个StackTraceElement实例数组: 1 public static Map<Thread, S...
继续访问
java堆栈常用排查指令
java 异常排查四板斧 1、查看java 堆栈线程信息 说明 jstack命令打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息。 对于每个Java框架,完整的类名,方法名, 字节码索引(BCI)和行号(如果有的话)被打印出来。 使用-m选项,jstack命令打印程序中所有线程的Java和本机帧 计数器(PC)。 对于每个本机帧,当可用时,将打印离PC最近的本机符号。 c++乱码的名字不会被修改。 要demangle c++名称,输出这个 命令可以管道到c++filt。 当
继续访问
java诊断工具-Arthas(thread命令)查看当前线程堆栈
cpu使用率与linux 命令top -H -p <pid>的线程CPU类似 1、支持一键展示当前最忙的前N个线程并打印堆栈 thread -n 3 没有线程ID,包含[Internal]表示为JVM内部线程,参考dashboard命令的介绍。 cpuUsage为采样间隔时间内线程的CPU使用率,与dashboard命令的数据一致。 deltaTime为采样间隔时间内线程的增量CPU时间,小于1ms时被取整显示为0ms。 time线程运行总CPU...
继续访问
java查看线程的堆栈信息
通过使用jps 命令获取需要监控的进程的pid,然后使用jstackpid 命令查看线程的堆栈信息。 通过jstack命令可以获取当前进程的所有线程信息。 每个线程堆中信息中,都可以查看到线程ID、线程的状态(wait、sleep、running 等状态)、是否持有锁信息等。 jstack -l <pid> >jvm_listlocks.txt 转...
继续访问
java 查看线程堆栈信息_Java多线程——查看线程堆栈信息
java多线程——查看线程堆栈信息摘要:本文主要介绍了查看线程堆栈信息的方法。使用thread类的getallstacktraces()方法方法定义可以看到getallstacktraces()方法的返回值是一个map对象,key是thread的实例,value是一个stacktraceelement实例数组:1 public static map getallstacktraces()使用可以使...
继续访问
java线程堆栈信息分析
java堆栈信息分析
继续访问
java 查看堆栈_javap 命令查看堆栈中信息
javap命令是对.java文件进行反编译,通过这个命令可以看到堆栈中是怎么压栈和出栈的已经执行顺序,这里简单解释下javap的简单的使用,下面举个例子:题目:i++ 和++i的区别解释:简单点说 这个问题都不难回答,这里就不说了,但是实际上堆栈中区别也是老大了(这里就用到了javap命令), 步骤:1.在任意一个盘下面建一个名为Test.java的文件(文件名可以随意命名)代码如下:public...
继续访问
java 查看线程堆栈信息_jstack-查看Java进程的线程堆栈信息,锁定高消耗资源代码。...
jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:jstack[option]pidjstack[option]executablecorejstack[option][server-id@]remote-hostname-or-ip命令行参数选项说明如下:-llonglistings,会打印出额外的锁信息,在发生死锁时可以用jstack-lpid来观察...
继续访问
java堆栈信息怎么看_线程堆栈信息怎么看? - cs_person的个人空间 - OSCHINA - 中文开源技术交流社区...
一条线程堆栈信息大概长成下面这个样子:RMI TCP Connection(267865)-172.16.5.25" daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd4f8684000]java.lang.Thread.State: BLOCKED (on object m...
继续访问
线程堆栈信息怎么看?
一条线程堆栈信息大概长成下面这个样子: RMI TCP Connection(267865)-172.16.5.25" daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd...
继续访问
java的栈和堆
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 Java 的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在...
继续访问
查看java线程_【JAVA】Java线程堆栈信息查看
如何获得线程的堆栈信息?线上服务器cpu 100%了,该如何排查问题?1.top命令查询哪个pid进程占用cpu高(ps -ef|grep java 获取PID号)2.通过 top -Hp pid 可以查看该进程下各个线程的cpu使用情况,获取占用cpu高的线程id3.执行命令:printf "%X\n" 线程tid(用于获取占用cpu高的线程id的16进制数)4.执行命令:jstack pid ...
继续访问
kill -3 java_kill -3 PID命令获取java应用堆栈信息
一、应用场景:当linux服务器出现异常情况(响应缓慢,负载持续飙升)并且服务器没有安装对应的包而无法使用jstack等命令时,可以使用linux的kill相关命令打印堆栈信息。命令格式:kill -3 PID二、执行步骤:2.1、获取java进程的PIDps -ef|grep java结果的第二列数字就是进程对应的pid。2.2、kill -3 PID(1)如果项目通过Tomcat进行发布(普通...
继续访问
jstack 工具 查看JVM堆栈信息
1|0介绍 jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或corefile或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式: jstack [-l] pid 主要分为两个功能: a. 针对活着的进程做本地的或远程的线程mp; b. 针对core文件做线程mp。 jstack用于生成java虚拟机当前时刻的线程快照。线程快照是...
继续访问
linux查看java堆栈
1、查看JAVA进程JVM参数 jinfo -flags pid(进程号) -XX:CICompilerCount=2 最大的并行编译数 -XX:InitialHeapSize=16777216 JVM 的初始堆内存大小 -XX:MaxHeapSize=257949696 JVM 的最大堆内存大小 -XX:MaxNewSize=85983232 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=5570560 -XX:OldSize=11206656 2、JVM 查看.
继续访问
Linux 如何查看一个进程的堆栈
有两种方法:第一种:pstack 进程ID第二种,使用gdb 然后attach 进程ID,然后再使用命令 thread apply all bt 两种方法都可以列出进程所有的线程的当前的调用栈。不过,使用gdb的方法,还可以查看某些信息,例如局部变量,指针等。不过,如果只看调用栈的话,pstack还是很方便的。
继续访问
JAVA获取堆栈信息
1. 通过Throwable获取 StackTraceElement[] stackTrace = new Throwable().getStackTrace(); 2. 通过Thread获取 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
继续访问
java 查看线程栈大小_基于 Java 线程栈的问题排查
除日志外,还有没有别的方式跟踪线上服务问题呢?或者,跟踪并排除日志里无法发现的问题?方法当然是有的,就是通过现场快照定位并发现问题。我们所说的现场,主要指这两方面:Java 线程栈。线程栈是Java线程工作的快照,可以获得当前线程在做什么;Java 内存堆。堆是JVM的内存快照,可以获取内存分配相关信息。
10. 在新建虚拟机时出现问题
JConsole
JConsole 图形用户界面是一种符合 Java 管理扩展(JMX)规范的监视工具。JConsole 使用 Java 虚拟机 (Java VM) 的广泛检测来提供有关在 Java 平台上运行的应用程序的性能和资源消耗的信息。
使用方法 本地
使用jconsole命令:监视本地运行的所有 Java 应用程序,JConsole 可以连接到这些应用程序。
使用jconsole PID命令:监视指定PID的Java应用程序。
使用jsconsole hostName:portNum命令:hostName是运行应用程序的系统的名称,portNum是您在启动Java VM时启用 JMX 代理时指定的端口号。
使用service:jmx::命令:使用 JMX 服务 URL 进行连接。
内容分析
将 JConsole 连接到应用程序后,JConsole 由六个选项卡组成。
概述:显示有关 Java VM 和受监视值的概述信息。
内存:显示有关内存使用的信息。
线程:显示有关线程使用的信息。
类:显示有关类加载的信息。
VM:显示有关 Java VM 的信息。
MBeans:显示有关 MBeans 的信息。
显示有关 CPU 使用情况、内存使用情况、线程计数和在Java VM中加载的类的图形监视信息。
提供执行GC的操作,可以随时点击按钮进行垃圾回收
伊甸园空间(堆):最初为大多数对象分配内存的池。
幸存者空间(堆):包含在伊甸园空间垃圾回收中幸存下来的物体的池。
终身代(堆):包含在幸存者空间中存在一段时间的对象的池。
永久生成(非堆):包含虚拟机本身的所有反射数据的池,如类和方法对象。使用类数据共享的 Java VM,这一代分为只读和读写区域。
代码缓存(非堆):HotSpotJava VM 还包括一个代码缓存,其中包含用于编译和存储本机代码的内存。
Java VM管理两种类型的内存:堆内存和非堆内存,这两种内存都是在 Java VM 启动时创建的。
堆内存是Java VM为所有类实例和数组分配内存的运行时数据区域。堆的大小可能是固定的或可变的。垃圾回收器是一个自动内存管理系统,用于回收对象的堆内存。
非堆内存包括所有线程之间共享的方法区域和Java VM的内部处理或优化所需的内存。它存储每类结构,如运行时常量池、字段和方法数据,以及方法和构造函数的代码。方法区域在逻辑上是堆的一部分,但是,根据实现,Java VM 可能不会对它进行垃圾回收或压缩。与堆内存一样,方法区域可能为固定大小或可变大小。方法区域的内存不需要连续。
内存池和内存管理器是Java VM内存系统的关键方面。
内存池表示Java VM管理的内存区域。Java VM至少有一个内存池,它可能会在执行期间创建或删除内存池。内存池可以属于堆内存或非堆内存。
内存管理器管理一个或多个内存池。垃圾回收器是一种内存管理器,负责回收不可到达的对象使用的内存。Java VM可能具有一个或多个内存管理器。它可以在执行期间添加或删除内存管理器。内存池可以由多个内存管理器管理。
垃圾回收 (GC) 是Java VM释放不再引用的对象占用的内存的方式。通常认为具有活动引用为"活动"且未引用(或无法访问)对象的对象为"已死"。垃圾回收是释放死对象使用的内存的过程。GC 使用的算法和参数对性能有显着影响。
Java hotspot VM垃圾回收器使用代数 GC。生成 GC 利用大多数程序符合以下概括的观察。
它们创建许多寿命较短的对象,例如迭代器和局部变量。
它们创建一些寿命很长的对象,例如高级持久对象。
提供有关线程使用的信息。
查找监视器死锁线程:检测对象监视器锁上是否有任何线程死锁。此操作返回死锁线程指示的数组。
getThreadInfo:返回线程信息。这包括线程当前被阻止的名称、堆栈跟踪和监视器锁(如果有)以及持有该锁的线程以及线程争用统计信息。
获取ThreadCpu时间:返回给定线程消耗的 CPU 时间
显示有关类加载的信息。
提供有关Java VM的信息。
以通用方式显示有关在平台 MBean 服务器注册的所有 MBeans 的信息。MBeans 选项卡允许您访问平台 MXBean 检测的完整集,包括在其他选项卡中不可见的仪器。此外,您还可以使用 MBeans 选项卡监视和管理应用程序的 MBeans。
列出目标系统上已检测的 Java 虚拟机 (JVM)。
监视 Java 虚拟机 (JVM) 统计信息。
对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
命令格式
jstat [-option] [PID]
option参数
class:显示有关类加载器行为的统计信息。
compiler:显示有关Java HotSpot VM实时编译器行为的统计信息。
gc:显示有关垃圾回收堆行为的统计信息。
gccapacity:显示有关几代人容量及其相应空间的统计信息。
gccause:显示有关垃圾回收统计信息(与 相同)的摘要,以及最后和当前(如果适用)垃圾回收事件的原因。-gcutil
gcnew:显示新一代行为的统计信息。
gcnewcapacity:显示有关新一代大小及其相应空间的统计信息。
gcold:显示有关旧一代和元空间统计信息行为的统计信息。
gcoldcapacity:显示有关旧一代大小的统计信息。
gcmetacapacity:显示有关元空间大小的统计信息。
gcutil:显示有关垃圾回收统计信息的摘要。
printcompilation:显示 Java 热点 VM 编译方法统计信息。
1.jstat –class: 显示加载class的数量,及所占空间等信息。
2.jstat -compiler显示VM实时编译的数量等信息。
3.jstat -gc: 可以显示gc的信息,查看gc的次数,及时间。
4.jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小
5.jstat -gcutil:统计gc信息
6.jstat -gcnew:年轻代对象的信息。
7.jstat -gcnewcapacity: 年轻代对象的信息及其占用量。
8.jstat -gcold:old代对象的信息。
9.jstat -gcoldcapacity: old代对象的信息及其占用量。
10.jstat -gcpermcapacity: perm对象的信息及其占用量。
11.jstat -printcompilation:当前VM执行的信息。
监视 Java 虚拟机 (JVM),并使远程监视工具能够连接到 JVM
命令格式
jstatd -[option]
option
-nr当找不到现有的RMI注册表时,不尝试使用jstatd进程创建一个内部的RMI注册表。
-p port在指定的端口查找RMI注册表。如果没有找到,并且没有指定-nr选项,则在该端口自行创建一个内部的RMI注册表。
-n rminameRMI注册表中绑定的RMI远程对象的名称。默认的名称为JStatRemoteHost。如果多个jstatd服务器在同一主机上运行,你可以通过指定该选项来让每个服务器导出的RMI对象具有唯一的名称。不管如何,这样做需要将唯一的服务器名称包含进监控客户端的hostid和vmid字符串中。
-Joption将选项参数传递给被javac调用的java启动程序。例如,-J-Xms48m设置启动内存为48 MB。使用-J将选项参数传递给执行Java应用程序的底层虚拟机,这是一种常见惯例。
使用方法
1.在jdk的bin目录下创建文件jstatd.all.policy
2.写入下面的安全配置
grant codebase "file:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/lib/tools.jar" {
permission java.security.AllPermission;
#此处写绝对路径,主要是防止路径错误问题,排查问题,应该写成相对路径
3.启动jstatd
./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=x.x.x.x &
4.使用jvisualvm工具远程连接,进行监控
jvisualvm
VisualVM,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的).
同时他还提供很多插件可以自己安装,是一款不错的监控分析工具。
故障排除工具 JInfo
可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息
命令格式
参数说明
pid对应jvm的进程id
executable core产生core mp文件
[server-id@]remote server IP or hostname远程的ip或者hostname,server-id标记服务的唯一性id
option
no option输出全部的参数和系统属性
-flag name输出对应名称的参数
-flag [+|-]name开启或者关闭对应名称的参数
-flag name=value设定对应名称的参数
-flags输出全部的参数
-sysprops输出系统属性
Javacore 概述
Javacore,也可以称为“threadmp”或是“javamp”,它是 Java 提供的一种诊断特性,能够提供一份可读的当前运行的 JVM 中线程使用情况的快照。即在某个特定时刻,JVM 中有哪些线程在运行,每个线程执行到哪一个类,哪一个方法。应用程序如果出现不可恢复的错误或是内存泄露,就会自动触发 Javacore 的生成。
使用方法
1.jinfo pid:输出当前 jvm 进程的全部参数和系统属性
2.jinfo -flag name pid:输出对应名称的参数使用该命令,可以查看指定的 jvm 参数的值。如:查看当前 jvm 进程是否开启打印 GC 日志。
3.jinfo -flag [+|-]name pid:开启或者关闭对应名称的参数
使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用。
4.jinfo -flag name=value pid:修改指定参数的值。
5.jinfo -flags pid:输出全部的参数
6.jinfo -sysprops pid:输出当前 jvm 进行的全部的系统属性
jhat
主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。
1.使用jmap命令导出堆文件jmap -mp:live,file=a.log pid
也可以使用下面方式导出堆文件
1、使用jconsole选项通过HotSpotDiagnosticMXBean从运行时获得堆转储(生成mp文件)、
2、虚拟机启动时如果指定了-XX:+HeapDumpOnOutOfMemoryError选项, 则在抛出OutOfMemoryError时, 会自动执行堆转储。
3、使用hprof命令
2.使用jhat分析堆文件jhat -J-Xmx512M a1.log
3.查看分析的html页面
http://ip:7000/jhat中的OQL(对象查询语言)
如果需要根据某些条件来过滤或查询堆的对象,这是可能的,可以在jhat的html页面中执行OQL,来查询符合条件的对象
基本语法:
select
[from [instanceof] ]
[where ]
解释:
(1)class name是java类的完全限定名,如:java.lang.String,java.util.ArrayList, C是char数组,java.io.File是java.io.File[]
(2)类的完全限定名不足以唯一的辨识一个类,因为不同的ClassLoader载入的相同的类,它们在jvm中是不同类型的
(3)instanceof表示也查询某一个类的子类,如果不明确instanceof,则只精确查询class name指定的类
(4)from和where子句都是可选的
(5)java域表示:obj.field_name;java数组表示:array[index]
举例:
(1)查询长度大于100的字符串
select s from java.lang.String s where s.count > 100
(2)查询长度大于256的数组
select a from [I a where a.length > 256
(3)显示匹配某一正则表达式的字符串
select a.value.toString() from java.lang.String s where /java/(s.value.toString())
(4)显示所有文件对象的文件路径
select file.path.value.toString() from java.io.File file
(5)显示所有ClassLoader的类名
select classof(cl).name from instanceof java.lang.ClassLoader cl
(6)通过引用查询对象
select o from instanceof 0xd404d404 o
built-in对象 -- heap
(1)heap.findClass(class name) -- 找到类
select heap.findClass("java.lang.String").superclass
(2)heap.findObject(object id) -- 找到对象
select heap.findObject("0xd404d404")
(3)heap.classes -- 所有类的枚举
select heap.classes
(4)heap.objects -- 所有对象的枚举
select heap.objects("java.lang.String")
(5)heap.finalizables -- 等待垃圾收集的java对象的枚举
(6)heap.livepaths -- 某一对象存活路径
select heaplivepaths(s) from java.lang.String s
(7)heap.roots -- 堆根集的枚举
辨识对象的函数
(1)classof(class name) -- 返回java对象的类对象
select classof(cl).name from instanceof java.lang.ClassLoader cl
(2)identical(object1,object2) -- 返回是否两个对象是同一个实例
select identical(heap.findClass("java.lang.String").name, heap.findClass("java.lang.String").name)
(3)objectid(object) -- 返回对象的id
select objectid(s) from java.lang.String s
(4)reachables -- 返回可从对象可到达的对象
select reachables(p) from java.util.Properties p -- 查询从Properties对象可到达的对象
select reachables(u, "java.net.URL.handler") from java.net.URL u -- 查询从URL对象可到达的对象,但不包括从URL.handler可到达的对象
(5)referrers(object) -- 返回引用某一对象的对象
select referrers(s) from java.lang.String s where s.count > 100
(6)referees(object) -- 返回某一对象引用的对象
select referees(s) from java.lang.String s where s.count > 100
(7)refers(object1,object2) -- 返回是否第一个对象引用第二个对象
select refers(heap.findObject("0xd4d4d4d4"),heap.findObject("0xe4e4e4e4"))
(8)root(object) -- 返回是否对象是根集的成员
select root(heap.findObject("0xd4d4d4d4"))
(9)sizeof(object) -- 返回对象的大小
select sizeof(o) from [I o
(10)toHtml(object) -- 返回对象的html格式
select "+ toHtml(o) + "" from java.lang.Object o
(11)选择多值
select {name:t.name?t.name.toString():"null",thread:t} from instanceof java.lang.Thread t
数组、迭代器等函数
(1)concat(enumeration1,enumeration2) -- 将数组或枚举进行连接
select concat(referrers(p),referrers(p)) from java.util.Properties p
(2)contains(array, expression) -- 数组中元素是否满足某表达式
select p from java.util.Properties where contains(referres(p), "classof(it).name == 'java.lang.Class'")
返回由java.lang.Class引用的java.util.Properties对象
built-in变量
it -- 当前的迭代元素
index -- 当前迭代元素的索引
array -- 被迭代的数组
(3)count(array, expression) -- 满足某一条件的元素的数量
select count(heap.classes(), "/java.io./(it.name)")
(4)filter(array, expression) -- 过滤出满足某一条件的元素
select filter(heap.classes(), "/java.io./(it.name)")
(5)length(array) -- 返回数组长度
select length(heap.classes())
(6)map(array,expression) -- 根据表达式对数组中的元素进行转换映射
select map(heap.classes(),"index + '-->' + toHtml(it)")
(7)max(array,expression) -- 最大值, min(array,expression)
select max(heap.objects("java.lang.String"),"lhs.count>rhs.count")
built-in变量
lhs -- 左边元素
rhs -- 右边元素
(8)sort(array,expression) -- 排序
select sort(heap.objects('[C'),'sizeof(lhs)-sizeof(rhs)')
(9)sum(array,expression) -- 求和
select sum(heap.objects('[C'),'sizeof(it)')
(10)toArray(array) -- 返回数组
(11)unique(array) -- 唯一化数组
jmap
打印进程、核心文件或远程调试服务器的共享对象内存映射或堆内存详细信息。
jmap [option]
(to connect to running process) 连接到正在运行的进程
jmap [option]
(to connect to a core file) 连接到核心文件
jmap [option] [server_id@]
(to connect to remote debug server) 连接到远程调试服务
option
pid:目标进程的PID,进程编号,可以采用ps -ef | grep java查看java进程的PID;
executable:产生core mp的java可执行程序;
core:将被打印信息的core mp文件;
remote-hostname-or-IP:远程debug服务的主机名或ip;
server-id:唯一id,假如一台主机上多个远程debug服务;
使用方法
jmap -mp:[live,]format=b,file= PID:使用hprof二进制形式,输出jvm的heap内容到文件
jmap -finalizerinfo PID:打印正等候回收的对象的信息
jmap -heap PID:打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况。
jmap -histo:live PID:打印每个class的实例数目,内存占用,类全名信息。VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
jmap -permstat PID:打印classload和jvm heap长久层的信息. 包含每个classloader的名字、活泼性、地址、父classloader和加载的class数量。另外,内部String的数量和占用内存数也会打印出来。
-F强迫.在pid没有相应的时候使用-mp或者-histo参数。在这个模式下,live子参数无效。
-h | -help打印辅助信息
-J传递参数给jmap启动的jvm.
jstack命令主要用于调试java程序运行过程中的线程堆栈信息,可以用于检测死锁,进程耗用cpu过高报警问题的排查。jstack命令会打印出所有的线程,包括用户自己启动的线程和jvm后台线程。
命令格式
jstack -[option] pid
option
-F强制mp线程堆栈信息. 用于进程hung住,jstack命令没有响应的情况
-m同时打印java和本地(native)线程栈信息,m是mixed mode的简写
-l打印锁的额外信
公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!
最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!
(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!
------ 特别推荐 ------
特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,“大咖笔记”,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。
文章有帮助的话,在看,转发吧!