小区域收集 + 形成连续的内存块,最后在收集完成后,就会形成连续的内存空间,这样就解决了内存碎片的问题
四步过程
初始标记:只标记GC Roots能直接关联到的对象
并发标记:进行GC Roots Tracing(链路扫描)的过程
最终标记:修正并发标记期间,因为程序运行导致标记发生变化的那一部分对象
筛选回收:根据时间来进行价值最大化回收
参数配置
开发人员仅仅需要申明以下参数即可
三步归纳:-XX:+UseG1GC -Xmx32G -XX:MaxGCPauseMillis=100
-XX:MaxGCPauseMillis=n:最大GC停顿时间单位毫秒,这是个软目标,JVM尽可能停顿小于这个时间
G1不会产生内碎片
是可以精准控制停顿。该收集器是把整个堆(新生代、老年代)划分成多个固定大小的区域,每次根据允许停顿的时间去收集垃圾最多的区域。
### # 十、确定垃圾、什么是GC Roots? ### 什么是垃圾? 简单来说就是内存中不再被使用的空间就是垃圾 ### 如何判断一个对象是否可以被回收 | 引用计数法 | Java中,引用和对象是有关联的。如果要操作对象则必须用引用进行。
因此,很显然一个简单的办法就是通过引用计数来判断一个对象是否可以回收。简单说,给对象中添加一个引用计数器
每当有一个地方引用它,计数器值加1
每当有一个引用失效,计数器值减1
任何时刻计数器值为零的对象就是不可能再被使用的,那么这个对象就是可回收对象。
那么为什么主流的Java虚拟机里面都没有选用这个方法呢?其中最主要的原因是它很难解决对象之间相互循环引用的问题。
该算法存在但目前无人用了,解决不了循环引用的问题,了解即可。![image.png](https://cdn.nlark.com/yuque/0/2020/png/308918/1592864179684-c7670260-f2b7-4c11-9516-a62b6ad5d21e.png#align=left&display=inline&height=226&margin=%5Bobject%20Object%5D&name=image.png&originHeight=226&originWidth=791&size=97327&status=done&style=none&width=791) | | --- | --- | | 枚举根节点做可达性分析 | 为了解决引用计数法的循环引用个问题,Java使用了可达性分析的方法:
![image.png](https://cdn.nlark.com/yuque/0/2020/png/308918/1592864296023-8a2a40fc-3b4e-4f5a-a20c-dd4a7c5023ab.png#align=left&display=inline&height=223&margin=%5Bobject%20Object%5D&name=image.png&originHeight=223&originWidth=788&size=120155&status=done&style=none&width=788)
所谓 GC Roots 或者说 Tracing Roots的“根集合” 就是一组必须活跃的引用
基本思路就是通过一系列名为 GC Roots的对象作为起始点,从这个被称为GC Roots的对象开始向下搜索,如果一个对象到GC Roots没有任何引用链相连,则说明此对象不可用。也即给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,没有被遍历到的对象就被判定为死亡
![image.png](https://cdn.nlark.com/yuque/0/2020/png/308918/1592864258220-a87af921-7673-44f0-a1c8-e95bc7cb5558.png#align=left&display=inline&height=447&margin=%5Bobject%20Object%5D&name=image.png&originHeight=447&originWidth=798&size=285021&status=done&style=none&width=798)
必须从GC Roots对象开始,这个类似于linux的 / 也就是根目录
蓝色部分是从GC Roots出发,能够循环可达
而白色部分,从GC Roots出发,无法到达 | | 可以被当做GC Roots的对象 |
- 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中的引用对象
- 方法区中的类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中的JNI(Native方法)的引用对象
| GC前对于重写的finalize方法的处理流程