堆:
Heap,一个jvm只有一个堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件后,将什么东西放到了堆中呢?
类、方法、常量、变量、保存我们所有引用类型的真实对象;
堆内存还要细分为三个区域:
- 新生区(伊甸园区):伊甸园区、幸存0区、幸存1区
- 养老区
- 永久区
堆的内存模型:
垃圾回收分为两种:轻量级垃圾回收(轻GC)、重量级垃圾回收(重GC);
垃圾回收主要在新生区(细分就是新生区的伊甸园区)和养老区
假设内存满了,就会报一个OOM错,其实就是堆内存不够了。
在jdk8以后,永久存储区改了个名字:元空间
新生区:一个类诞生、成长甚至死亡的区域。
- 伊甸园区:所有的对象都是在伊甸园区new出来的
真理:经过研究,99%的对象都是临时对象。
老年区:
永久区:这个区域常驻内存,用来存放JDK自身携带的Class对象、Interface元数据、存储的是Java运行时的一些环境或类信息。这个区域不存在垃圾回收。关闭虚拟机就会释放这个区域的内存。
当一个启动类加载了大量的第三方jar包、Tomcat部署了太多的应用、大量动态生成反射类等情况就会出现OOM。
jdk1.6之前:永久代,常量池是在方法区;
jdk1.7:永久代,但是慢慢退化了,去永久代,常量池在堆中;
jdk1.8之后:无永久代,常量池在元空间;
现在的堆模型,jdk1.8之后(更细分):
幸存0区和幸存1区是动态的,会换位置。
元空间:逻辑上存在,物理上不存在!