笔记—OOM

(除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能)

1.可用的内存太少

2.应用太多,并且没释放,浪费内存

Java堆溢出:

内存泄漏:申请使用完的内存没释放,导致JVM不能再次使用该内存

解决:使用工具查看泄漏对象到GC Roots的引用链,找到泄露对象是通过怎样的引用路径,与哪些GC Roots相关联,才导致垃圾收集器无法回收它们并进行解决。

内存溢出:申请的内存超过了JVM能提供的内存大小

解决:在JVM设置参数(-Xmx、-Xms)。通过设置-XX:+HeapDumpOnOutOfMemoryError的JVM参数,可以在发生OutOfMemoryError后获取到一份二进制Heap Dump文件,生成的文件会直接写入到工作目录。

方法区和运行时常量池溢出:

(JDK 8 方法区从内存中移出,很难在发生溢出)

注意:intern()方法,这个方法是当前的字符对象(通过new出来的对象)从常量池看有没有此String对象的字符串,有就返回引用,没有就将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。

作用: 适当的使用可以减少内存的消耗

String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
 
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
结果:
JDK1.6false false
JDK1.7false true
String s = new String("1");
String s2 = "1";
s.intern();
System.out.println(s == s2); 

String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4);
JDK1.6false false
JDK1.7false false

img

img

在JDK1.7中,常量池中不需要再存储一份对象了,可以直接存储堆中的引用。这份引用直接指向 s3 引用的对象,也就是说s3.intern() ==s3会返回true。

img

本机直接内存溢出:

​ 由直接内存导致的内存溢出,一个明显的特征是在Heap Dump文件中不会看见有什么明显的异常情况,如果发现Dump文件很小,而又直接或者间接使用了DirectMemory(典型的间接使用就是NIO),那就可以考虑重点检查一下直接内存这一方面。

(NIO类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,他可以使用Native函数库直接分配堆外内存,同一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一场场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。)

(Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。Heap Dump是有着多种类型的。不过总体上heap dump在触发快照的时候都保存了java对象和类的信息。通常在写heap dump文件前会触发一次FullGC,所以heap dump文件中保存的是FullGC后留下的对象信息。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值