java垃圾回收策略_浅谈java中的垃圾回收策略(Garbage collector)

经常听网上或身边的朋友讨论java和C++到底谁更好,公说公有理,婆说婆有理。大多数对java有成见的人都抱怨java运行起来太慢了,必须把对象都放到heap中,不如c++那样把对象放到stack中,能够灵活的运用指针,从而运行效率要比java快的多。固然这有一定道理,可是java的对象分配策略真的像我们想象的那么差么,如果它这么糟糕的话,美国航天局的登月飞船程序为什么还要用java写呢?下面我就从java的垃圾回收策略写起吧,谈谈我对这一问题的看法。

a4c26d1e5885305701be709a3d33442f.png

在一些JVMs中,java堆是不一样的,它更像一个传送带,一旦新的对象创建,就把该对象放到传送带上,传送带向前移动。从这个特点我们可以看出这种存储分配的速度是相当快的。因为"堆指针"一直指向传送带上未分配的空间,这一原理很像C++中的“堆栈指针”。

但是我们必须清醒以上只是对java对象分配原理的比喻,实际上不可能是传送带式的,如果那样做了,将会产生分页问题(这对性能是个极大的挑战),最终导致内存不够用了。这时java的垃圾回收便挺身而出,起着至关重要的作用。因为它不像我们想象的那样简单地回收垃圾,而是把堆中的所有对象进行压缩以便减小发生缺页中断的可能性。垃圾回收器对堆空间重新分配,可以提供堆的使用效率。

下面我就来谈谈垃圾回收器如何回收对象。

通常JVMs使用自适应的垃圾回收策略。一种叫stop-and-copy方法,另一种叫mark-and-sweep方法。从方法的名字中我们可以很容易看出这些方法是如何工作的。

stop-and-copy方法

a4c26d1e5885305701be709a3d33442f.png

首先JVMS对heap中的所有对象进行遍历,找到所有仍处于生命周期的对象,然后jvm停下眼前的工作把这个对象copy到另一个堆中,其他没有生命的对象交给回收器处理了。这里我们要注意,copy到新堆中的对象并不是随便分配的,而是像我们在第三段提到的那样,采用压缩式分配,这样大大提高了处理效率。不过这种方法也有缺点,很明显你必须准备一个堆空间来存放对象的copy,如果copy空间很大的话,维护的效率就较低了。还有一个问题就是拷贝。假设堆中所有的对象都处于生命周期内,换句话说,几乎没有产生什么垃圾。这种情况下,copy工作并不会停止,仍然将对象从一个堆拷贝到另一个堆中,可想而知这相当费时费力啊!为了避免这种情况发生,一些JVMs采用mark-and-sweep方法,这种方法通常速度很慢,但是如果当你知道产生的垃圾很少时,上述方法还是很快的。

mark-and-sweep方法

a4c26d1e5885305701be709a3d33442f.png

这种方法与前面讲到的stop-and-copy方法类似,不过不同之处在于,每次当jvm发现一个活动对象时,就为这个对象设置一个标志位,但是并不回收它。只有当所有的标记工作完成之后,才进行清扫工作。清扫工作中,无用对象被释放。

从stop-and-copy方法和mark-and-sweep方法的特点我们可以看出,这两种方法各有千秋,正好可以做到互补。就是说如果堆中产生的“垃圾”比较多时,采用第一种方法;如果堆中产生的“垃圾”比较少时,采用第二种方法。即一种自适应的方法。

小结:

以上主要讲解了java垃圾回收器的基本工作原理,我们可以看出这一策略可以根据程序运行时的实际情况合理的选择垃圾回收机制。只有高效合理的回收机制作保证,才会有高效的内存分配效率。试想我们生活的城市,如果没有城市清洁工们的辛勤劳动,我们不可能享受这美好、轻松、愉快的生活。从这一点上说,java的运行效率并不像人们原来想象的那么糟糕,相反它为人们考虑了更多的事情,优化了内存分配、节省了开发人员的宝贵时间、确保了系统的安全性和可靠性,从这方面讲,它真的值得我们认真学习啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值