垃圾清理势在必行——java垃圾收集算法

垃圾清理势在必行——java垃圾收集算法,第1张

垃圾清理势在必行——java垃圾收集算法,第2张

1.垃圾收集算法的核心思想。

Java语言建立了垃圾收集机制,跟踪使用中的对象,发现并回收不再使用(引用)的对象。该机制可以有效防止动态内存分配中可能出现的两种危险:内存垃圾过多导致的内存耗尽和内存释放不当导致的非法内存引用。

垃圾收集算法的核心思想是识别虚拟机可用内存空中的对象,也就是堆空中的对象。如果对象正在被引用,则称为活对象;否则,如果该对象不再被引用,它就是一个垃圾对象,被占用的空空间可以被回收重新分配。垃圾收集算法的选择和垃圾收集系统参数的合理调整直接影响系统性能,开发者需要对此有更多的了解。

2.触发主垃圾收集器的条件

JVM进行子GC的频率很高,但这种GC耗时很短,所以对系统影响不大。更值得关注的是主GC的触发条件,因为它对系统的影响很明显。一般来说,有两种情况会触发主GC:

①当应用空空闲时,即没有应用线程运行时,将调用GC。因为GC是在优先级最低的线程中执行的,所以当应用程序繁忙时,将不会调用GC线程,以下情况除外。

②Java堆内存不足时会调用GC。当应用线程正在运行,并且在运行过程中创建了一个新的对象时,如果此时内存不足空,JVM会强制调用GC线程来回收内存进行新的分配。如果一次后GC不能满足内存分配的要求,JVM将再进行两次GC尝试。如果仍然不能满足要求,JVM将报告“内存不足”错误,Java应用程序将停止。

由于JVM是根据系统环境来决定是否进行主GC的,而系统环境是不断变化的,主GC的运行是不确定的,无法预测何时必然出现,但可以肯定的是,对于一个长时间运行的应用,主GC是重复的。

3.降低GC开销的措施

根据GC的上述机制,程序的运行会直接影响系统环境的变化,从而影响GC的触发。如果不根据GC的特点对其进行设计和编码,就会产生记忆保留等一系列负面影响。为了避免这些影响,基本原则是尽量减少垃圾,减少GC过程中的开销。具体措施包括以下几个方面:

(1)不要显式调用System.gc()

这个函数建议JVM执行主要的GC。虽然只是建议但不一定,很多情况下会触发主GC,从而增加主GC的频率,也就是增加间歇停顿的次数。

(2)尽量减少临时物件的使用

临时对象跳出函数调用后,就会变成垃圾。使用较少的临时变量相当于减少了垃圾的产生,从而延长了上述第二个触发条件的发生时间,减少了主GC的机会。

(3)对象在不使用时被显式设置为Null。

一般来说,Null对象会被当作垃圾处理,所以显式地将未使用的对象设置为Null有利于GC收集器判断垃圾,从而提高GC的效率。

(4)尽量用StringBuffer代替String来积累字符串(详见另一篇博客文章《JAVA中的String和StringBuffer》)

因为String是一个定长的String对象,所以在累加String对象时,不是在一个String对象中展开,而是创建一个新的String对象,比如Str5=Str1+Str2+Str3+Str4。在这个语句的执行过程中,会产生很多垃圾对象,因为“+”操作时必须创建新的字符串对象,但是这些过渡对象对系统没有实际意义,只会增加更多的垃圾。为了避免这种情况,我们可以使用StringBuffer来累积字符串,因为StringBuffer的长度是可变的,是在原来的基础上放大的,不会产生中间对象。

(5)如果能使用int、long等基本类型,就不需要Integer、Long long对象了。

基本变量占用的内存资源比对应对象占用的少得多。如果没有必要,使用基本变量。

(6)尽量少用静态对象变量。

静态变量是全局变量,不会被GC回收。它们会一直占据内存。

(7)创建或删除分散对象的时间

短时间内创建大量新对象,尤其是大型对象,会导致突然需要大量内存。面对这种情况,JVM只能进行主GC来回收内存或者合并内存碎片,从而增加主GC的频率。删除集中式对象也是如此。它使得大量垃圾对象突然出现,并且空 idle 空之间的时间必然减少,从而大大增加了下次创建新对象时强制主GC的几率。

4.gc和finalize方法

(1) GC方法请求垃圾收集。

使用System.gc()可以请求Java垃圾收集,而不管JVM使用哪种垃圾收集算法。注意,调用System.gc()只是一个请求。JVM在收到这个消息后,并没有立即进行垃圾收集,只是对几种垃圾收集算法进行了加权,使得垃圾收集操作容易发生,或者发生得更早,或者收集得更多。

⑵完成方法,看穿垃圾收集器的操作。

在JVM垃圾收集器收集对象之前,程序通常需要调用适当的方法来释放资源。但是,当资源没有被显式释放时,Java提供了一种默认机制来终止对象以释放资源。这个方法是finalize()。它的原型是:

受保护的void finalize()抛出Throwable

finalize()方法返回后,对象消失,垃圾收集开始。原型中的Throwable意味着它可以抛出任何类型的异常。

所以,当对象即将被销毁时,有时需要做一些善后工作。您可以在finalize()方法中编写这些操作。

以下是引用的片段:
protected void finalize()
{
//此处为终结代码
}

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 垃圾清理势在必行——java垃圾收集算法

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情