什么是GC?
垃圾收集(Garbage Collection)通常被称为“GC”,由虚拟机“自动化”完成垃圾回收工作。
思考一个问题,既然GC会自动回收,开发人员为什么要学习GC和内存分配呢?为了能够配置上面的参数配置?参数配置又是为了什么?
当排查各种内存溢出问题的时候,当垃圾回收成为系统达到更高并发量的瓶颈时,我们就需要对GC的自动回收实施必要的监控和调节。
如何判断对象存活
1.引用计数算法法
给对象添加一个引用计数器,每当有一个地方引用到这个对象得时候,计数器加1,释放得时候计数器减一,当计数器为0得时候这个对象就会被回收。引用计数器事现简单,判断效率高,但是无法解决循环引用得问题。
2.可达性分析算法
可达性分析算法是通过GC ROOT的对象作为起点,基于对象的引用关系向下搜索,走过的路线叫做引用链,当一个对象到GC ROOT没有任何引用链的时候,这个对象就是不可用的可以被回收的。
绿色的是有引用链的不需要被回收,灰色的对象是没有到GC ROOT的引用链需要被回收。
说说Java GC都用了哪些算法?
一.标记清除算法、
Mark-sweep算法,包含两个阶段标记和清除,首先标记出所有需要回收的对象,然后统一回收掉被标记的所有对象
优缺点:一个是效率问题,标记和清楚的效率都不高,另外是空间问题,标记和清楚以后会产生大量的不连续碎片,空间碎片太多可能会导致当程序再运行的时候需要较大的对象时无法找到足够连续的内存空间而导致不得不提前出发另一次垃圾回收机制
二.标记整理算法
Mark-compact算法,和标记清除一样,但后续步骤并不是对可回收对象进行清理,而是让所有存活的对象向一侧进行移动然后清除掉边界意外的内存
这种算法不既不用浪费50%的内存,也解决了复制算法在对象存活率较高时的效率低下问题。
三.复制算法
Copying算法,奖可用的内存分为两块,每次只用其中一块,当一块内存用完了,就奖还存活的对象复制到另外一块内存空间里面去,然后清理掉之前的那一块。
每次对半区内存回收时、内存分配时就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
缺点:将内存缩小为一半,性价比低,持续复制长生存期的对象则导致效率低下。
四.分代收集算法
基本思路就是将JAVA的堆内逻辑分成两块,新生代和老年代针对不同的存货周期,不同的大小的对象采取不同的垃圾回收策略。
在新生代中大多对象都是瞬间对象,只有少量对象存活,复制较少的对象可以完成清理,因此采取复制算法。老年代的对象存活率较高,有没有额外的担保内存,因此采用标记整理算法
JVM内存优化
途中展示了三个区域:Eden 、from survivor,to survivor ,他们的比例是8:1:1为什么要这样设计呢?因为:由于Eden中的对象属于像浮萍一样“瞬生瞬灭”的对象,所以并不需要1:1的比例来分配内存,而是采用了8:1:1的比例来分配。
常用控制参数:
- -Xms设置堆的最小空间大小。
- -Xmx设置堆的最大空间大小
- -Xmn设置新生代初始最大大小
- -XX:Newsize设置新生带最小空间大小
- -XX:MaxNewsize设置新生代最大空间大小
- -XX:Permsize设置永久代最小空间大小
- -XX:MaxPermsize设置永久最大空间大小
- -Xss:设置每个线程的堆栈大小