堆的内存结构图:
![](https://i-blog.csdnimg.cn/blog_migrate/049ba1685dc268955ecd969b65c1179f.png)
堆的逻辑结构图
![](https://i-blog.csdnimg.cn/blog_migrate/33cf3624bfa10e7ea550c2bfb3d73d94.png)
代码调试堆:
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("虚拟机试图使用的最大内存\t"+maxMemory+"b\t"+maxMemory/(1024*1024)+"MB");
System.out.println("JVM总内存\t"+totalMemory+"b\t"+totalMemory/((double)1024*1024)+"MB");
System.out.println(Math.round(maxMemory/totalMemory));
}
}
OOM解决方案:1.尝试扩大堆内存看结果,2.分析内存,看一下那个地方出现了问题(专业工具)
运行时指令:-Xms1024m -Xms1024m -XX:+PrintGCDetails
打印结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4305d50a992df32333d735412cb650b3.png)
计算可以得出:305664+699392=1,005,056K=~981(此时说明元空间并没有占用堆的物理内存)
GC常用算法:
- 引用计数法
![](https://i-blog.csdnimg.cn/blog_migrate/7c3c52d1e4279108846e17753880874a.png)
- 复制算法
![](https://i-blog.csdnimg.cn/blog_migrate/e780590895befd26e5af5dfd650e1952.png)
- 标记清除算法
![](https://i-blog.csdnimg.cn/blog_migrate/debeae12386412abed7b82b29df1e04a.png)
总结:
JVM在进行GC时,并不是对着三个区域统一回收。大部分时候,回收都是新生代
- 新生代
- 幸存区
- 老年区
GC两种类:
- 轻GC(普通的GC)
- 重GC(全局GC)
这几个题心里必须有数:
- JVM的内存模型和分区~详细到每个区放什么?
- 堆里面的分区有哪些?说他们的特点?
- GC的算法有哪些?标记清除法、标记压缩、复制算法、引用计数器,怎么用的?
- 轻GC和重GC分别在什么时候发生?
算法总结:
- 内存效率:复制算法>标记清除算法>标记压缩算法
- 内存整齐度:复制算法=标记压缩算法>标记压缩算法
- 内存利用率:标记压缩算法=标记清除算法>复制算法
(优解)分代收集算法:
- 年轻代:
存活率低=====使用复制算法
- 老年代:
区域大,存活率高========使用标记清除(内存碎片不多)+标记压缩算法