在JVM中只有一个堆内存,堆的内存大小可以调节。
类加载器读取类文件后,一般会把类、方法、常亮、变量、保存引用的实例对象放到堆中。
堆内存分为三个区域:
- 新生区(伊甸园区、幸存0区、幸存1区)
- 养老区
- 永久区(1.8后为元空间)
在新生区中,对象经过轻GC在伊甸园区、幸存者0、1区过渡,后经过重GC(Full GC)过渡到养老区。GC垃圾回收,主要是在伊甸园区和养老区。新生区和养老区都满了会报OOM错误。
新生区
- 类:诞生和成长、死亡;
- 伊甸园区:所有的类都是在伊甸园区new出来的;
- 幸存者0、1区
永久区
这个区域是常驻内存的,用来存放JDK自身携带的Class对象。Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收。关闭VM虚拟就会释放这个区域的内存。
元空间逻辑上存在,物理上不存在,也称作非堆。理论上,JVM最大内存(-Xmx)为计算机内存的1/4,初始化内存(-Xms)为计算机内存的1/64。
遇到OOM可以:
- 调整JVM内存:-Xms104m -Xmx1024m -XX:+PrintGCDetails
- 分析内存,看一下那个地方出现问题(MAT、JProfiler)
MAT、JProfiler作用:
- 分析Dump内存文件,快速定位内存泄漏;-XX:HeapDumpOnOutOfMemoryError
- 获得堆中的数据;
- 获得大的对象;
- ....