java的内存回收机制

如何确定一个对象是否可以被回收?

1、 引用计数算法:判断对象的引用数量

2、 可达性分析算法:判断对象到GC Root引用链是否可达

ps:c++中解决循环引用的方法:

1. 当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
2. 当A的生存期超过B的生存期的时候,B改为使用一个普通指针指向A。
3. 使用弱引用的智能指针打破这种循环引用。
虽然这三种方法都可行,但方法1和方法2都需要程序员手动控制,麻烦且容易出错。我们一般使用第三种方法:弱引用的智能指针weak_ptr。

Java中引用的四种类型:

1.强引用:类似Object obj=new Object(),只要强引用还存在垃圾收集器永远不会回收掉被引用的对象

2.软引用:用来描述一些还有用但并非必须的对象,在系统将要发生内存溢出异常之前将会把这些对象列入回收范围之中,JDK1.2之后通过SoftReference类实现软引用

3.弱引用:描述非必须对象,比软引用弱,被弱引用关联的对象只能生成到下一次垃圾回收发生之前,无论内存是否足够。通过WeakReference来实现

4.虚引用:最弱的引用关系,一个对象是否有虚引用存在完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例,虚引用的唯一目的就是在这个对象被回收时可以得到系统通知。通过PhantomReference类实现虚引用。

PS:即使在可达性分析算法中不可达的对象也不是非死不可的。第一次不可达后会对对象进行一次标记和筛选,筛选对象没有覆盖finalize()方法或者已经被调用过,如果没有那么这个对象会被放置在F-Queue队列中,在稍后由一个自动建立的低优先级Finalizer线程去执行finalize()方法。稍后GC将会对队列中的对象进行第二次小规模标记,如果在finalize()方法中重新与引用链上的对象关联则可以移出即将回收的集合

可以做GC Root的对象


虚拟机栈中的引用对象
方法区中类静态属性引用的对象
方法区中常量引用对象
本地方法栈中JNI引用对象

 

垃圾收集算法

1、标记清除算法

2、复制算法

3、标记整理算法

4、分代收集算法

垃圾收集器

  • Serial收集器(复制算法)新生代单线程收集器,标记和清理都是单线程,优点是简单高效;

  • Serial Old收集器 (标记-整理算法)老年代单线程收集器,Serial收集器的老年代版本;

  • ParNew收集器 (复制算法)新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;

  • Parallel Scavenge收集器 (复制算法)新生代并行收集器追求高吞吐量,高效利用 CPU。吞吐量 = 用户线程时间/(用户线程时间+GC线程时间),高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;

  • Parallel Old收集器 (标记-整理算法): 老年代并行收集器吞吐量优先,Parallel Scavenge收集器的老年代版本;

  • CMS(Concurrent Mark Sweep)收集器(标记-清除算法): 老年代并行收集器以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。

  • G1(Garbage First)收集器 (标记-整理算法): Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代

 

PS:CMS和G1前3次标记的作用分别是

1.初始标记:仅标记GC Root能直接关联到的对象

2.并发标记:进行可达性分析标记

3.重新标记:修正在并发标记期间用户程序运作导致标记变动的对象

 

新生代转移到老年代的触发条件:

1、长期存活的对象

2、大对象直接进入老年代

3、minor gc后,survivor仍然放不下

4、动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代 

 

GC 相关参数总结

1. 与串行回收器相关的参数

-XX:+UseSerialGC:在新生代和老年代使用串行回收器。

-XX:+SurvivorRatio:设置 eden 区大小和 survivor 区大小的比例。

-XX:+PretenureSizeThreshold:设置大对象直接进入老年代的阈值。当对象的大小超过这个值时,将直接在老年代分配。

-XX:MaxTenuringThreshold:设置对象进入老年代的年龄的最大值。每一次 Minor GC 后,对象年龄就加 1。任何大于这个年龄的对象,一定会进入老年代。

2. 与并行 GC 相关的参数

-XX:+UseParNewGC: 在新生代使用并行收集器。

-XX:+UseParallelOldGC: 老年代使用并行回收收集器。

-XX:ParallelGCThreads:设置用于垃圾回收的线程数。通常情况下可以和 CPU 数量相等。但在 CPU 数量比较多的情况下,设置相对较小的数值也是合理的。

-XX:MaxGCPauseMills:设置最大垃圾收集停顿时间。它的值是一个大于 0 的整数。收集器在工作时,会调整 Java 堆大小或者其他一些参数,尽可能地把停顿时间控制在 MaxGCPauseMills 以内。

-XX:GCTimeRatio:设置吞吐量大小,它的值是一个 0-100 之间的整数。假设 GCTimeRatio 的值为 n,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集。

-XX:+UseAdaptiveSizePolicy:打开自适应 GC 策略。在这种模式下,新生代的大小,eden 和 survivor 的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。

3. 与 CMS 回收器相关的参数

-XX:+UseConcMarkSweepGC: 新生代使用并行收集器,老年代使用 CMS+串行收集器。

-XX:+ParallelCMSThreads: 设定 CMS 的线程数量。

-XX:+CMSInitiatingOccupancyFraction:设置 CMS 收集器在老年代空间被使用多少后触发,默认为 68%。

-XX:+UseFullGCsBeforeCompaction:设定进行多少次 CMS 垃圾回收后,进行一次内存压缩。

-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收。

-XX:+CMSParallelRemarkEndable:启用并行重标记。

-XX:CMSInitatingPermOccupancyFraction:当永久区占用率达到这一百分比后,启动 CMS 回收 (前提是-XX:+CMSClassUnloadingEnabled 激活了)。

-XX:UseCMSInitatingOccupancyOnly:表示只在到达阈值的时候,才进行 CMS 回收。

-XX:+CMSIncrementalMode:使用增量模式,比较适合单 CPU。

4. 与 G1 回收器相关的参数

-XX:+UseG1GC:使用 G1 回收器。

-XX:+UnlockExperimentalVMOptions:允许使用实验性参数。

-XX:+MaxGCPauseMills:设置最大垃圾收集停顿时间。

-XX:+GCPauseIntervalMills:设置停顿间隔时间。

5. 其他参数

-XX:+DisableExplicitGC: 禁用显示 GC。

你可能感兴趣的:(java的内存回收机制)