垃圾收集器?
如何判定对象已死?
方法1:引用计数法,给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就会加1,当引用失效时就会减1,任何时刻计数器为o的对象就是不可用的。存在的问题是:对象之间循环相互引用的问题
方法2:可达性分析算法,通过一系列的称为“GC ROOTs”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径,当一个对象到GC Roots没有任何引用链相连接时,则证明此对象不可用。GC Roots的对象包含以下几种:虚拟机栈中引用的对象、方法区中静态属性引用的对象,方法区中常量引用的对象,本地方法栈中引用的对象。
JAVA中的引用类型有几种?
强引用(Strong reference):new出来的引用就叫强引用,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象。 软引用(Soft Reference):描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统中将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。 弱引用(Weak Reference):用来描述非必需的对象,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。 虚引用(Phantom Reference):一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被垃圾收集器回收时收到一个通知。
当一个对象是不可达的对象,垃圾回收的过程分为两次标记?
方法区的垃圾回收?
在堆内存中,尤其是在新生代中,常规应用一次垃圾收集一般可以回收70%-95%的空间,而永久代的垃圾收集效率远低于此,永久代的垃圾收集分为两部分:废弃常量和无用的类。
如何判定一个类是无用的类?
1.该类所有的实例都已经被回收;2.加载类的CLassLoader已经被回收;3.该类对应的java.lang.Class对象没有在任何地方被引用,无法通过反射来访问到该类。
内存分配策略?
对象的内存分配,大方向上讲,就是在堆上分配,对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,讲按线程优先在TLAB上分配。少数情况下也可能会直接分配在老年代中。
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC.
新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为JAVA对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度比较快。
老年代GC(Full GC ):指发生在老年代的GC,出现了Full GC,经常会伴随至少一次Minor GC。
大对象直接进入老年代,所谓大对象是指,需要大量连续内存空间的JAVA对象,最典型的就是那种很长的字符串以及数组。这样做的目的是避免在Eden区以及两个Survivor区之间发生大量的内存复制。
长期存活的对象将进入老年代,虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过一次MGC后仍然存活,并且被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。对象在Survivor区中每熬过一次MGC,年龄就增加1,当他的年龄增加到一定程度(默认为15),就将会晋升到老年代中。
为了更好的适应不同程序的内存情况,虚拟机并不是永远地要求对象的年龄必须达到最大年龄才能晋升到老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,就可以直接进入老年代。
空间分配担保:
1.在发生MGC之前,虚拟机会先检查老年代最大可用连续空间是否大于新生代所有对象总空间。如果这个条件成立,则MGC可以确保是安全的。
2.如果条件不成立,则虚拟机回去检查是否设置了允许担保失败,如果允许,那么会继续检查老年代连续空间大小是否大于历次的copy的平均值,如果大于,将尝试进行一次MGC。
3.如果如果不允许担保失败或者小于经验值,则直接进行Full GC。