一、如何判定垃圾对象有两种方式:
第一种:引用计数器法
概念:就是通过判断一个对象被引用的数量来判断这个对象是否可以被回收。给对象添加一个引用计数器,被引用一次就加1,被取消一次就减1,无论任何时候,只要这个对象的引用数量是0就会被判定为垃圾对象。
优点:算法简单
缺点:额外的引入计数器,浪费资源
第二种:可达性分析法
概念:就是从GCRoot对象开始寻找引用,经过两次标记还没有可达,就会被标记为垃圾对象。
GCRoot对象有哪些?
①java栈中的引用对象
②Native方法区中的引用对象
③方法区的普通的引用常量
④方法区的静态的引用常量
四种引用?
①强应用:new User()就是强引用
②软引用:new SoftReference(new User()) 就是软引用 一旦发生OOM会被回收
③弱引用:new WeakReference(new User())就是弱引用 一旦发生GC会被回收
④虚引用:new Phanton(new User())就是虚引用
二、如何回收垃圾
1 复制算法
概念:就是把内存一分为二,我们平时只是其中一个,如果新创建的对象放不下,就会把存活的对象放入另外一般内存,清空之前的那个内存。
优点:①算法简单②数据量不大的时候比较高效
缺点:①浪费内存②对象存活率比较高的情况下,需要复制大量的对象,并且还要重置指针,效率其实不高。
2标记清除算法:
第一步:标记阶段。遍历所有的对象标记出存活对象和垃圾对象
第二步:删除阶段。遍历所有的对象删除所有的垃圾对象
优点:效率相对较高
缺点:2次遍历,效率实际并不高
3标记整理算法:
第一步:标记阶段。遍历所有的对象标记出存活对象和垃圾对象
第二步:整理阶段。遍历所有的对象,把存活的对象向一端移动
优点:避免内存碎片
缺点:效率很低
4分带回收算法:
实际上:
频繁回收年轻代;较少回收老年代;基本不动永久代
效率上:复制算法>标记清除>标记整理
内存利用率:标记整理> 标记清除>复制算法
内存连续度:标记整理 > 复制算法 > 标记清除
所以JVM扬长避短:
年轻代:对象存活率不高,频繁的垃圾回收,使用“复制算法”
老年代:对象存活率相对较高,使用“标记清除”或者“标记整理算法”