Heap ,一个JVM只有一个堆内存,堆内存大小是可以调节的。
类加载器读取了这些文件后,一般会把什大学放到堆中?
类,方法,常量,变量,保存我是所引用类型的真实对象
堆内存中分为三个区域:
- 新生区(伊甸园 Eden space)
- 养老区
- 永久区
GC垃圾回收,主要在伊甸园区和养老区
假设内存满了,OOM,堆内存不够
JKD8以后, 永久存储区改了名字(元空间);
新生区:
类:诞生和成长的地方,甚至死亡;
-
伊甸园:所有的对象都是在伊甸园区 new出来
-
幸存区(0,1)
-
经过研究,99%的对象都是临时的
老年区:
永久区
这个区域常驻内存的。用来存放JDK自身携带的Class对象。Interface元数据, 存储的是Java运行时的一些环境或类信息~,这个区域不存在垃圾回收!关闭VM虚拟就会释放这个区域的内存
一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类。不断的被加载。直到内存满,就会出现00M;
●jdk1.6之前:永久代,常量池是在方法区;
●jdk1.7 :永久代,但是慢慢的退化了,去永久代, 常量池在堆中
●jdk1.8之后:无永久代,常量池在元空间
元空间:逻辑上存在,物理上不存在
下面跑一个程序看看虚拟机的内存大小:
public class Test {
public static void main(String[] args) {
//返回虚拟机试图使用的最大内存
long max = Runtime.getRuntime().maxMemory();
//返回jvm的初始化总内存
long total = Runtime.getRuntime().totalMemory();
System.out.println("max=" + max +"字节" + (max/(double)(1024*1024))+"MB");
System.out.println("total=" + max +"字节" + (total/(double)(1024*1024))+"MB");
//默认情况下:分配内的总内存大约是电脑内存的1/4,而初始化的内存为1/64
}
}
默认情况下:分配内的总内存大约是电脑内存的1/4,而初始化的内存为1/64
运行结果:(我的电脑内存16G)
可见 305664k + 699392 = 1029177344
所以元空间的物理内存并不在堆中
在Configuration中手动调节内存大小:
-Xms1024m -Xmx1024m -XX:+PrintGCDetails
OOM:
public class Hello {
public static void main(String[] args) {
// -Xms8m -Xmx8m -XX:+PrintGCDetails
String str = "longzx6666666666666";
while (true){
str += str + new Random().nextInt(999999999)+new Random().nextInt(999999999);
}
}
}
将内存调为8M,打印结果
-Xms8m -Xmx8m -XX:+PrintGCDetails
在一个项目中,突然出现了0OM故障,那么该如何排除~研究为什么出错
●能够看到代码第几行出错:内存快照分析工具,MAT, Jprofiler
●Dubug,一行行分析代码!
MAT, Jprofiler作用
●分析Dump内存文件,快速定位内存泄露;
●获得堆中的数据
●获得大的对象~
内存分析工具:JProfiler下载安装,已经IDEA安装插件
1.下载JProfiler(IDEA)插件
在IDEA上直接下载Settings–plugins,搜索JProfiler 点击 install 按钮安装,然后从启IDEA工具
方式2:
官网下载插件,手动安装
官方插件下载地址
在首页向下翻,中部位置能看到JProfiler最新版本,包括历史版本下载链接。点击DOWNLOAD进行下载。
然后在IDEA中引入插件
找到你压缩包的位置即可,然后重启
安装成功后会有如下标志
2.安装JProfiler监控软件
官网地址
3.配置IDEA运行环境
Settings–Tools–JProflier–JProflier executable选择JProfile安装可执行文件。(如果系统只装了一个版本,启动IDEA时会默认选择)保存
测试:
import java.util.ArrayList;
public class DumpDemo {
byte[] array = new byte[1*1024*1024]; //1m
public static void main(String[] args) {
ArrayList<DumpDemo> list = new ArrayList<>();
int count = 0;
try{
while (true){
list.add(new DumpDemo());
count = count + 1;
}
}catch (Exception e){
System.out.println(" count:"+count);
}
}
}
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
再次运行
打开文件
点击打开文件,使用JProfiler分析
分析线程:
也可以在程序中捕获Error,