上篇文章介绍了jvm运行时候对象进入老年代的场景,以及如何避免频繁fullGC。
Jvm参数设置-JVM(八)
- 老年代分配担保机制
这个机制的目的是为了提升效率,在minorGC之前,会有三次判断,之后再次minorGC速度会很快。
- 老年代剩余空间是否 大于 年轻代里现在所有对象
大于的话则直接minorGC
- 如果不大于则看看参数是否配置:-XX:-HandlerPromotionFailure
没有配置则直接fullGC
- 配置了则看看 老年代剩余可用空间是否 大于 每次minorGC后进入老年代的平均值
大于的话直接minorGC,否则直接fullGC
FullGC之后最后还是会minorGC。
- 对象内存回收
- 引用计数器
这个方法简单效率高,但目前主流虚拟机没有用表格这个算法,主要不能解决循环引用问题。因为两者相互引用,导致他们引用计数器不为0,而引用计数器必须是为0才会回收。
- 可达性分析算法
将GC roots对象作为节点,向下搜索,找到对象都标记为 非垃圾对象,其余未标记的都是 垃圾对象。
GC roots根节点,:线程栈本地变量,静态变量,本地方法栈变量等。
- 常见引用类型
引用类型:强引用,软引用,弱引用,虚引用
- 强引用:User user = new User();
- 软引用:用SoftReference软引用类型包裹对象, 正常不会被回收,但GC做完释放不出空间放新对象,则会回收。软引用可以作用在内存敏感的高速缓存。
SoftReference<User> user = new SoftReference<User>(new User());
软引用在实际场景很重要,例如浏览器后退按钮,这个后退是重新加载还是从缓存里取,这要看实际应用场景。
- 如果一个浏览器进入新页面就内容回收,则需要重新加载。
- 如果浏览页面内存很大,放在内存会内存溢出。
- 弱引用GC每次会直接回收。
WeakReference<User> user = new WeakReference<User>(new User());
- 虚引用也成为幽灵引用,几乎不用。
- finalize()方法最终判断对象是否存活
当对象背回收之前,会判断这个对象是否覆盖了finalize方法,如果覆盖了,在回收之前则会执行这个方法,不回收则不执行。
既然在回收之前会执行,那么自然可以自救,可以把当前对象放入静态list集合保证在使用则不会被收回。(不推荐使用)
- 如何判断一个类是无用的类
方法区如果发生回收的条件,必须这个类是无用的类:
- 该类所有对象实例都被回收,也就是java堆中不存在该类任何实例。
- 加载该类的ClassLoader已经被回收。(CLassLoader回收条件很苛刻)
前面说过引导类(核心包)BootStrapClassLoader,扩展ClassLoader以及appClassLoader应用程序的classLoader,这些不会被回收。
但是jsp的加载器,每个jsp都对应一个新的加载器,这种加载器就很容易被回收。(一般自定义的才会回收)
- 该类的java.lang.Class对象没有地方被引用,无法在任何地方通过反射访问该类信息。