一、为什么要进行垃圾回收?
随着程序的运行,内存中存在的实例对象、变量等信息占据的内存越来越多,如果不及时进行垃圾回收,必然会带来程序性能的下降,甚至会因为可用内存不足造成一些不必要的系统异常。
二、哪些“垃圾”需要回收?
如果某个对象已经不存在任何引用,那么它可以被回收。
三、什么时候进行垃圾回收?
1、引用计数算法
每个对象添加一个引用计数器,每被引用一次,计数器加1,失去引用,计数器减1,当计数器在一段时间内保持为0时,该对象就认为是可以被回收得了。(在JDK1.2之前,使用的是该算法)
缺点: 当两个对象A、B相互引用的时候,当其他所有的引用都消失之后,A和B还有一个相互引用,此时计数器各为1,而实际上这两个对象都已经没有额外的引用了,已经是垃圾了。但是却不会被回收。
2、可达性分析算法
该算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,从一个节点GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点
目前java 中可作为GC Root 的对象有:
四、如何垃圾回收
内存主要被分为三块,新生代、旧生代、持久代。三代的特点不同,造就了他们所用的GC算法不同,
首先介绍下新生代、旧生代、持久代的概念及特点:
新生代: New Generation或者Young Generation。上面大致分为Eden区和Survivor区,Survivor区又分为大小相同的两部分:FromSpace 和ToSpace。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代的大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例.
旧生代: Old Generation。用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象。旧生代占用大小为-Xmx值减去-Xmn对应的值。
持久代: Permanent Generation。在Sun的JVM中就是方法区的意思,尽管有些JVM大多没有这一代。主要存放常量及类的一些信息默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来设置最小值和最大值。
五、常见的GC算法
1、标记-清除算法(Mark-Sweep)即分为标记和清除两个阶段进行处理内存中的对象。
缺点:
2、复制算法(Copying)
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。反复去交换两个内存的角色,完成垃圾收集
优点: 这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等。复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一半,未免太高了一点。
缺点: 复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低(所以eden区没有采用这个算法)
java中新生代的from和to空间就是使用这个算法
3、标记-整理算法(标记-压缩法)(Mark-Compact)
即是在标记清除法基础上做了优化,把存活的对象压缩到内存一端,然后直接清理掉端边界以外的内存(老年代使用的就是标记压缩法)
六、分代收集算法(Generational Collection)
1、根据对象存活周期的不同将内存划分为几块。
2、一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
3、在新生代中,每次垃圾收集时都发现有大批对象死去(回收频率很高),只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
其中,新生代又细分为三个区:Eden,From Survivor,ToSurviver,比例是8:1:1
4、老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。
七、分区算法
其主要就是将整个内存分为N个多小的独立空间,每个小空间都可以独立使用,这样细粒度的控制一次回收都少个小空间和那些个小空间,而不是对整个空间进行GC,从而提升性能,并减少GC的停顿时间。
八、GC算法优劣标准
评价一个垃圾收集GC算法的两个标准
九、吞吐量
JVM在专门的线程[GC Threads]中执行GC 只要GC线程是活动的 就会和应用程序线程[Application Threads]争用当前可用CPU的时钟周期而吞吐量就是指应用程序线程占程序总用时的比例
十、停顿
一个时间段内应用程序线程让GC线程执行而完全暂停。
垃圾回收器的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以高效的执行,大部分情况下,会要求系统进入一个停顿的状态。停顿的目的是终止所有应用线程,只有这样系统才不会有新的垃圾产生,同时停顿保证了系统状态在某一个瞬间的一致性,也有益于更好地标记垃圾对象,因此垃圾回收时,都会产生应用程序的停顿
十一、垃圾收集器
转自:https://blog.csdn.net/w372426096/article/details/81360083