java代码检查内存泄漏 java内存泄露的问题调查定位( 二 )


三,常见内存溢出错误解决办法
1,OutOfMemoryError异常
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能,
Java Heap 溢出
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常 。
出现这种异常,一般手段是先通过内存映像分析工具(如Eclipse Memory
Analyzer)对dump出来的堆转存快照进行分析,重点是确认内存中的对象是否是必要的,先分清是因为内存泄漏(Memory
Leak)还是内存溢出(Memory Overflow) 。
如果是内存泄漏 , 可进一步通过工具查看泄漏对象到GC Roots的引用链 。于是就能找到泄漏对象时通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收 。
如果不存在泄漏 , 那就应该检查虚拟机的参数(-Xmx与-Xms)的设置是否适当 。
2,虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度 , 将抛出StackOverflowError异常 。
如果虚拟机在扩展栈时无法申请到足够的内存空间 , 则抛出OutOfMemoryError异常
这里需要注意当栈的大小越大可分配的线程数就越少 。
3,运行时常量池溢出
异常信息:java.lang.OutOfMemoryError:PermGen space
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法 。该方法的作用是:如果池中已经包含一个等于
此String的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String
对象的引用 。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量
池的容量 。
4,方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等 。
异常信息:java.lang.OutOfMemoryError:PermGen space
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的 。在经常动态生成大量Class的应用中,要特别注意这点 。
如何用Java编写一段代码引发内存泄露1、首先得搞清楚什么叫内存泄露,简单来说就是一个东西放在内存里的时间太长了,当java代码检查内存泄漏你的程序都跑完了,它还存在那里 。这时它是白白的占用了java代码检查内存泄漏你的内存,累积起来占用的内存越来越多……最后就会导致JVM报错:out of memory 。
2、一般情况下,别人如果能指出你的系统(程序)内存溢出 , 这个人应该还是挺厉害的 。通常对于新人来说,喜欢把变量直接定义在class下(此时称之为实例变量,或者成员变量),那么在方法里调用后,这个实例变量是不会被释放的,大量的这样使用就可能会引发内存泄露 。
3、把变量定义在方法里,当这个方法执行完毕后内存就得到释放了,这是个好习惯 。
4、如果想要看到内存溢出 , 可以按这样的思路去尝试一下:定义一个静态的实例变量(list或其它集合),然后在一个方法里循环往这个静态变量塞东西,直到这个实例变量撑爆你的jvm内存 。很快你就能看到out of memory……
import java.util.ArrayList;
import java.util.List;
public class MemoryTest {
private static List list = new ArrayList();
private static int count = 0;

推荐阅读