没有合适的资源?快使用搜索试试~ 我知道了~
首页Java线程堆栈分析与问题定位指南
《Java问题定位技术》是一本深入探讨Java编程中问题定位技巧的书籍,特别关注内存泄漏定位和线程堆栈分析这两个核心领域。书中强调了线程堆栈分析的重要性,尤其对于那些从C++/C转到Java的开发者,它是理解Java虚拟机内部工作方式的关键技术,但对于原生Java开发者来说可能较为陌生。 该书详细介绍了如何获取和解读Java线程堆栈,包括线程的状态、调用堆栈以及锁的持有情况。通过线程堆栈分析,可以解决各种问题,如线程死锁、CPU过高、代码执行效率低下、资源不足导致的性能下降、线程阻塞或挂死、多线程竞争导致的锁链问题,以及性能瓶颈的识别。作者提供了多种分析手段,如模拟性能瓶颈、使用JVM参数调整、专业性能分析工具如runhprof、JProfiler等,以及操作系统CPU统计工具。 内存泄漏部分则涵盖了Java内存管理的基本概念,如对象大小、引用关系、垃圾回收机制以及如何正确释放不再使用的内存。书中指出,仅仅将对象设为null并不一定能避免内存泄漏,因为可能还存在弱引用或软引用的情况。此外,还讨论了Java内存泄漏的常见症状,如出现OutOfMemory异常,以及如何定位和诊断内存泄漏问题。 《Java问题定位技术》提供了一套实用的工具和技术,帮助读者提升Java编程的效率和系统的稳定性,对于任何希望深入理解和优化Java应用的开发者来说,这是一本不可或缺的参考书籍。
资源详情
资源推荐
![](https://csdnimg.cn/release/download_crawler_static/11177763/bg10.jpg)
4 1 JAVA线程堆栈分析
2>&1表示将错误输出重定向到标准输出流中,即将标准输出和错误输出都重定向到一个文件
中。
提示:
在JDK1.5以上的版本中,可以在Java程序中通过Thread.getStackTrace()控制堆栈自动打
印.通过这种方式,线程堆栈的打印时机可编程。通过手工编程,可以在满足某些条件时,
将线程堆栈自动打印。
![](https://csdnimg.cn/release/download_crawler_static/11177763/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/11177763/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/11177763/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/11177763/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/7c873bfdf4a74983906cd4363a2d3225_taurus_7c.jpg!1)
七哥带你学编程
- 粉丝: 119
- 资源: 2
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助
![](https://csdnimg.cn/release/wenkucmsfe/public/img/voice.245cc511.png)
最新资源
- 中国微型数字传声器:技术革新与市场前景
- 智能安防:基于Hi3515的嵌入式云台控制系统设计
- 手机电量低时辐射真增千倍?解析手机使用谣言
- 56F803型DSP驱动的高精度大功率超声波电源控制策略研究
- ARM与GPRS结合的远程监测系统设计
- GPS与RFID技术结合的智能巡检系统设计
- CPLD驱动的低功耗爆炸场温度测试系统设计
- 基于FPGA的智能驱动控制系统:可扩展设计与工业网络协议
- 基于ATmega128和CH374的嵌入式USB接口设计
- 基于AT89C52的温度补偿超声波测距仪:高精度设计与应用
- MSP430F448单片机在交流数字电压表中的应用
- 提升变频器应用效率的12项实用技巧
- STM32F103在数字电镀电源并联均流系统中的应用
- PSpice仿真下的升压开关电源设计:拓扑分析与CCM稳定性提升
- 轻巧高效:MSP430主导的低成本无线传感器网络节点设计
- FPGA在EDA/PLD中实现LVDS接口的应用解析
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![](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)