堆
Heap,一个JVM只有一个堆内存,堆的大小是可以调节的。
类加载器读取了类文件后一般会将 类,方法,常量,变量放在堆里面
堆内存分为3个部分:
- 新生代(伊甸园区)
- 老年代
- 永久代
GC垃圾回收机制主要在新生代和老年代
在JDK8以后,永久存储区改了一个名字:元空间
永久区
这个区域 是常驻内存中的,用来存放 JDK自带的Class对象,
- jdk1.6之前:永久代,常量池在方法区
- jdk1.7 :永久代,慢慢退化,常量池在堆里面
- jdk1.8之后:无永久代,常量池在元空间,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此默认情况下元空间的大小仅受本地内存限制。
堆内存调优
在一个项目中,突然出现了OOM故障,那么该如何分析?
- 能看见第几行出错:内存快照分析工具,MAT(eclipse)、Jprofiler
- Debug,一行行分析代码!
MAT、Jprofiler作用:
- 分析Dump内存文件
例子:
运行下面这段代码
public class OOM {
byte[] array = new byte[1 * 1024 * 1024];
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
int count = 0;
try {
while(true){
list.add(new OOM());
count += 1;
}
} catch (Exception e) {
System.out.println("count:"+count);
e.printStackTrace();
}
}
}
报错:
解决步骤:
1.调节虚拟机参数:VM Options
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
//-Xms 设置初始化内存分配大小 默认1/64
//-Xmx 设置初始化内存分配大小 默认1/4
//-XX:+PrintGcDetails 打印GC垃圾回收的信息
//-XX:+HeapDumpOnOutOfMemoryError 打印OOM信息
再次运行
双击点开
从图中可以看出ArrayList数据占据了90%的内存,然后看线程里面可以找到具体程序在哪行出错。