例子中,代码栈中存在Vector对象的引用vector和Object对象的引用object。
在For循环中,我们不断的生成新的对象,然后将其添加到vector对象中,之后将object引用置空。
问题是当o引用被置空后,如果发生GC,我们创建的Object对象是否能够被GC回收呢?答案是否定的。
因为,GC在跟踪代码栈中的引用时,会发现vector引用,而继续往下跟踪,
就会发现vector引用指向的内存空间中又存在指向Object对象的引用。
【也就是说尽管object引用已经被置空,但是Object对象仍然存在其他的引用,是可以被访问到的,所以GC无法将其释放掉。】
如果在此循环之后,Object对象对程序已经没有任何作用,那么我们就认为此Java程序发生了内存泄漏。
===============================分割线===================================================
上面讲的太肤浅:
下面来点深入的:
在说明内存泄露之前先补充点知识(其实在jvm调优文章中已经有一张很清晰的图)
JVM内存模型和垃圾收集算法:
1.JVM内存模型:
2.垃圾回收算法
垃圾回收算法可以分为三类,都基于标记-清除(复制)算法:
- Serial算法(单线程)
- 并行算法:多线程,回收时暂停应用执行
- 并发算法:多线程,回收时不停止应用,【适合交互高的程序】
JVM会根据机器的硬件配置对每个内存代选择适合的回收算法
内存泄露的和解决办法:
1.系统奔溃前的一些想象:
a.每次垃圾回收时间越来越越长,由之前的10ms延迟到50ms,FullGc的时间也延长到4、5s
b.FUllGc次数越来越多,最频繁时隔不到1分钟
c.old区内存越来越大,并且每次FullGc后old没有内存释放
之后 系统无法响应新请求,逐渐到达OutOfMemoryError临界值
解决办法:
步骤1.生成堆的dump文件【dump进程的内存镜像,扩展名是 .dmp】
【通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件】
步骤2:打开dump文件
如何分析:3G的文件根本打不开
使用Eclipse的静态分析工具:Mat【还有的用windDBG】
步骤3:分析内存泄露
通过Mat可以看到
a.哪些被怀疑为内存泄露,
b.哪些对象占用空间最大
c.对象的调用关系
d.通过分析线程状态,可以观察到线程被阻塞在哪个对象上,从而判断系统瓶颈。
针对本案:是ThreadLocal中有很多的JbpmContext实例,经调查时JBPM的Context没有关闭导致