Contents

Java-GC机制

背景:

  • Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。
  • 堆空间是用来存储new出来的对象的,当new出来的对象填充满时,会让堆爆掉,程序就挂了,这显然时不被允许的。
  • Garbage Collection的机制就是判断堆内存中哪些对象能被删除,判断的标准就是GCRoot

GCRoot

  • GCRoot:指向堆中的对象的引用,包含:
    • 栈上的引用直接或者间接地被引用
    • 方法区上全局的的Static变量&常量直接或者间接被引用
    • 本地方法栈上的的C++直接或者间接被引用
  • 那些可以直接存在的,没有和GCRoot有相连的关系的对象可以被删除

GC机制清理堆中垃圾的思路

  • **标记-清理:**在堆中要删除对象后面打标

    • 缺点:标记和清除两次扫描会严重浪费时间,同时会产生内存碎片
    • 优点:不需要额外空间
  • **标记-整理:**堆中删除的对象留下的空间能聚集在一起

    • 缺点:代价太大,除了两次扫描还要把所有整理后的对象前移
    • 优点:减少了内存碎片
  • **复制算法:**将整个内存一分为二,将1区需要删除的标记,然后将没打标记的对象紧凑复制到2区,既避免了内存碎片问题,整个内存开销又不是很大。

    • 缺点:需要两倍内存空间
    • 优点:不会产生碎片问题
    • 最佳使用场景:对象的成活率较低(新生区就是这样)
  • 实际的GC:将堆区划分

    • 新new的对象都会在Eden(伊甸园)出生,当Eden快满的时候会触发young区域的GC,采用复制算法,将Eden中没有标记的对象复制到Survivor0(幸存0)区域

    • Eden很大,Survivor更小。因为对象都有一个特点:朝生夕死,很容易就夭折了,生死率大概是1:8

    • 需要两块Survivor区交替工作(From和To的反复交替:谁空谁是To)

      • E+S1 复制到 S0
      • E+S0 复制到 S1
      • E+S1 复制到 S0
      • …(如此交替工作)
    • 一个对象每幸存1次,其年龄就会+1,如果满了6岁,(满了6岁基本60岁都不会清理了)就不会复制到Survivor区了,就会直接到Old区了

    • 大对象(例:1000万个元素的int数组)会直接存放到Old区。

    • Old区满了也会触放GC,OldGC一般也会伴随YoungGC,所以,Old区满了会触发FullGC,此时会触发stoptheworld,java程序全部暂停,报错OOM(java.lang.OutOfMemory :Java heap space),全力进行垃圾回收(采用标记清理 or 标记整理算法)

    • 总结:

    • 标记-清理和标记-整理 主要用在 FullGC机制

      • 复制算法只要用在 YoungGC机制
    • 内存效率(时间复杂度): 复制算法>标记清除>标记整理

      • 内存整齐度: 复制算法=标记整理>标记清除
      • 内存利用率: 标记整理=标记清除>复制算法
      • 没有最好的算法,只有最合适的算法
    • 垃圾收集器:

      • 年轻代:ParNew:复制算法
      • 老年代:CMS:标记-清理
      • 最新版的JDK采用的是:G1垃圾收集器
  • 永久区

    该区域常驻内存,用来存放JDK自身携带的Class对象等。存储的是java运行时的一些环境。

    该区域不存在垃圾回收,关闭虚拟机就会释放该区域的内存

    • jdk1.6之前:永久代,常量池在方法区
    • jdk1.7:永久代慢慢退化了,常量池在堆中
    • jdk1.8之后:无永久代,整个方法区(包含常量池)都在元空间

    JDK8之后的堆内存模型:

    这个元空间:逻辑上存在,物理上不存在

    堆内存参数调优初识:在IDEA中,VM options中添加几个参数,可以指定最大内存,最小内存,和是否打印GC的详细信息

    1
    
    -Xms8m -Xmx8m -XX:+PrintGCDetails
    

相关题目

  1. JVM的内存模型和分区~详细到每个区都放什么?
  2. 堆里面的分区有哪些?Eden,from,to,老年区,说说他们的特点?
  3. GC的算法有哪些:标记清除法,标记整理,引用计数法
  4. 轻GC和中GC分别在什么时候发生?
1
2
#定义对象进入老年区的时间,默认是15
-XX:MaxTenuringThreshold=15