1 内存溢出
内存溢出(OutOfMemory,OOM)是指程序在申请内存时,没有足够的内存空间供其使用,出现OOM。在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OOM异常的可能。
public class OOMDemo {
static class OOMObejct{
}
public static void main(String[] args) {
List<OOMObejct> list = new ArrayList<OOMDemo.OOMObejct>();
while(true){
list.add(new OOMObejct());
}
}
}
备注:
将VM arguments设置为:-verbose:gc -Xms20M-Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
运行结果:
2 内存泄露
内存泄露(Memory Leak)是指对象已经没有被程序使用,但是垃圾回收期没法移除他们,因为还被其他对象引用着。
2.1内存泄露原因分析
对象obj5、obj6和obj7虽然互相连接,但是它们到GC Roots是不可达,因此会被判定为可回收对象。
obj3是有用对象,因为其引用obj4,obj2则是无用对象。但是由于obj2和obj3都可到达GC Roots,因此都不会被GC回收,正是obj2这种无用且不会被GC回收的对象占用着内存不释放,导致内存泄露发生。
2.2常见内存泄露场景
1)集合对象如HashMap,ArrayList等,特别是当它们被声明为static时,它们的生命周期就会和应用程序一样长,容易引发内存泄漏。
2)在JDK6中,String.substring()方法也容易导致内存泄露。虽然在会新生成一个字符串对象,但是仍然保留着对原对象的字符数组的引用,导致原字符串无法被GC。在JDK7中这个问题已经解决。
3)当一个 监听器 在使用的时候被 注册 ,但不再使用之后却未被 注销 。在OSGI框架中,启动时注册一个服务监听器,关闭时要记得将服务监听器移除。
3 参考文献
[1].周志明, 深入理解Java虚拟机:JVM高级特性与最佳实践.第 2 版. 2015: 机械工业出版社.