1
finalize 方法类似于C++中的西沟函数,在实力类覆盖了finalize方法时,
被垃圾回收之前调用该方法,执行析构的逻辑,因此可能会造成回收逃逸(如果在析构函数中将当前对象指向this,就又可以使用了)
2
四种引用
2.1 strong reference 强引用,我们最常用的方式
2.2 soft reference 软引用,使用SoftReference
当内存足够时,不回收,当内存不够时,被gc回收,Guava缓存底层用的就是这个东西.比较实用
2.3 weak reference 弱引用,使用WeakReference进行使用,当第二次垃圾回收的时候被回收.
2.4 幽灵引用 PhantomReference ,可用来判断某个对象是否已经被垃圾回收.
3
根搜索算法
有四种对象可以当做GC root对象
3.1 本地方法栈中的对象(本地变量表)
3.2 静态成员变量对象
3.3 常量变量对象
3.4 本地方法区中的对象,native对象
4
GC回收是进行分代回收的,分代,
我们将整个java堆内存分为三块
1
新生代 Young generation,内部继续划分为伊甸园 eden 区和两个存活区(survivor ,s0,s1 两个内存大小相等),
eden 和(s0+s1)的默认内存比例为9:1, 新生的对象都是放在eden区中的,当eden区中内存不够时,触发minor GC,
采用标记复制算法,将eden区中的对象copy到S0中,eden区中内存全部回收. 当eden中的内存又不够的时候,再次触发minor GC,
这时候将s0中尚存活的对象放到copy到s1 中,把s0回收,然后将eden区中的对象进行回收,放到s0中去,同时对s0,s1中对象记录时间轴,
达到阀值时,对象进入老年代中,当老年代中的内存不够时,将触发full gc,这将是非常耗性能的,应该避免,同时如果说创建的对象比较大,超过设定值,将直接进入老年代,避免新生代中进行频繁的copy操作
2
老年代 tenured generation ,存放对象年龄较老的,或者内存比较大的对象. 这块内存回收有多重算法.
CMS是其中一种.
3
永久代 permanent generation ,归属于方法区,方法区逻辑上是堆内存的一部分.
放的是常良池和字节码文件对象及类方法的元数据信息.虽然也会有垃圾回收,
但是回收的条件非常苛刻
1 对应类的实例对象全部被回收
2
加载该类的类加载器被回收
3 无法通过任何方式访问该类,(即使反射也不行)
这样我们就可以清楚的看到,当我们程序中大量的适应动态代理AOP等,在内存中动态生成的类的字节码对象,可能占用过多的
永久代内存,以及错误的使用+号连接过多的字符串内容,也会导致永久代内存溢出