JavaGC面试题

GC的标记算法

  • 引用计数算法

    • 通过判断对象的引用数量来决定对象是否可以被回收

    • 每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1

    • 任何引用计数为0的对象实例可以被当作垃圾收集

      优点:执行效率高,程序执行受影响较小

      缺点:无法检测出循环引用的情况,导致内存泄漏

  • 可达性分析算法(主流)

    • 通过判断对象的引用链是否可达来决定对象是否可以被回收
    • 可以作为GC Root的对象
      • 虚拟机栈中引用的对象(栈帧中的本地变量表)
      • 方法区中的常量引用对象
      • 方法区中的类静态属性引用的对象
      • 本地方法栈中JNI(Native方法)的引用对象
      • 活跃线程的引用对象

GC的垃圾回收算法

  • 标记-清除算法(Mark and Sweep)(适合垃圾少)

    • 标记:从根集合进行扫描,对存活的对象进行标记(可达性分析算法)
    • 清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存
  • 标记-整理算法(Compacting)(适合垃圾少)

    • 标记:从根集合进行扫描,对存活的对象进行标记(可达性分析算法)
    • 整理:移动所有存活的对象,且按照内存地址次序依次排列,将末端内存地址以后的内存全部回收(对标记-清除算法的优化,防止内存碎片问题)
  • 复制算法(Copying)(适合垃圾多,减少复制的对象数量)

    • 将内存分为对象面和空闲面
    • 对象在对象面创建
    • 存活的对象被从对象面复制到空闲面,此时原先的对象面变为现在空闲面,被复制了对象的原先空闲面变为现在对象面
  • 分代收集算法(Generational Collector)

    • 以上回收算法的组合拳

    • 按照对象生命周期的不同划分区域以采用不同的垃圾回收算法

    • 年轻代使用复制算法(年轻代,垃圾多适合复制算法),老年代使用标记整理算法或标记清除算法(老年代,垃圾少适合这两种算法)


    • 年轻代使用的算法,也叫Minor GC

      • 年轻代的内存分布(Eden区,两个Surrvivor区(from区,to区))

      • 对象如何晋升到老年代

        • 经历一定Minor次数依然存活的对象
        • Survivor区中存放不下的对象
        • 新生成的大对象(-XX:+PretenuerSizeThreshold 大于该值直接放进老年代)
      • 常用的调优参数

        • -XX:SurvivorRatio:Eden和Survivor的比值,默认8:1
        • -XX:NewRatio:老年代和年轻代内存大小的比例
        • -XX:MaxTenuringThreshold:对象从年轻代晋升到老年代经过GC次数的最大阈值
    • 老年代使用的算法

      • Full GC(新老同时一起GC)和Major GC(老年代GC:标记-整理算法)
      • 触发Full GC的条件
        • 老年代空间不足
        • 永久代空间不足(jdk8前)
        • Minor GC 晋升到老年代的平均大小大于老年代的剩余空间
        • 调用System.gc()

年轻代常见的垃圾收集器

JVM的运行模式

  • Server:启动慢,重量级,启动后运行速度快
  • Client:启动快,轻量级,启动后较Server运行速度慢

Serial收集器

-XX:+UseSerialGC,复制算法

  • 单线程收集,进行垃圾收集时,必须暂停所有工作进程
  • 简单高效,Client模式下默认的年轻代收集器

ParNew收集器

-XX:+UseParNewGC,复制算法

  • 多线程收集,其余行为、特点和Serial收集器一样
  • 属于Server模式下的收集器单核执行效率不如Serial,在多核下执行才有优势

Parallel Scavenge收集器

-XX:+UseParallerel,复制算法

吞吐量=运行代码的时间/(运行代码的时间+垃圾收集时间)

  • 比起关注用户线程停顿时间,更关注系统的吞吐量
  • 在多核下执行才有优势,Server模式下默认的年轻代收集器

老年代常见的垃圾收集器

Serial Old收集器

-XX:+UseSerialOldGC,标记-整理算法

  • 单线程收集,进行垃圾收集时,必须暂停所有的工作线程

  • 简单高效,Client模式下默认的老年代收集器

Parallel Old收集器

-XX:+UserParallelOldGC,标记-整理算法

  • 多线程,吞吐量优先

CMS收集器

-XX:+UseConcMarkSweepGC,标记-清除算法

新老代集成的垃圾回收器

G1收集器

-XX:+UseG1GC,复制+标记-整理算法

垃圾收集器之间的联系

连线表示可以共用

Java中的引用类型

强引用

  • 最普遍的引用:Object obj=new Object()
  • 即使抛出OutOfMemoryError(内存满了)也不会回收具有强引用的对象
  • 通过将对象设置为null来弱化引用,使其被回收

软引用(Soft Reference)

  • 对象处在有用但非必须的状态
  • 只有当内存空间不足时,GC会回收该引用的对象的内存
  • 可以用来实现高速缓存
  • 同样,软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象垃圾回收Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

弱引用(Weak Reference)

  • 非必须的对象,比软引用更弱一些
  • GC时会被回收
  • 被回收的概率也不大,因为GC线程优先级比较低
  • 同样,弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象垃圾回收Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

虚引用(PhantomReference)

  • 不会决定对象的生命周期
  • 任何时候都可能被垃圾收集器回收
  • 跟踪对象被垃圾收集器回收的活动,起哨兵作用
  • 必须和引用队列ReferenceQueue联合使用

四种引用的关系

原文地址:https://www.cnblogs.com/shouyaya/p/13524476.html