zoukankan      html  css  js  c++  java
  • JVM 垃圾回收

    1. 如何判断垃圾可以回收

    (1)引用计数算法:引用时,计数+1,引用失效,计数-1,零时回收;缺点是遇到互相引用导致都不为零

    (2)可达性分析算法(Java用):扫描堆中的对象,沿着GC Root对象为起点的引用链看能否找到该对象,如果能则其仍然存活,不能则判定为可回收的对象。

    可作为GC Root的对象:栈帧中的局部变量,参数,临时变量;静态变量;常量;同步锁持有对象;Class对象

    2. 五种引用(由强至弱)

    • 强引用:传统的正常引用,只要引用关系还在,就不会被回收
    • 软引用:在系统将要内存溢出前,会把这些对象进行二次回收,如果回收后还是没有足够内存,才会抛出内存溢出异常(java.lang.ref.SoftReference)
    • 弱引用:当垃圾回收器开始工作时,就会回收弱引用关联的对象
    • 虚引用:为一个对象设置虚引用,在该对象被回收是会收到一个系统通知,是否有虚引用不会对其生存时间有影响。虚引用Cleaner,在ByteBuffer对象被回收后,其占用的直接内存地址还在,此时把虚引用Cleaner放到引用队列,执行Unsafe.freeMemory来释放直接内存。
    • 终结器引用(补):当对象被垃圾回收时,把对象加入引用队列(入队等待),之后通过终结器引用找到待回收的对象,调用对象的finalize()方法。注:由于处理引用队列线程优先级很低,所以不推荐用finalize()会回收对象。

    3. 垃圾回收算法

    (1)标记清除:先标记,然后清除,清除时就是把对象的起终地址记入空闲地址队列

    优点:速度快  缺点:产生内存碎片

    (2)标记整理:先标记,再把剩余的对象紧凑到一起

    优点:解决了外部碎片  缺点:速度较慢

    (3)标记复制:将内存划分出大小相等的两块,其中一块为原始,一块空白,把存活的对象复制到空白区(移动堆指针,按序分配无碎片)

    优点:无内存碎片,高效  缺点:占用太多空间

    4. 分代回收

    (1)对象首先分配在Eden区

    (2)新生代空间不足时,会触发minor gc,Eden和From中存活的对象被复制到To中,这些对象年龄+1,然后From和To指针交换

    (3)Minor gc会阻塞其他用户进程stop the world(因为对象地址在发生改变,不停止其他进程会错误),等垃圾回收结束再恢复运行

    (4)当对象寿命超过阈值时,它会晋升到老年代,最大寿命是15

    (5)当老年代空间也不足时,会先尝试Minor gc,若空间仍不足,会触发Full gc(标记+整理,较慢),若还不足,会触发out of Memory

    5. 几种垃圾回收器

    (1)串行垃圾回收器:Serial(复制算法)+SerialOld(标记整理算法)

    发生垃圾回收时,先让所有线程在一个安全点停止,等待垃圾回收结束以后其他线程继续工作

    (2)吞吐量优先回收器(垃圾回收时间占总运行时间比例最小,并行):Parallel+ParallelOld

    MaxGCPauseMillis:设置回收花费总时间尽量不超过该设定值

    GCTimeRatio:垃圾收集时间占总时间的比率

    (3)响应时间优先垃圾回收器(单次垃圾回收时间最短,并发):

    ParNew+CMS(标记清除)  垃圾回收和用户进程可以同时进行

    (4)G1垃圾回收器(在延迟可控的情况下获得尽可能高的吞吐量)

    1)G1把堆内存分成若干大小相同的Region,每个Region都可以是Eden,Survivor或Old,通过G1HeapRegionSize可以设置每个Region大小(弱化分代概念,引入分区思想)

    2)工作过程(三个流程循环进行):

    a. 新生代回收:和其他垃圾收集器新生代回收一样,Eden->Survivor->Old

    b. 新生代回收+并发标记(老年代占用到整堆45%时会开始)

    • 初始标记:仅标记GC Root能关联到的对象,有STW但很短
    • 并发标记:可以和用户进程并发,扫描整个堆的对象图,耗时长

    c. 混合回收(会对E,S,O全面回收)

    • 最终标记:短暂STW,标记并发阶段又产生变动的对象
    • 筛选回收:暂停用户线程,多线程并行,把存活的Region复制到空的Region,然后把旧的Region清理

    3)G1和CMS的新生代回收与Serial和Parallel一样,在老年代收集时,先会触发并发标记到筛选回收的过程,如果并发处理速度小于垃圾生成速度,才会Full gc(STW时间更长)

    4)优化:JDK 8u20版本里,所有新分配的字符串放入一个队列,在新生代收集时判断是否有相同字符串,如果有,让他们引用同一个对象

    8u40版本中,经过并发标记,如果发现一个类加载器的所有类都不再使用,则卸载所有它加载的类

    8u60版本中,如果一个对象大小超过Region一半,则称为巨型对象,G1不会对巨型对象拷贝,且会优先回收巨型对象

    6. GC调优

    (1)由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况

    (2)新生代空间Xmn不能太大或太小,建议25%-50%

    如果小了,新生代会发生频繁的Minor gc,有STW;如果大了,老年代空间会小,发生Full gc概率更大,而且空间大了回收时间会较长

    (3)大对象可以考虑放入老年代,否则占用新生代空间,-XX:PretenureSizeThreshold可以设置直接进入老年代的对象大小

    (4)-XX:MaxTenuringThreshold 设置对象进入老年代的年龄大小,减少老年代的内存占用,降低Full gc 发生的频率

    (5)设置稳定的堆大小,堆大小设置有两个参数:-Xms 初始化堆大小,-Xmx 最大堆大小。

    (6)如果满足下面的指标,则一般不需要进行 GC 优化:

    • Minor GC 执行时间不到50ms;
    • Minor GC 执行不频繁,约10秒一次;
    • Full GC 执行时间不到1s;
    • Full GC 执行频率不算频繁,不低于10分钟1次。
  • 相关阅读:
    C# 操作配置文件
    C# Excel操作类
    没有找到 mspdb100.dll 的解决办法
    工厂方法模式
    .Net互操作2
    The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决
    手机抓包xcode自带命令行工具配合wireshark实现
    expecting SSH2_MSG_KEX_ECDH_REPLY ssh_dispatch_run_fatal问题解决
    使用ssh-keygen设置ssh无密码登录
    远程复制文件到服务器
  • 原文地址:https://www.cnblogs.com/Kinghao0319/p/14460136.html
Copyright © 2011-2022 走看看