对象被判定为垃圾的标准?
没有被其他对象引用,如何判定没有被引用呢
a:判断对象的引用数量(引用计数算法)
通过判断对象的引用数量来决定对象是否可以被回收
每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1
任何引用计数为0的对象实例都可以被当做湿垃圾来处理
优点:执行效率高,程序执行受影响较小
缺点:无法检测出循环引用(相互引用)的情况,导致内存泄漏
b:可达性分析算法
通过判断对象的引用链是否可达来决定对象是否被回收
可以作为Gc Root的对象?
虚拟机栈中引用的对象
方法区中的常量引用的对象
方法区中的类静态属性引用的对象
本地方法栈中jni(Native)的引用对象
活跃线程的引用对象
谈谈你了解的垃圾回收算法?
a:标记-清除算法
标记:从根集合进行扫描,对存活的对象进行标记
清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存
缺点:容易造成碎片化
b:复制算法
分为对象面和空闲面
对象在对象面上创建
存活的对象被从对象面复制到空闲面
将对象面的对象内存清除
优点:
解决碎片化问题
顺序分配内存,简单高效
适用于对象存活率低的场景
c:标记-整理算法
标记:从根集合进行扫描,对存活的对象进行标记
清除:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收
优点:避免内存的不连续行
不用设置两块内存互换
适用于存活率高的场景
d:分代收集算法
垃圾回收算法的组合拳
按照对象生命周期的不同划分区域以采用不同的垃圾回收算法
提高jvm回收效率
Gc的分类
Minor GC 新生代(年轻代)gc
Full GC/major gc 进入老年代后将进行Full Gc
年轻代:尽可能快速的收集那些生命周期短的对象
Eden区,两个Survivor区,To和From
在Eden区创建,存活的放入Survivor区,在两个Survivor区来回执行,每次执行完清除一个Survivor区和Eden区。
对象如何晋升到老年代
经历一定Minor次数依然存活的对象,15岁
Survivor区中存放不下的对象
新生成的大对象-XX:+PretenuerSizeThreshold 设置,超过则放入老年代
常用的调优参数
-XX:SurvivoRatio:Eden和Survivo的比值,默认8:1
-XX:NewRatio:老年代和年轻代内存大小的比例
-XX:+PretenuerSizeThreshold
老年代:
Minor GC, Major GC,Full GC的区别
Minor GC发生在新生代中,采用复制算法;
Major GC发生在老年代中,采用标记—清除算法或标记—整理算法;
Full GC包括一次Minor GC和一次Major GC。
触发Full gc的条件
老年代空间不足
永久代空间不足 jdk7以下才有,jdk8变成元空间
CMS GC出现promotion failed,concurrent mode failure
Minor Gc晋升到老年代的平均大小大于老年代的剩余空间
调用System.gc(),对回不回收没有控制权
使用RMI来进行RPC或或者管理的JDK应用
调整元空间(方法区)大小-----jdk8
-XX:MetaspaceSize元空间初始大小
-XX:MaxMetaspaceSize元空间最大大小
调整永久代(方法区)大小-----jdk7
-XX:PermSize
方法区初始大小
-XX:MaxPermSize
方法区最大大小
超过这个值将会抛出OutOfMemoryError异常:java.lang.OutOfMemoryError: PermGen
年轻代常见垃圾收集器
垃圾收集器分为server和client模式。