1、判断对象的存活
1、引用计数
原理:给一个对象添加一个引用计数器,每当一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器为0的对象就是不可再被使用的;
优点:效率高;
缺点:很难解决对象间的循环引用;
2、可达性分析
原理:通过一系列称为“GC Roots”的对象作为起点向下开始搜索,搜索走过的路径称为引用链,当一个对象到“GC Roots”没有任何引用链时(不可达),则该对象是不可用的;
可作为“GC Roots”的对象:1、虚拟机栈中引用的对象;2、方法区中“静态属性、常量”引用的对象;3、本地方法中引用的对象;
3、各种引用
强引用
软引用:对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收,如果第二次回收后还没有足够内存,才会抛出内存溢出异常;
弱引用:弱引用关联的对象,只能生存到下一次垃圾收集发生之前。下一次垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象;
虚引用:没有其他影响;为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
4、至少两次标记才会宣告对象死亡
第一次标记:是否与“GC Root相连”以及是否有必要执行finalize方法;
第二次标记:在F-Queue中;
注意:对象的finalize方法只能被调用一次,可以在finalize方法中实现对象自救;
5、回收方法区的性价比低
方法区主要的垃圾:废弃常量和无用的类;
描述无用的类需要同时满足这三个条件:1、该类所有实例已经被回收(堆中无该类的实例);2、加载该类的ClassLoader已经被回收;3、该类的java.lang.Class对象都没有在任何地方被引用,无法在任何地方通过反射访问该类的方法;
内存溢出与内存泄露
内存溢出:是指不能申请到足够的内存进行使用,就会发生内存溢出;
内存泄漏:内存泄露是指在程序中已经动态分配的堆内存由于某种原因未释放或者无法释放(已经没有用处了,但是没有释放),造成系统内存的浪费,这种现象叫“内存泄露”。
当内存泄露到达一定规模后,造成系统能申请的内存较少,甚至无法申请内存,最终导致内存溢出,所以内存泄露是导致内存溢出的一个原因。