新生区、永久区
新生区
类:诞生和成长的地方,甚至死亡
伊甸园,所有的对象都是在伊甸园区new出来的!
幸存区(0,1)
真理:经过研究,99%的对象都是临时对象
GC清理流程:
先GC,后Full GC,再GC,再Full GC,直到老年区对象满了,就会出现OOM
测试代码
//-Xms8m -Xmx8m -XX:+PrintGCDetails
public class Test2 {
public static void main(String[] args) {
String str = "yuan";
while (true){
str+=str+new Random().nextInt(888888)+new Random().nextInt(999999);
}
}
}
输出结果
[GC (Allocation Failure) [PSYoungGen: 1536K->504K(2048K)] 1536K->632K(7680K), 0.0009460 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1977K->500K(2048K)] 2105K->933K(7680K), 0.0013858 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1774K->456K(2048K)] 2207K->1387K(7680K), 0.0006280 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1978K->472K(2048K)] 2910K->2401K(7680K), 0.0010538 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 1493K->0K(2048K)] [ParOldGen: 4923K->3126K(5632K)] 6417K->3126K(7680K), [Metaspace: 3307K->3307K(1056768K)], 0.0045988 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1054K->32K(2048K)] 5178K->5154K(7680K), 0.0003836 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 32K->0K(2048K)] [ParOldGen: 5122K->2626K(5632K)] 5154K->2626K(7680K), [Metaspace: 3308K->3308K(1056768K)], 0.0037782 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 4622K->4622K(7680K), 0.0001909 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 4622K->3624K(5632K)] 4622K->3624K(7680K), [Metaspace: 3308K->3308K(1056768K)], 0.0020645 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 3624K->3624K(7680K), 0.0003315 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 3624K->3604K(5632K)] 3624K->3604K(7680K), [Metaspace: 3308K->3308K(1056768K)], 0.0045071 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 2048K, used 43K [0x00000000ffd80000, 0x0000000100000000, 0x0000000100000000)
eden space 1536K, 2% used [0x00000000ffd80000,0x00000000ffd8adc8,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 5632K, used 3604K [0x00000000ff800000, 0x00000000ffd80000, 0x00000000ffd80000)
object space 5632K, 64% used [0x00000000ff800000,0x00000000ffb852a8,0x00000000ffd80000)
Metaspace used 3340K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 363K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at com.JVM.demo01.Test2.main(Test2.java:10)
Process finished with exit code 1
永久区
这个区域常驻内存,用来存放JDK自身携带的Class对象,Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收!关闭虚拟机就会释放这个区域的内存
永久区会蹦的情况:
一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类。不断的被加载,直到内存满,就会出现OOM;
jdk1.6之前:永久代,常量池在方法区
jdk1.7:永久代,但是慢慢的退化了,去永久代,常量池在堆中
jdk1.8之后:无永久代,叫做元空间,常量池在元空间,下图中方法区里的一小块区域就是常量池
元空间逻辑上存在,物理上不存在
证明:
public class Test3 {
public static void main(String[] args) {
//返回虚拟机试图使用的最大内存
long max = Runtime.getRuntime().maxMemory();//字节 1024*1024
//返回jvm的初始化总内存
long total = Runtime.getRuntime().totalMemory();
System.out.println("max="+max+"字节\t"+(max/(double)1024/1024)+"MB");
System.out.println("total="+total+"字节\t"+(total/(double)1024/1024)+"MB");
//默认情况下:分配的总内存(JVM试图使用的最大内存)是电脑的1/4,而初始化的内存:1/64
//OOM堆内存满了,采取什么措施?
//1.尝试扩大堆内存看结果
//2.分析内存,看一下哪个地方出现了问题(专业工具)
//-Xms1024m -Xmx1024m -XX:+PrintGCDetails
//305664K+ 699392K=1,005,056K=981.5M
}
}
输出结果
max=1029177344字节 981.5MB
total=1029177344字节 981.5MB
Heap
PSYoungGen total 305664K, used 20971K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
eden space 262144K, 8% used [0x00000000eab00000,0x00000000ebf7afb8,0x00000000fab00000)
from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
to space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
ParOldGen total 699392K, used 0K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
object space 699392K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000eab00000)
Metaspace used 3322K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 360K, capacity 388K, committed 512K, reserved 1048576K
结果分析
将新生区的总内存与老年区的总内存相加305664K+ 699392K=1,005,056K=981.5M
结果为JVM初始化的总内存981.5M,说明元空间在物理上不存在,但是输出结果中有元空间:
Metaspace used 3322K, capacity 4496K, committed 4864K, reserved 1056768K
所以说元空间逻辑上存在
如果OOM,堆内存满了,采取什么措施?
1.尝试扩大堆内存看结果
2.分析内存,看一下哪个地方出现了问题(专业工具)
扩大堆内存的方法,在VM options中配置参数:-Xms1024m -Xmx1024m -XX:+PrintGCDetails
其中-XX:+PrintGCDetails可要可不要,这个参数只是为了打印GC工作信息
`
1.尝试扩大堆内存看结果
2.分析内存,看一下哪个地方出现了问题(专业工具)
扩大堆内存的方法,在VM options中配置参数:-Xms1024m -Xmx1024m -XX:+PrintGCDetails
其中-XX:+PrintGCDetails可要可不要,这个参数只是为了打印GC工作信息