新生代和老年代
对象在被实例化之后,都是属于新生代。
大部分新生代的生命周期都是及其短暂的,例如在一个方法中创建的对象会随着方法执行完毕,栈空间的栈帧出栈后而失去引用。
而有一些对象确实会长期存活在堆内存的,比如被Static引用的对象。这种对象不会轻易的被垃圾回收器回收。
所以JVM会将堆内存分为两个区域,一个年轻代,一个老年代。
其中年轻代,顾名思义,就是创建和使用完之后立马就要被回收的对象放在里面。然后老年带呢,就是把一些会长期存活的对象放在里面。
为什么要分成新生代和老年代很多人都会有一个疑问,为什么要划分两个区域呢?
因为这个垃圾回收有关,对于年轻代的对象,他们的特点是很快就会被回收,所以需要使用一种垃圾回收算法。
而对于老年代而言,里面的大部分对象可能都会长期存活,那么使用新生代的回收算法放在这里就可能并不是那么的合适。需要有着自己的一套回收算法。
什么是永久代很简单,JVM里的永久代其实就是我们之前说的方法区
所谓的永久代,你可以认为是存放一些类的信息,在上一个章节我们知道我们生成的.class就是存放在这个区域的。一般情况下,我们对于jvm调优都是对新生代和老年代进行调优。一般而言永久代保持默认配置就可以了。
是不是意味着我们就不需要关注永久代?
肯定不是的。因为要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。最典型的场景就是,在 jsp 页面比较多的情况,容易出现永久代内存溢出。
如何判断一个对象是否是垃圾我们知道,当一个对象被创建出来的时候,比如说在一个方法中创建一个对象,当该方法执行完毕后,就没有引用指向这个对象了,这个对象就会变成垃圾对象。
这仅仅是一种情况。
到低哪些对象是辣鸡,哪些对象不是?
JVM中使用了一种可达性分析算法来判定哪些对象是可以被回收的。这个算法的核心就是看这个对象有谁在引用它,然后一层一层的往上判断,看是否被GC roots所引用。
在java中,可作为GC Roots的对象有:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象(也就是我们前面提到在方法中创建的对象); 2.方法区中的类静态属性引用的对象; 3.方法区中常量引用的对象; 4.本地方法栈中JNI(即一般说的Native方法)中引用的对象当一个对象没有被上述所引用,那么这个对象就可以被认为是垃圾对象了。
总之记住一句话,只要你的对象被方法的具备变量,类的静态变量给引用了,就不会回收他。
java中对象不同的引用关系。1、强引用
就是被GC roots所直接引用的对象。只要是强引用关系,那么垃圾回收器是绝对不会回收这个对象的。2、软引用
public class test{ public static SoftReference<ReplicaManager> manager = new SoftReference<ReplicaManager>(new Replicamanager) } /**如上诉代码,实例对象被“SoftReference” 软引用类型的对象包装起来了,那么这个对象的引用就是软引用。 正常情况下是不会回收软引用对象的,但是如果你进行垃圾回收后,返现内存还是不够存放新的对象的时候,这个时候就会吧软引用的对象给回收掉 **/3、弱引用
这个相对前两中使用的很少,与软引用类时,当一个实例对象被“WeakReference”弱引用的对象包装起来的时候,那么这个对象就是弱引用。 弱引用的生命周期就存在下一次垃圾回收之前,也就是说下一次垃圾回收会回收掉弱引用的对象。4、虚引用
最弱鸡的一种引用,我感觉没什么作用。一个对象是不是虚引用对他本生的生命周期没有影响。该什么时候回收就什么时候回收。 设置他唯一的目的就是被回收的时候会得到一个系统通知,一般来说没什么卵用 finalize()方法的作用到这里,我相信你应该清楚了哪些对象会被回收哪些对象不会被回收。
如果一个对象被GC Roots所引用,但是!!他如果是软引用或弱引用,那么也是可能会被辣鸡回收器给回收掉的。
在垃圾对象被回收的时候,会调用Object对象的finalize()方法。
我们来模拟一个辣鸡的自我救赎代码。
public class A{ public static A instance; @Override protected void finalize() throws Throwable{ A.instance = this; } }当对象被回收的时候,调用finalize方法,重新将GC Roots的变量引用指向自己,那么就不会被回收了。
这个基本上没人用,感觉就是一个sb才会写的代码。写出来就是给大家说出这个细节。
新生代对象是如何变成老年代对象的 长期存活的对象会多次躲过垃圾回收