目录
垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
内存溢出异常
Java会存在内存泄漏吗?请简单描述
内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。理论上来说,Java是有GC垃圾回收机制的。也就是说,不再被使用的对象,会被GC自动回收掉,自动从内存中清除。
但是,即使这样,Java也还是存在着内存泄漏的情况,Java导致内存泄漏的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏。尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是Java中内存泄漏的发生场景。
垃圾收集器
简述Java垃圾回收机制
在Java中,程序员是不需要显式的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中有一个垃圾回收线程。它是低优先级的,在正常情况下是不会执行的。只有在虚拟机空闲或者当前堆内存不足时,才会触发执行。扫描那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。
GC是什么?为什么要GC
GC是垃圾收集的意思,内存处理是编程人员容易出错的地方。忘记或错误的内存回收会导致程序或系统的不稳定甚至崩溃。Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的。Java语言没有提供释放已分配内存的显式操作方法。
垃圾回收的优点和原理,并解释两种回收机制
Java语言最显著的特点就是引入了垃圾回收机制。它使Java程序员在编写程序时不再考虑内存管理的问题。
由于有这个垃圾回收机制,Java对象不再有“作用域”的概念,只有引用的对象才有作用域。
垃圾回收机制有效地防止了内存泄漏,可以有效的使用可使用的内存。
垃圾回收器通常作为一个单独的低级别的线程运行,在不可预知的情况下,堆内存堆中已经死亡的或长时间没有用过的对象进行清除和回收。
程序员不能实时的对某个对象或所有对象调用垃圾回收器进行垃圾回收。
垃圾回收有分代复制垃圾回收、标记垃圾回收、增量垃圾回收。
垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
通常,GC采用有向图的方式记录和管理堆中的所有对象。通过这种方式确定哪些对象是“可达的”,哪些对象是不可达的。当GC确定一些对象为不可达时,GC就有责任回收这些空间。
程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不一定保证GC一定会执行。
Java中都有哪些引用类型?
l 强引用:发生GC的时候不会被回收。
l 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。
l 弱引用:有用但不是必须的对象,在下一次GC的时候会被回收。
l 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用PhantomReference实现虚引用,虚引的用途是在GC时返回一个通知。
怎么判断对象是否可以被回收?
垃圾收集器在做垃圾回收的时候,首先需要判定的就是哪些内存是需要被回收的,哪些对象是存活的,是不可以被回收的;哪些对象已经死掉了,需要被回收。
一般有两种方法来判断:
l 引用计数法:为每个对象创建一个引用计数,有对象引用时计数器加1,引用被释放时计数器减1.当计数器为0的时候就可以被回收。他有一个缺点是不能解决循环引用的问题;
l 可达性分析算法:从GC roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是可以被回收的。
说一下JVM有哪些垃圾回收算法?
l 标记-清除算法:标记无用的对象,然后进行垃圾回收。缺点:效率不高,无法清除垃圾碎片。
l 复制算法:按照容量划分两个大小相同的内存区域,当一块用完的时候将活着的对象复制到另一块上。然后再把已经使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。
l 标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清掉边界以外的内存。
l 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代。新生代基本采用复制算法,老年代采用标记整理算法。
标记清除算法
标记清除算法是一种常见的基础垃圾收集算法,它将垃圾收集分为两个阶段:标记阶段(标记出可以回收的对象)和清除阶段(回收被标记的对象所占用的空间)。标记清除算法之所以是最基础的,是因为后面讲的垃圾收集算法都是在此算法的基础上进行改进的。
优点:实现简单,不需要对象进行移动。缺点:标记清除过程效率太低,产生大量不连续的内存碎片,提高了垃圾回收的频率。
标记清除算法的执行过程如下图所示:
复制算法
为了解决标记清除算法的效率不高的问题,产生了复制算法。它把内存空间分成两个相等的区域,每次只使用其中一个区域。垃圾收集时,遍历当前区域,把存活对象复制到另外一个区域中,最后将当前使用的区域的可回收对象进行回收。
优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片。
缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。
复制算法的执行过程如下图所示:
标记整理算法
在新生代中可以使用复制算法,但是在老年代就不能选择复制算法了,因为老年代的对象存活率会较高。这样会有较多的赋值操作,导致效率变低。标记清除算法可以应用在老年代中,但是它效率不高,在内存回收后容易产生大量内存碎片。因此就出现了一种标记整理算法,与标记清除算法不同的是,在标记可回收的对象后将所有存活的对象压缩到内存的一端,是他们紧凑的排列在一起,然后对端边界以外的内存进行回收。回收后,已用和未使用的内存都各自站一边。
优点:解决了标记清除算法存在的内存碎片问题。
缺点:仍需要进行局部对象移动,一定程度上降低了效率。
标记整理算法的执行过程如下图所示:
分代收集算法
当前商业虚拟机都采用分代收集的垃圾收集算法。分代收集算法,顾名思义是根据对象的存活周期将内存分为几块。一般包括年轻代、老年代和永久代。如图所示: