没有合适的资源?快使用搜索试试~ 我知道了~
首页Java线程堆栈分析与性能瓶颈定位
Java线程堆栈分析与性能瓶颈定位
需积分: 9 5 下载量 190 浏览量
更新于2024-07-18
收藏 3.16MB PDF 举报
"Java问题定位技术文档详细探讨了在开发过程中如何有效地利用Java线程堆栈分析来解决系统瓶颈和内存泄漏问题。首先,章节1介绍了线程堆栈的输出和解读,包括线程状态、锁的含义,以及如何通过堆栈追踪分析线程死锁、CPU过高、代码循环、资源消耗、系统挂死和锁链等问题。接着,第二部分深入讨论了性能瓶颈的常见原因、分析手段和工具,如模拟性能瓶颈、利用操作系统统计工具、专业分析工具(如runhprof、JProfiler等)以及调整JVM参数。这部分强调了性能调优的条件和注意事项。 在第三部分,文档关注Java内存泄漏的背景知识,包括Java对象大小、引用关系、自动垃圾回收机制以及如何确保内存释放。它澄清了关于将对象设为null就能避免内存泄漏的误解,并详细解释了内存泄漏与OOM(Out Of Memory)的关系。最后,讲解了内存泄漏的定位方法,如观察症状、理解内存分配和回收过程,以及如何通过各种工具和技术进行有效检测和管理。 这篇文档为开发者提供了一套全面的Java问题定位技巧,涵盖了从线程堆栈分析到内存管理的关键知识点,旨在帮助他们更高效地诊断和优化Java应用程序的性能和稳定性。"
资源详情
资源推荐
![](https://csdnimg.cn/release/download_crawler_static/10772213/bg10.jpg)
4 1 JAVA线程堆栈分析
2>&1表示将错误输出重定向到标准输出流中,即将标准输出和错误输出都重定向到一个文件
中。
提示:
在JDK1.5以上的版本中,可以在Java程序中通过Thread.getStackTrace()控制堆栈自动打
印.通过这种方式,线程堆栈的打印时机可编程。通过手工编程,可以在满足某些条件时,
将线程堆栈自动打印。
![](https://csdnimg.cn/release/download_crawler_static/10772213/bg11.jpg)
1 JAVA线程堆栈分析 5
§1.2 如何解读线程堆栈?
下面通过一个实际的例子对线程堆栈的解读进行详细介绍。掌握了线程堆栈解读的方法,
就可以庖丁解牛,对线程堆栈进行深入剖析。
§1.2.1 线程的解读
如下面一段Java源代码程序:
public class MyTest {1
Object obj1 = new Object();2
Object obj2 = new Object();3
public void fun1()4
{5
synchronized(obj1){6
fun2();7
}8
}9
public void fun2()10
{11
synchronized(obj2){12
while(true){ //为了演示需要,该函数永不退出13
System.out.print("");14
}15
}16
}17
public static void main(String[] args) {18
MyTest aa = new MyTest();19
aa.fun1();20
}21
运行该程序: java MyTest,通过上节介绍的方法打印线程堆栈,打印的线程堆栈如下(Linux下)
3
:
Full thread dump Java HotSpot(TM) Client VM (1.5.0_08-b03 mixed mode, sharing):
"Low Memory Detector" daemon prio=1 tid=0x080a5848 nid=0xd2e runnable //第(1)个线程
"CompilerThread0" daemon prio=1 tid=0x080a42a0 nid=0xd2d waiting on condition//(2)
"Signal Dispatcher" daemon prio=1 tid=0x080a31d8 nid=0xd2c runnable //(3)
"Finalizer" daemon prio=1 tid=0x0809c660 nid=0xd2b in Object.wait() //(4)
at java.lang.Object.wait(Native Method)
- waiting on <0xc8bf06c8> (a java.lang.ref.ReferenceQueue$Lock)
3
为了排版需要,将某些线程的地址信息给删除掉了,这些信息在问题分析中用处不大,如:"Reference
Handler" daemon prio=1 tid=0x0809b970 nid=0xd2a in Object.wait()[0xf26d9000..0xf26da0b0]中后面的[]中的信
息给略掉了。
![](https://csdnimg.cn/release/download_crawler_static/10772213/bg12.jpg)
6 1 JAVA线程堆栈分析
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
- locked <0xc8bf06c8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=1 tid=0x0809b970 nid=0xd2a in Object.wait() //(5)
at java.lang.Object.wait(Native Method)
- waiting on <0xc8bf05d8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:474)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0xc8bf05d8> (a java.lang.ref.Reference$Lock)
"main" prio=1 tid=0x0805c988 nid=0xd28 runnable [0xfff65000..0xfff659c8] //(6)
at java.lang.String.indexOf(String.java:1352)
at java.io.PrintStream.write(PrintStream.java:460)
- locked <0xc8bf87d8> (a java.io.PrintStream)
at java.io.PrintStream.print(PrintStream.java:602)
at MyTest.fun2(MyTest.java:16)
- locked <0xc8c1a098> (a java.lang.Object)
at MyTest.fun1(MyTest.java:8)
- locked <0xc8c1a090> (a java.lang.Object)
at MyTest.main(MyTest.java:26)
"VM Thread" prio=1 tid=0x08098d88 nid=0xd29 runnable //(7)
"VM Periodic Task Thread" prio=1 tid=0x080a6d30 nid=0xd2f waiting on condition//(8)
在这段堆栈输出中可以看出,我们看出系统当前共有如下线程:Low Memory Detector、
CompilerThread0、Signal Dispatcher、Finalizer、Reference Handler、main、VM Thread、VM
Periodic Task Thread共八个,其中只有main线程属于Java用户线程,其它七个都是由虚拟机自
动创建的,如果是java界面程序,虚拟机还会自动创建事件分发线程awt-eventqueue等,我们在
实际分析的过程中,只关心Java用户线程即可。
从上面的main线程中看,线程堆栈里面的最直观的信息是当前线程的调用上下文,即从
哪个函数中调用到哪个函数中(从下往上看),正执行到哪个类的哪一行,借助这些信息,我
们就对当前系统正在做什么就一目了然。线程堆栈在分析问题中的作用请见后面的章节。其
中一个线程的某一层调用含义如下
4
:
4
如果括号中没有显示Java源代码文件名,可能是由于系统运行期间启动了JIT,JIT详见第 142页第 §7.3节。
![](https://csdnimg.cn/release/download_crawler_static/10772213/bg13.jpg)
1 JAVA线程堆栈分析 7
at MyTest.fun1(MyTest.java:8)
| | | |
| | | +-----当前正在调用的函数所在的源代码文件的行号
| | +------------当前正在调用的函数所在的源代码文件
| +---------------------当前正在调用的方法名
+---------------------------当前正在调用的类名
另外,从main线程的堆栈中,有"- locked <0xc8c1a090> (a java.lang.Object)"语句,这表示
该线程(即main线程)已经占有了锁<0xc8c1a090>,其中0xc8c1a090表示锁ID,这个锁的ID是系
统自动产生的,我们只需要知道每次打印的堆栈,同一个ID表示是同一个锁即可
5
。每一个线
程堆栈的第一行含义如下:
"main" prio=1 tid=0x0805c988 nid=0xd28 runnable [0xfff65000..0xfff659c8]
| | | | | |
| | | | | +--线程占用内存地址
| | | | +-----------线程的状态
| | | +----线程对应的本地线程id号
| | +-------------------线程id
| +--------------------------线程优先级
+-------------------------------线程名称
其中"线程对应的本地线程id号"所指的"本地线程"是指该Java线程所对应的虚拟机中的
本地线程。我们知道Java是解析型语言,执行的实体是Java虚拟机,因此Java语言中的线程是
依附于Java虚拟机中的本地线程来运行的,实际上是本地线程在执行Java线程代码。Java代码
中创建一个thread,虚拟机在运行期就会创建一个对应的本地线程,而这个本地线程才是真正
的线程实体。为了更加深入得理解本地线程和Java线程的关系,在Unix/Linux下,我们可以通
过如下方式把Java虚拟机的本地线程打印出来:
1. 使用ps -ef | grep java 获得Java进程ID。
2. 使用pstack <java pid>获得Java虚拟机的本地线程的堆栈
6
。
本例中,我们获取的本地线程堆栈如下:
Thread 8 (Thread 4067802000 (LWP 3369)):
#0 0xffffe402 in __kernel_vsyscall ()
#1 0x0082042c in pthread_cond_timedwait@@GLIBC_2.3.2 ()
#2 0x008208d5 in pthread_cond_timedwait@GLIBC_2.0 () from /lib/libpthread.so.0
#3 0xf7ab9e4c in os::Linux::safe_cond_timedwait ()
#4 0xf7aa5d71 in Monitor::wait ()
#5 0xf7b5c25b in VMThread::loop ()
5
在有的虚拟机实现中,即使是同一个锁变量,当多次打印堆栈时,每次堆栈打印的锁ID也是不同的。
6
pstack可以打印出本地程序的线程堆栈,有的操作系统下,打印本地堆栈的命令是gstack
![](https://csdnimg.cn/release/download_crawler_static/10772213/bg14.jpg)
8 1 JAVA线程堆栈分析
#6 0xf7b5bec0 in VMThread::run ()
#7 0xf7ababe8 in _start ()
#8 0x0081c3db in start_thread () from /lib/libpthread.so.0
#9 0x0077c06e in clone () from /lib/libc.so.6
Thread 7 (Thread 4067273616 (LWP 3370)):
#0 0xffffe402 in __kernel_vsyscall ()
#1 0x008201a6 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2 0x0082085e in pthread_cond_wait@GLIBC_2.0 () from /lib/libpthread.so.0
#3 0xf7ab9cee in os::Linux::safe_cond_wait ()
#4 0xf7aafcef in ObjectMonitor::wait ()
#5 0xf7b06176 in ObjectSynchronizer::wait ()
#6 0xf7a02b03 in JVM_MonitorWait ()
#7 0xf287a4db in ?? ()
#8 0x0809ba30 in ?? ()
#9 0xf26d9fcc in ?? ()
#10 0x00000000 in ?? ()
Thread 6 (Thread 4066745232 (LWP 3371)):
#0 0xffffe402 in __kernel_vsyscall ()
#1 0x008201a6 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2 0x0082085e in pthread_cond_wait@GLIBC_2.0 () from /lib/libpthread.so.0
#3 0xf7ab9cee in os::Linux::safe_cond_wait ()
#4 0xf7aafcef in ObjectMonitor::wait ()
#5 0xf7b06176 in ObjectSynchronizer::wait ()
#6 0xf7a02b03 in JVM_MonitorWait ()
#7 0xf287a4db in ?? ()
#8 0x0809c720 in ?? ()
#9 0xf2658f1c in ?? ()
#10 0x00000000 in ?? ()
Thread 5 (Thread 4063869840 (LWP 3372)):
#0 0xffffe402 in __kernel_vsyscall ()
#1 0x008221ae in sem_wait@GLIBC_2.0 () from /lib/libpthread.so.0
#2 0xf7abb046 in check_pending_signals ()
#3 0xf7ab7f4d in os::signal_wait ()
#4 0xf7ab5285 in signal_thread_entry ()
#5 0xf7b233d3 in JavaThread::run ()
#6 0xf7ababe8 in _start ()
#7 0x0081c3db in start_thread () from /lib/libpthread.so.0
#8 0x0077c06e in clone () from /lib/libc.so.6
Thread 4 (Thread 4063341456 (LWP 3373)):
#0 0xffffe402 in __kernel_vsyscall ()
#1 0x008201a6 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2 0x0082085e in pthread_cond_wait@GLIBC_2.0 () from /lib/libpthread.so.0
#3 0xf7ab9cee in os::Linux::safe_cond_wait ()
剩余320页未读,继续阅读
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://profile-avatar.csdnimg.cn/c7e55aebd3474fbca8b76e5e38b65c80_luqiang81191293.jpg!1)
架构技术专栏
- 粉丝: 231
- 资源: 1
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助
![](https://csdnimg.cn/release/wenkucmsfe/public/img/voice.245cc511.png)
最新资源
- 多模态联合稀疏表示在视频目标跟踪中的应用
- Kubernetes资源管控与Gardener开源软件实践解析
- MPI集群监控与负载平衡策略
- 自动化PHP安全漏洞检测:静态代码分析与数据流方法
- 青苔数据CEO程永:技术生态与阿里云开放创新
- 制造业转型: HyperX引领企业上云策略
- 赵维五分享:航空工业电子采购上云实战与运维策略
- 单片机控制的LED点阵显示屏设计及其实现
- 驻云科技李俊涛:AI驱动的云上服务新趋势与挑战
- 6LoWPAN物联网边界路由器:设计与实现
- 猩便利工程师仲小玉:Terraform云资源管理最佳实践与团队协作
- 类差分度改进的互信息特征选择提升文本分类性能
- VERITAS与阿里云合作的混合云转型与数据保护方案
- 云制造中的生产线仿真模型设计与虚拟化研究
- 汪洋在PostgresChina2018分享:高可用 PostgreSQL 工具与架构设计
- 2018 PostgresChina大会:阿里云时空引擎Ganos在PostgreSQL中的创新应用与多模型存储
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![](https://img-home.csdnimg.cn/images/20220527035711.png)
![](https://img-home.csdnimg.cn/images/20220527035711.png)
![](https://img-home.csdnimg.cn/images/20220527035111.png)
安全验证
文档复制为VIP权益,开通VIP直接复制
![](https://csdnimg.cn/release/wenkucmsfe/public/img/green-success.6a4acb44.png)