JAVA问题定位技术(3)

JAVA 远程调试

虚拟机远程调试开关:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=%DEBUG_PORT%,suspend=n;suspend设为n时JVM会在打开调试端口后正常启动,若设为y则JVM启动后会等候调试器连接后才继续启动

JAVA 内存泄漏检测

内存泄露产生
2.1      java的垃圾回收机制
java虚拟机的垃圾回收算法要做两件事情。首先,它必须检测出垃圾对象。
其次,它必须回收垃圾对象所使用的堆空间并还给程序。
垃圾检测通常通过建立一个根对象的集合并且检查从这些根对象开始的可触及性来实现。
如果正在执行的程序可以访问到的根对象和某个对象之间存在引用路径,这个对象就是可触及的。
对于程序来说,根对象总是可以访问的。从这些跟对象开始,
任何可以被触及的对象都被认为是“活动”对象。无法被触及的对象被认为是垃圾,
因为它们不再影响程序的未来执行。

2.2      内存泄漏的产生
如果系统中存在越来越多的不再影响程序未来执行的对象,且这些对象和根对象之间存在引用路径,
内存泄漏产生了。

2.3      内存泄漏的消除
根据 内存泄漏的产生 所述。发生内存泄漏要满足如下两个条件:
1. 系统中存在越来越多的不再影响程序未来执行的对象。
2. 这些对象和根对象之间存在引用路径。
从这两个条件中能很容易找出消除内存泄漏的方法:截断系统中存在的不影响程序未来执行的对象与
根对象之间的引用路径。这样,这些对象就成了“垃圾”对象,javm就能正常回收它们。

常见的内存泄露陷阱
常见的内存泄露
(1) 全局HashMap等容器,在对象不需要后没有及时从容器中remove掉
特别是在抛出异常的时候,一定要确保remove方法执行到。

(2) Runnable对象new了就必须使用线程来Run等

Java内存泄漏的初步确定
下面是使用GC输出分析内存泄漏的原理:
 [GC 65.233: [DefNew: 12949K->1434K(13824K), 0.0122730 secs] 87703K->76189K(134892K), 0.0123500 secs]
   (87703K->76189K(134892K), 87703K表示系统使用了多少内存(我们称之为当前使用内存),
76189K表示进行这次垃圾回收之后使用的内存数量(我们称之为垃圾回收后内存),134892K上两个数据相减)   
 
   可以按照如下思路分析GC输出,能够初步比较准确地判断系统是否存在内存泄漏:
   (1) 首先要确保系统已经稳定运行(如初使化等已经完成等) (这个条件很重要)
   (2) 然后取一个时间段的GC 输出作为分析数据,只分析FULL GC的行,以垃圾回收后的值为分析对象
   (3) 然后根据GC分析内存的使用情况:
       A. 如果当前使用内存持续增长, 而垃圾回收后内存也持续增长, 有一直增长到Xmx设置的内存的趋势,
那么这个时侯基本上就可以断定有内存泄漏问题了.
       B. 如果当前使用内存增长到一个值之后,又能回落, 达到一个动态平衡, 那么就没有内存泄漏的情况.

[Full GC 912526K->614350K(912576K), 2.5546922 secs]
[Full GC 912526K->623890K(912576K), 2.5777505 secs]
[Full GC 912575K->625359K(912576K), 2.5620272 secs]
[Full GC 912575K->648552K(912576K), 2.5632979 secs]
[Full GC 912532K->688576K(912576K), 2.5211377 secs]
[Full GC 912532K->714354K(912576K), 2.6212585 secs]
[Full GC 912538K->784362K(912576K), 2.5190768 secs]
(1) 只有FULL GC的行才有分析价值
(2) 只需要检查完全垃圾后剩余的内存值是否一直再增大。

JAVA 内存泄漏精确定位
借助一些工具,如:Optimizeit JProfiler、JRockit等,
甚至可以使用Java虚拟机自带的工具HProf进行问题的定位;使用HProf的方法如下:

java -Xrunhprof 其它参数 要运行的系统main函所在的类
具体的参数列表如下:
Hprof usage: -Xrunhprof[:help]|[:<option>=<value>, ...]
Option Name and Value Description Default
--------------------- ---------------------- -------
heap=dump|sites|all heap profiling all
cpu=samples|times|old CPU usage off
monitor=y|n monitor contention n
format=a|b ascii or binary output a
file=<file> write data to file java.hprof(.txt for ascii)
net=<host>:<port> send data over a socket write to file
depth=<size> stack trace depth 4
cutoff=<value> output cutoff point 0.0001
lineno=y|n line number in traces? y
thread=y|n thread in traces? n
doe=y|n dump on exit? y
gc_okay=y|n GC okay during sampling y
Example: java -Xrunhprof:cpu=samples,file=log.txt,depth=3 FooClass
使用HProf定位内存泄漏问题时,可以通过通过增加参数“heap=sites”来输出堆栈信息到文件中,
然后通过分析堆栈信息h和线程信息来判断内存泄漏的位置;

JAVA 内存泄漏检测-OptimizeIt
使用OptimizeIt定位内存泄露确切位置的步骤:

(1) 系统稳定运行一段时间,即按照从业务逻辑来讲,
不应该再有大的内存需求波动。这个非常重要。
(2) 点击OptimizeIt上的垃圾回收按钮,然后马上再点mark按钮。
将当前实际对象的数量作为基准点。
(3) 过一段时间(如一个小时或者更多)
(4) 点击OptimizeIt上的垃圾回收按钮,检查是否有大量的对象增加,
如果有增加,主要是哪些对象
确定可疑范围,通过结合阅读代码进行分析。

Unix下调试利器-Proc工具介绍
/proc文件系统不是普通意义上的文件系统,它是一个到运行中进程地址空间的访问接口。通过/proc,可以用标准Unix系统调用(比如open()、read()、write()、ioctl()等等)访问进程地址空间。
大多数Unix(/Linux)操作系统在带一系列的工具集,借助这些工具,可以对进行进行剖析,从而协助定位相关问题。
Windows下可以使用Taskinfo工具分析类似的内容
Linux下直接到/Proc下面,大部分数据可读。 可结合lsof进行分析

Proc工具列表
pcred
pfiles
pflags
pldd
pmap
prun
psig
pstack
pstop
ptime
ptree
pwait
pwdx
plimit
……
展开阅读全文

没有更多推荐了,返回首页