堆的内存结构图:
堆的逻辑结构图
代码调试堆:
package com.edu.jvm; /** * @作者 five-five * @创建时间 2020/10/8 */ public class Test05 { public static void main(String[] args) { //返回虚拟机试图使用的最大内存 long maxMemory = Runtime.getRuntime().maxMemory();//以字节为单位b //返回JVM的初始化总内存 long totalMemory = Runtime.getRuntime().totalMemory(); System.out.println("虚拟机试图使用的最大内存 "+maxMemory+"b "+maxMemory/(1024*1024)+"MB"); System.out.println("JVM总内存 "+totalMemory+"b "+totalMemory/((double)1024*1024)+"MB"); System.out.println(Math.round(maxMemory/totalMemory)); } }
OOM解决方案:1.尝试扩大堆内存看结果,2.分析内存,看一下那个地方出现了问题(专业工具)
运行时指令:-Xms1024m -Xms1024m -XX:+PrintGCDetails
打印结果如下:
计算可以得出:305664+699392=1,005,056K=~981(此时说明元空间并没有占用堆的物理内存)
GC常用算法:
- 引用计数法
- 复制算法
- 标记清除算法
总结:
JVM在进行GC时,并不是对着三个区域统一回收。大部分时候,回收都是新生代
- 新生代
- 幸存区
- 老年区
GC两种类:
- 轻GC(普通的GC)
- 重GC(全局GC)
这几个题心里必须有数:
- JVM的内存模型和分区~详细到每个区放什么?
- 堆里面的分区有哪些?说他们的特点?
- GC的算法有哪些?标记清除法、标记压缩、复制算法、引用计数器,怎么用的?
- 轻GC和重GC分别在什么时候发生?
算法总结:
- 内存效率:复制算法>标记清除算法>标记压缩算法
- 内存整齐度:复制算法=标记压缩算法>标记压缩算法
- 内存利用率:标记压缩算法=标记清除算法>复制算法
(优解)分代收集算法:
- 年轻代:
存活率低=====使用复制算法
- 老年代:
区域大,存活率高========使用标记清除(内存碎片不多)+标记压缩算法