0
点赞
收藏
分享

微信扫一扫

JVM垃圾回收机制

北冥有一鲲 2022-02-20 阅读 59
java

参考链接:
https://www.bilibili.com/video/BV1AE411E7uj?p=1
https://www.bilibili.com/video/BV1yE411Z7AP?spm_id_from=333.999.0.0
https://www.cnblogs.com/chenpt/p/9803298.html
https://www.iteye.com/problems/71569
https://codingdict.com/questions/113892
https://www.cnblogs.com/dmzna/archive/2020/05/18/12913458.html
https://www.cnblogs.com/shouyaya/p/13524476.html
https://blog.csdn.net/mccand1234/article/details/52078645
https://blog.csdn.net/qq_41701956/article/details/81664921
https://blog.csdn.net/yubujian_l/article/details/80804708

补:运行时数据区

补:程序计数器

为了保证程序(在操作系统中理解为进程)能够连续地执行下去,处理器必须具有某些手段来确定下一条指令的地址。而程序计数器正是起到这种作用,所以通常又称为指令计数器。在程序开始执行前,必须将它的起始地址,即程序的第一条指令所在的内存单元地址送入程序计数器,因此程序计数器的内容即是从内存提取的一条指令的地址。当执行指令时,处理器将自动修改PC的内容,即每执行一条指令PC增加一个量,这个量等于指令所含的字节数,以便使其保持的总是将要执行的下一条指令的地址。由于大多数指令都是按顺序来执行的,所以修改的过程通常只是简单的对PC加1。
但是,当遇到转移指令如JMP(跳转、外语全称:JUMP)指令时,后继指令的地址(即PC的内容)必须从指令寄存器中的地址字段取得。在这种情况下,下一条从内存取出的指令将由转移指令来规定,而不像通常一样按顺序来取得。因此程序计数器的结构应当是具有寄存信息和计数两种功能的结构。
这一部分不会发生内存泄漏,程序计数器指令可以标记if for 多线程等“运行到哪里” 通常又称之为‘指令计数器’

补:JVM堆空间(gc堆)

  • 存放: 对象实例 and 数组
  • 每次new操作都是在堆中开辟空间,不一定是连续的空间,
  • 堆空间的分配常用分代策略(新生代 老年代 永久代(现:元空间))

补:垃圾回收的流程

以分代机制+回收算法+G1垃圾收集器为例:

  • G1垃圾收集器决定了:垃圾回收的cpu资源调度方式是并发兼顾延迟和吞吐量,分堆;能结合多种算法策略,是一个监视者的角色。
  • 回收算法决定了:xx对象在本轮回收中是否被回收,如强引用则不回收,其他引用回收策略不同
  • 分代机制决定了:什么时候调用垃圾回收,如新生代区的Eden满后调用Minor GC
  • 过程:不停的new,因为引用方式不同and对象大小不同,会导致不同的对象分在了元空间(相当于JDK8之前的永久代)、新生代(Eden满后Minor GC)、老年代(System.gc()或老年代区满后Full GC)
    ————因为垃圾回收器的区别,如G1会动态监控并标记GC Roots,调用回收算法
    ————进行可达性分析,决定对象的去留
    ————调用Full GC来进行垃圾回收,释放内存

JVM如何判定一个对象是否应该被回收?

1.引用计数器算法×

方法内容:
对象被引用一次,计数器+1;失效一次,计数器-1,计数器归零后失效

不能解决互相引用情况下的垃圾回收问题,例如:LinkedList源码中clear方法和unLinked方法需要多步操作来消除循环引用

2.可达性分析算法√

在Java C#中的主流算法
算法思想:
通过一些列成为“GC Roots”的根对象作为起始点,如果一条引用链的起始点不是GC Roots,那么就会被垃圾回收(不是强引用就会被垃圾回收,只是时间问题
GC Roots包括:

  1. 虚拟机栈中引用的对象
  2. 方法区静态属性引用的对象
  3. 方法区常量引用的对象
  4. 本地方法引用的对象(底层是c或操作系统语言)
    打圈的会被回收

GC Roots

这其实是一个相对的概念,在调用Minor GC的时候,老年代就是根对象
像上面的那4种是“即使Full GC”也不会回收的,就是绝对的根对象

补充:引用的四种方式:

参考链接

强引用

Object obj = new Object();强引用在,垃圾收集器就一直不会被回收该对象,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

软引用SoftReference

SoftReference aSoftRef=new SoftReference(obj);如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;软引用可用来实现内存敏感的高速缓存,一旦垃圾线程回收该Java对象之 后,get()方法将返回null

弱引用WeakReference

创建方法和WeakReference 相同,但比SoftReference更弱,仅仅能生存到下次垃圾回收之前,无论内存是否足够 都会回收

    People people=new People("zjh",21);  
    WeakReference<People>reference=new WeakReference<People>(people);
    System.out.println(reference.get());  //zjh 21
    System.gc();  
    System.out.println(reference.get()); //null

虚引用PhantomReference

最弱的引用关系,虚引用主要用来跟踪对象被垃圾回收的活动,在回收之前通知系统,但不影响对象的生命周期

JVM垃圾回收算法有哪些?

  • 以下三种方法,在实际的虚拟机中是组合使用,去其糟粕,取其精华
  • 垃圾回收算法 和 回收机制不同

标记清除算法

标记不连续,可用内存被分割,在申请连续大空间时可能没有可用的内存,资源浪费大

标记整理算法

标记的同时把可用对象整理在一起

复制算法

局限性很大,内存利用率很差,先复制可用存活对象复制到一块区域

右边这块的内存都是不能使用的

参考链接

JVM垃圾回收机制

  • 回收机制≠回收算法
  • 常用的是分代回收策略
  • 一般是只要空间不足就触发垃圾回收机制

代的划分

参考链接1
参考链接2

商用Java内存分配和回收的机制概括的说,就是:分代分配,分代回收

  • 对象将根据存活的时间被分为:
    年轻代(Young Generation):回收频率快
    年老代(Old Generation):回收频率慢
    永久代(Permanent Generation,也就是方法区,JDK1.8之后删除了永久代)
  • 不同代有不同的算法,不同的处理机制
  • 内存担保机制:新生代到老年代

新生代的三个分区8:1:1

Eden伊甸园:From幸存区:To幸存区=8:1:1
From是上一次幸存的对象
To是本次幸存的对象

  • new一个对象,默认采用伊甸园的空间,大对象则直接到老年代
  • 一直new直到伊甸园空间放不够了就触发新生代垃圾回收Minor GC
  • 直到连老年代都快满了,触发老年代垃圾回收Full GC

Minor GC

  • 触发了Minor GC之后就调用垃圾回收算法(标记清除、标记整理、复制算法)
  • 例如调用了标记算法,就把标记存活的对象复制到幸存区To中,寿命计数器+1;而被标记回收的伊甸园对象则被回收
  • 伊甸园再次空闲,直到下次满的时候触发第二次Minor GC
  • 寿命计数器>15(4bit)时(可能因为新生代空间严重不足而提前晋升),对象从新生代传入老年代,此后不会被Minor GC回收
  • 会触发STW,但耗时短

Full GC

  • 新生代老年代同时进行垃圾回收
  • 会触发STW,且耗时长
  • 调用System.gc()

STW

  • stop thr world 当触发STW时,其他的所有线程都停止,直到垃圾回收完成
  • 因此回收效率高,但会有停顿时间,适合在Client端使用,不适合在Sever端使用
  • Minor GC 和 Full GC都会触发STW

垃圾收集器

JVM中的垃圾收集器主要包括7种,即Serial,Serial Old,ParNew,Parallel Scavenge,Parallel Old以及CMS,G1收集器。

G1——Garbage one

  • 取代CMS垃圾回收器
  • 出自JDK7,JDK9之后成为默认的垃圾回收器
  • 并发
  • 同时注重吞吐量和响应时间
  • 适合于超大内存场景,会将堆均匀分区以便并发,每个区都有独立的年轻代、老年代堆区域
  • CMS和G1都是Full GC(老年代垃圾回收机制)

串行

  • 单线程
  • 堆内存小,适合个人电脑

吞吐量优先

  • 多线程
  • 堆内存大,需要多核CPU支持(真并发),适合服务器
  • 一次大量回收,单位时间STW时间尽可能短,总时间更短

响应时间有限

  • 多线程
  • 堆内存大,需要多核CPU支持(真并发),适合服务器
  • 单次少量回收,单次STW时间尽可能短,每次影响更小
举报

相关推荐

0 条评论