什么是java程序中的垃圾?什么这些垃圾又是怎样被回收的?为什么会被回收?不进行回收又会怎样?这些问题都是我们要在这篇博客中要解决的问题!
大家都知道,在c语言中,作为程序员,必须得考虑到去怎样回收已经分配的内存,经常要面临的问题是,什么时候进行垃圾的回收,什么时候进行释放?释放过早了,那些仍然需要用到的对象资源消失了,面临的是系统的奔溃;但是一旦忘记回收无用的内存,就会导致内存的泄露,降低系统的性能。问题很大吧?很让人觉得恼火吧?但是在java编程时,不需要程序员进行一个显式的内存回收,因为jre已经帮我们做好了这些事情,从起初的内存的分配到那些没有被引用对象的回收,它都一首操控了,简直让人觉得很爽啊。jre会分配个自己的小的隶属——一个小的线程进行检测和控制,这个小的线程,一直在程序运行时,跟踪所有的对象的运行状况,特别是那些已经进行内存的分配,但是没有被引用的对象们,它会很灵活机智地把其在堆内存中所指向的数据区置为null,在cpu空闲或者内存不足时,进行一个垃圾的回收。内存占领它回收的空间,更为人性化的是,由于创建对象和垃圾回收器释放丢弃资源的的内存空间时,会出现碎片。这些碎片就是那些,没有被分配的空间,“比上不足,比下有余”的尴尬处境,jvm会将碎片进行收集和整理,将所占用的堆内存从堆的一端,移动到另外一端,jvm整理出的内存分配给新的对象。
简单介绍了,垃圾回收的机制,那么它有什么特点呢?回收没有用的对象的空间,这些空间都是虚拟机堆内存中的内存空间,它只能回收内存资源,对于外设,数据库资源,IO资源,它并不能发挥自己的作用;垃圾回收还是要具体情况,具体说明下的,在不同的虚拟机下,他们所采用的垃圾回收算法也不一定一样的,所以处理回收方式就可能从在一定的差异,有的可能是定时进行回收,有的也可能在cpu空闲时犯什么,甚至也有可能在cpu运行出现极限时,才进行垃圾的回收。
除此,我们在编写java程序时,对于不在需要的对象,不要去引用它们,如果你要保持对这些对象的引用,垃圾回收机制暂时不会回收这些对象,他们会觉得你可能在下个时刻会使用,所以会为你暂时保留,那这样的话,系统的可用的内存会越来越少,这样,垃圾回收机制会被调用的频率变高,系统的性能会降低。
在实际上,目前有几种常见的垃圾回收的算法。
第一种,引用计数法,引用计数法是唯一没有使用根集的垃圾回收的法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。
第二种,标记和清除垃圾收集器,引出根基的概念,从根集开始扫描,识别出那些对象可达和哪些对象不可达,对于不可达的对象,就进行垃圾的收集。
第三种,compacting算法
为了解决堆碎片问题,在清除的过程中,算法将所有的对象移到堆的一端,堆的另一端就变成了一个相邻的空闲内存区,收集器会对它移动的所有对象的所有引用进行更新,使得这些引用在新的位置能识别原来的对象。在基于Compacting算法的收集器的实现中,一般增加句柄和句柄表。
这里仅仅简单的介绍了三种具体的回收算法,回收算法也随着计算机的发展而不断进行改进和提高。
在具体的编程中,我们也可以向jvm提出强求,即调用方法system.gc().请求垃圾回收,但正如我所说的,仅仅是个请求,jvm在接受到消息时,还会根据垃圾回收算法进行一个加权,使得垃圾回收算法,容易发生,或者容易发生,并不代表,调用后,会直接进行垃圾的回收。对于其中的finalize()方法,该方法,是在真正去回收空间时要执行的的方法,该方法先进行“擦除”,再真正释放空间。