• 引用类型

    • 强引用:类似Object o=new Object()这种引用。只要强引用还存在,对象不会被回收。

    • 软引用:对于软引用关联的对象,在系统将要发生内存溢出前,会被纳入回收范围,并进行第二次回收。

    • 弱引用:被弱引用关联的对象只能生存到下一次回收之前。无论内存是否足够都会被回收。

    • 虚引用:不会影响对象生存时间,也无法获得对象实例,对其唯一期望是关联的实例在被回收时收到一个系统通知。

  • 对象回收

    • 引用计数法(Reference Counting)

      • 给对象中添加一个引用计数器,被引用时+1,失效时-1。任何时刻引用计数为0则对象不可再使用。 这种算法很难应对循环引用的情况。

    • 根搜索算法(GC Roots Tracing)

      • 当一个对象到GC Roots不可达时,证明此对象是不可用的。根搜索算法中,无法到达的对象并非立即回收,而是被标记一次后进行筛选,筛选的条件是此对象是否有必要执行finaliz()方法。存在该方法(未被调用 过)的对象,将被放置在名为F-Queue的队列,并在稍后有虚拟机建立一个低优先级的Finalizer线程执行(虚拟机不承诺该方法执行结束,不一定 会执行), 稍后GC将对F-Queue进行第二次小规模标记,如果此时发现对象可达,将被移出即将回收集合。

      • 可作为GC根的对象包括

        • 虚拟机栈(中局部变量表)中引用的对象。

        • 方法区中类静态属性引用的对象。

        • 方法区中常量引用的对象。

        • 本地方法中JNI(java本地方法)的引用对象。

  • 方法区回收

    • 废弃常量:与堆中实例回收类似(常量池中类、接口、方法、字段的符号引用也类似)。

    • 无用的类:堆中没有该类实例——加载该类的Classloader已被回收,该类对应的java.lang.Class对象没有引用,无法通过反射访问。

    • 大量使用反射、动态代理、CGLib等bytecode框架的场景,以及动态生成jsp或者osgi这类频繁自定义Classloader的场景都需要该功能

  • 垃圾回收算法

    • 标记-清除算法(Mark-Sweep)

      • 算法:首先标记所有需要回收的对象,在标记完成后,统一回收所有被标记对象。

      • 优点:不存在循环引用问题。

      • 缺点:效率不高,会产生大量不连续内存碎片。

    • 复制算法(Copying)

      • 算法:将可用内存分为两块,每次只使用一块,回收时将此块内存中还生存的对象复制到另一块,把已使用的内存清理掉。

      • 优点:不会出现碎片问题。

      • 缺点:浪费。对象存活率较高时,效率降低。

    • 标记-整理算法(Mark-Compact)

      • 算法:与标记-清除算法类似,只是不直接回清除,而是让所有对象向一端移动,然后清理掉端边界以外的内存。

    • 分代收集算法(Genrerational Collection)

      • 算法:根据对象存活周期划分内存为几块,一般是把堆分为新生代和老年代,根据各个时代不同,采用不同算法。

  • 垃圾收集器

    • 示意图

JVM(二)——GC_虚拟机

    • Serial

      • 单线程垃圾收集器,运行时停止其他线程直到GC结束。

      • 新生代:复制算法。

      • 老年代:标记-整理算法。

    • ParNew

      • Serial的多线程版本。

      • 新生代:复制算法。并行。

      • 老年代:标记-整理算法。串行。

    • Parallel Scavenge

      • 新生代收集器,使用复制算法。并行。类似ParNew收集器,此收集器更关注系统的吞吐量。可以通过参数来打开自适应调节策略,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量;也可以通过参数控制GC的时间不大于多少毫秒或者比例。

    • Serial Old

      • 老年代收集器,使用标记-整理算法。串行。

    • Parallel Old

      • Parallel Scavenge的老年代版本。使用标记-整理算法。并行。

    • Cms

      • 以获取最短回收停顿时间为目标的收集器。标记-清除算法。

      • 步骤:

        • 初始标记:快速标记GC根能连接的对象。

        • 并发标记:根搜索,标记待回收。

        • 重新标记:应对标记期间变动的对象的标记记录。

        • 并发清除:回收。

      • CPU敏感。

      • 无法处理浮动垃圾:一些在本次GC过程中生成的数据,只能留待下一次GC。如果GC过程中预留内存无法满足,会抛出Concurrent Mode Failure后,启动Serial Old进行老年代垃圾收集。

      • 标记-清除算法会产生大量空间碎片,在无法为对象找到足够的连续空间时,会触发Full GC。

    • G1

      • 基于标记-整理算法实现,可以精确控制停顿。

  • 内存分配与回收策略

    • 优先在eden分配。大对象直接进入老年代。长期存活对象将进入老年代。