-Xms 是指堆的最小内存:意思是回收到最小内存的时候,就不再回收了,假如-Xms是2G,那么当程序启动的时候,会向OS申请堆内存,一点点申请,不够了再申请,直到申请到堆的最大内存,如果还需要内存的话,那么就内存溢出,如果产生垃圾进行回收的话,回收到堆的最小内存的时候,就不再继续回收了。也不是不回收了,只是回收到堆得最小内存的时候,回收的那些内存会返回给OS,如果还在继续往小于堆最小内存的方向回收的话,回收的内存就不会返回给OS了。
向开始说的那样,不停的申请内存会出现什么情况呢?
public class FullGCDemo {
// -Xmx512m -server -verbose:gc -XX:+PrintGCDetails
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 1000; i++) {
byte[] tem = new byte[1024 * 1024 * 256];
System.out.println("running......");
Thread.sleep(2000L);
}
}
}
这个程序时间有点长了,这个程序之所以没有OOM的原因是:创建256M的byte类型的数组,虽然对象在堆里,但是引用是在栈里,出了for循环引用就清空了。
然后再第二次循环的时候,继续创建256M的数组,这属于大对象,大对象是直接进入到老年代的,这时候因为老年代只有341M内存,再申请256M的内存用来存数组的话,老年代存不下了,那么就产生Full GC(虽然老年代有341内存,但是实际上可能不到整的341M.)
发生了Full GC后,之前申请的那个256M的数组就被回收了。所以不会发生OOM
当创建340M的数组的时候,不会OOM,而是Full GC。
创建341M的数组的时候就是OOM
public class FullGCDemo {
// -Xmx512m -server -verbose:gc -XX:+PrintGCDetails
public static void main(String[] args) throws InterruptedException {
ArrayList<Object> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new byte[1024*1024*64]);
System.out.println("添加成功");
Thread.sleep(1000L); //先执行Full GC 随后OOM
}
}
}
//控制台
E:\Java\jdk1.8.0_131\bin\java.exe -Xmx512m -server -verbose:gc -XX:+PrintGCDetails "-javaagent:F:\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=63154:F:\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath E:\Java\jdk1.8.0_131\jre\lib\charsets.jar;E:\Java\jdk1.8.0_131\jre\lib\deploy.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;E:\Java\jdk1.8.0_131\jre\lib\javaws.jar;E:\Java\jdk1.8.0_131\jre\lib\jce.jar;E:\Java\jdk1.8.0_131\jre\lib\jfr.jar;E:\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;E:\Java\jdk1.8.0_131\jre\lib\jsse.jar;E:\Java\jdk1.8.0_131\jre\lib\management-agent.jar;E:\Java\jdk1.8.0_131\jre\lib\plugin.jar;E:\Java\jdk1.8.0_131\jre\lib\resources.jar;E:\Java\jdk1.8.0_131\jre\lib\rt.jar;F:\workspace_idea\untitled_tiaoyou\out\production\untitled_tiaoyou FullGCDemo
添加成功
添加成功
添加成功
添加成功
添加成功
[GC (Allocation Failure) [PSYoungGen: 6510K->1208K(75776K)] 334190K->328896K(425472K), 0.0023030 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1208K->1144K(75776K)] 328896K->328832K(425472K), 0.0022520 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 1144K->0K(75776K)] [ParOldGen: 327688K->328668K(349696K)] 328832K->328668K(425472K), [Metaspace: 3993K->3993K(1056768K)], 0.0112951 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(75776K)] 328668K->328668K(425472K), 0.0009928 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(75776K)] [ParOldGen: 328668K->328615K(349696K)] 328668K->328615K(425472K), [Metaspace: 3993K->3993K(1056768K)], 0.0077370 secs] [Times: user=0.14 sys=0.02, real=0.01 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at FullGCDemo.main(FullGCDemo.java:9)
Heap
PSYoungGen total 75776K, used 1734K [0x00000000f5580000, 0x00000000fe980000, 0x0000000100000000)
eden space 65024K, 2% used [0x00000000f5580000,0x00000000f5731970,0x00000000f9500000)
from space 10752K, 0% used [0x00000000f9500000,0x00000000f9500000,0x00000000f9f80000)
to space 10752K, 0% used [0x00000000fdf00000,0x00000000fdf00000,0x00000000fe980000)
ParOldGen total 349696K, used 328615K [0x00000000e0000000, 0x00000000f5580000, 0x00000000f5580000)
object space 349696K, 93% used [0x00000000e0000000,0x00000000f40e9e68,0x00000000f5580000)
Metaspace used 4024K, capacity 4568K, committed 4864K, reserved 1056768K
class space used 450K, capacity 460K, committed 512K, reserved 1048576K
Process finished with exit code 1
如果在这个for循环里调用system.gc也是回收不了内存的,要想gc,也得达到gc的条件吧,可达性分析了解一下。这个list是可达的,还是持有引用的。
那项目中OOM了可以dump到磁盘上,然后用eclipse Memory Analyzer或者用
来分析。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!