一.三种JVM
二.堆(重点)
1.新生区
目的:控制对象的诞生,成长和死亡
分为:
-
伊甸园区:所有对象都在伊甸园区new出来
-
幸存0区和幸存1区:轻GC之后存下来的
2.老年区(养老区)
永久存在的对象放在老年区
步骤:
-
伊甸园区满了之后进行轻GC幸存下来的放到幸存0区或幸存1区
-
当伊甸园区、幸存0区和幸存1区都满了进行重GC,幸存下来的放到养老区???
-
当伊甸园区、幸存0区、幸存1区和养老区都满了,会出现OOM
3.永久区
注意:
-
元空间是逻辑上存在而物理上不存在的,又称为非堆,但是实际上是和堆放在同一个物理空间中
-
方法区中的一小块为常量区
案例程序:
-
默认情况下,JVM使用的最大内存为电脑总内存的四分之一,JVM使用的总内存为电脑总内存的十六分之一
-
配置VM的参数: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
@Test
public void test1() {
//返回JVM试图使用的最大内存:默认情况下为电脑总内存的1/4
long max = Runtime.getRuntime().maxMemory();
//返回JVM的初始化总内存:默认情况下为电脑总内存的1/16
long total = Runtime.getRuntime().totalMemory();
System.out.println("max:" + max / (double) (1024 * 1024) + "MB");
System.out.println("total:" + total / (double) (1024 * 1024) + "MB");
//配置VM的参数: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
}
案例二:OOM
-
配置VM的参数: -Xms8m -Xmx8m -XX:+PrintGCDetails
public class JVMTest {
public static void main(String[] args) {
//配置VM的参数: -Xms8m -Xmx8m -XX:+PrintGCDetails
String s = "aaaaaaaaaa";
while(true){
s += s + new Random().nextInt(999999999) + new Random().nextInt(888888888);
}
}
}
三.堆内存调优
-
使用工具JProfiler
-
内存快照分析工具:MAT(eclipse中使用),JProfiler
-
作用:用于分析Dump文件,查找错误原因
使用步骤:
-
IDEA中在插件库中下载插件JProfiler
-
在网上下载JProfiler桌面工具破解并安装
-
在IDEA中配置JProfiler
编写会OOM的代码,并配置VM options
编写程序
- -Xms:设置初始化内存分配大小
- -Xmx:设置最大分配内存
- -XX:+PrintGCDetails:打印GC垃圾回收信息
- -XX:+HeapDumpOnOutOfMemoryError:栈溢出信息生成Dump文件
//-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
public class Demo01 {
byte[] array = new byte[1*1024*1024]; //1M
public static void main(String[] args) {
ArrayList<Demo01> list = new ArrayList<>();
int count = 0;
while(true){
list.add(new Demo01());
count++;
}
}
}
生成的dump文件在项目的目录下的xxx.hprof,双击打开
使用工具排错
四.GC
-
Eden与Survivor的内存大小比例为8:1:1
1.引用计数法:
2.复制算法
-
幸存区from和幸存区to中谁是空的谁就是to,我们会将to中数据复制到from中保持to中数据为空
-
from和to区实际上为逻辑上的概念,保证to区一直空
-
默认对象经过15次GC后还没有被销毁就会进入养老区
流程:
-
将Eden区进行GC存活对象放入空的To区,将From区存活的放到空的To区
-
此时From区为空变成了To区,To区有数据变为From区
-
经过15次GC后From区还存活的对象会被移动到养老区
好处:没有内存碎片
坏处:浪费了内存空间(To区为空)
复制算法最佳使用场景:对象存活度较低(如果存活度较高,则From区空间全部被占满导致会将全部内容复制到To区)
3.标记清除算法
-
需要两次扫描,第一次扫描标记存活对象,第二次扫描清除没有被标记的对象
优点:不需要额外的空间
缺点:两次扫描严重浪费时间,并且还会产生内存碎片
4.标记压缩算法
-
在标记清除算法上进行优化,再扫描一次将存活对象移动到一起
总结:
五.JMM
-
Java Memory Model:java内存模型