1、堆内存分配参数
-Xmx –Xms
指定最大堆和初始堆内存大小(两个参数设置一样可减少垃圾回收)
-Xmx20m –Xms10m:指定最大堆内存20M,初始化堆内存10M
package com.thread.study;
public class Heap {
public static void main(String[] args) {
//最大堆内存
System.out.println("(最大堆内存:)Xmx="+Runtime.getRuntime().maxMemory()/1024.0/1024+"M");
//空闲堆内存
System.out.println("(初始化堆内存:)Xms="+Runtime.getRuntime().freeMemory()/1024.0/1024+"M");
//当前最大可用堆内存
System.out.println("(当前可用:)"+Runtime.getRuntime().totalMemory()/1024.0/1024+"M");
}
}
(最大堆内存:)Xmx=18.0M
(空闲堆内存:)Xms=8.701156616210938M
(当前可用:)9.5M
创建5M的对象:
package com.thread.study;
public class Heap {
private static final Integer MAX_BYTE_LENGTH = 1024 * 1024;
public static void main(String[] args) {
byte[] bytes = new byte[5 * MAX_BYTE_LENGTH];
//最大堆内存
System.out.println("(最大堆内存:)Xmx="+Runtime.getRuntime().maxMemory()/1024.0/1024+"M");
//空闲堆内存
System.out.println("(初始化堆内存:)Xms="+Runtime.getRuntime().freeMemory()/1024.0/1024+"M");
//当前最大可用堆内存
System.out.println("(当前可用:)"+Runtime.getRuntime().totalMemory()/1024.0/1024+"M");
}
}
(最大堆内存:)Xmx=18.0M(空闲堆内存:)Xms=3.701141357421875M(当前可用内存减少约5M)
(当前可用:)9.5M
在创建6M的对象,则当前可用内存不满足会进行堆内存扩容。
package com.thread.study;
public class Heap {
private static final Integer MAX_BYTE_LENGTH = 1024 * 1024;
public static void main(String[] args) {
byte[] bytes5m = new byte[5 * MAX_BYTE_LENGTH];
byte[] bytes6m = new byte[6 * MAX_BYTE_LENGTH];
//最大堆内存
System.out.println("(最大堆内存:)Xmx="+Runtime.getRuntime().maxMemory()/1024.0/1024+"M");
//空闲堆内存
System.out.println("(初始化堆内存:)Xms="+Runtime.getRuntime().freeMemory()/1024.0/1024+"M");
//当前最大可用堆内存
System.out.println("(当前可用:)"+Runtime.getRuntime().totalMemory()/1024.0/1024+"M");
}
}
(最大堆内存:)Xmx=18.0M(空闲堆内存:)Xms=4.2010650634765625M
(当前可用:)16.0M
-Xmn(设置新生代大小,设置为绝对值)
设置新生代大小
-XX:NewRatio
新生代(eden+2*s)和老年代(不包含永久区)的比值
4 表示 新生代:老年代=1:4,即年轻代占堆的1/5
-XX:SurvivorRatio
设置两个Survivor区和eden的比
8表示 两个Survivor :eden=2:8,即一个Survivor占年轻代的1/10
2、设置示例
-Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails
package com.thread.study;
public class HeapExample {
public static void main(String[] args) {
byte[] b=null;
for(int i=0;i<10;i++)
b=new byte[1*1024*1024];
}
}
[GC (Allocation Failure) [PSYoungGen: 509K->504K(1024K)] 509K->512K(19968K), 0.0018745 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 1024K, used 736K [0x00000000ffe80000, 0x0000000100000000, 0x0000000100000000)
eden space 512K, 45% used [0x00000000ffe80000,0x00000000ffeba370,0x00000000fff00000)
from space 512K, 98% used [0x00000000fff00000,0x00000000fff7e010,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 18944K, used 10248K [0x00000000fec00000, 0x00000000ffe80000, 0x00000000ffe80000)
object space 18944K, 54% used [0x00000000fec00000,0x00000000ff6020a0,0x00000000ffe80000)
Metaspace used 2640K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 285K, capacity 386K, committed 512K, reserved 1048576K
触发了GC新生代老年代均有内存分配
3、dump数据信息
发生OOM时需记录下当时内存分配情况
package com.thread.study;
import java.util.Vector;
public class HeapDump {
public static void main(String[] args) {
Vector v=new Vector();
for(int i=0;i<25;i++){
v.add(new byte[1*1024*1024]);
}
}
}
java.lang.OutOfMemoryError: Java heap spaceDumping heap to d:/a.dump ...
Heap dump file created [15905605 bytes in 0.027 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.thread.study.HeapDump.main(HeapDump.java:10)
dump文件分析:使用jdk自带jvisualvm.exem
byte数组内存占比95%以上导致内存溢出
OOM时触发脚本:
-XX:OnOutOfMemoryError
在OOM时,执行一个脚本
"-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p“
当程序OOM时,在D:/a.txt中将会生成线程的dump
可以在OOM时,发送邮件,甚至是重启程序
4、堆参数设置总结
根据实际事情调整新生代和幸存代的大小
官方推荐新生代占堆的3/8
幸存代占新生代的1/10
在OOM时,记得Dump出堆,确保可以排查现场问题