初识JVM(待填)
垃圾收集机制
哪些内存需要回收?
- 堆和方法区的内存需要回收,其余的不需要回收。
因为只有堆和方法区是线程共享的,其余的是与线程“同生共死”的,线程结束,内存自然就跟着回收了,所以不用管它们。
什么时候回收?
堆中
- 回收没有被引用的对象,也就是死亡的对象,如何判断对象是否死亡,有两种方法。
引用计数算法
- 给对象添加一个引用计数器,每当有一个地方引用它时,计数器的值就+1,当引用失效时,计数器的值就-1,当计数器的值为0时,代表此对象已不被引用,也就是“可以死了”。有一个弊端,若两个对象互相引用,则无法进行回收。
可达性分析
- 所有生成的对象都是一个称为“GC Roots”的根的子树。从GC Roots开始向下搜索,搜索所经过的路径称为引用链。当一个对象到GC Roots没有任何引用链可以到达时,就称这个对象是不可达的,也就是可以被GC回收了。这个是Java中采用较多的方式。
怎么判断一个对象是否还存在着引用?java中的引用分为4种:
- 强引用:Object o=new Object(),只要强引用存在,GC永远不会回收掉被引用的对象。
- 软引用:描述一些还有用但非必需的对象。当系统即将发生内存溢出了,就会对其进行回收。
- 弱引用:只要进行GC,就会对其进行回收。
- 虚引用:这是最弱的一种引用关系,无法通过虚引用来取得一个对象实例。它的作用是:能在这个对象被收集器回收时收到一个系统通知。
方法区中
- 方法区里存储的是已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。所以我们在方法区里面进行垃圾回收,回收的是一些废弃的常量和无用的类。
如何判断一个常量是否被废弃了?
- 看引用计数就可以,如果没有对象引用该常量,则说明此常量被废弃了,也就可以回收了。
怎么判断一个类是无用的类?
- 怎么判断一个类是无用的类?有如下三种情况
- 该类所有的实例都已经被回收。
- 加载该类的ClassLoader已经被回收。
- 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
如何回收?
有4种算法作为理论:
标记-清除算法
- 定义:先标记,再清除。先开始对存活的对象进行标记,然后将没有被标记的对象进行回收。
- 特点:会产生大量的碎片
复制算法
- 定义:把内存分为2个空间:A和B,一个用来负责装载正常的对象信息,一个用来做垃圾回收。每次把A中存活的对象全部复制到B里面,再一次性的将A删除。
其中,伊甸区和幸存0、1区的比例是:8:1:1。 - 特点:没有碎片问题,但是内存缩小为了原来的一半。适用于新生代的回收。
标记-整理算法
- 定义:前面两者的综合,先标记、清除完,然后将存活的对象移动到内存的一端。
- 特点:成本较高,但是解决了碎片问题。适用于老年代的回收。
分代收集算法
- 分代收集算法是现在的jvm采用的算法。根据对象的存活周期的不同而将内存分为几块,分别为新生代、老年代和永久代。