JVM学习之路(十三)——java代码编写过程中的“内存优化”技巧

十三、java代码编写过程中的“内存优化”技巧

众所周知,Java是从C++的基础上发展而来的,而C++程序的很大的一个问题就是内存泄露难以解决,尽管Java的JVM有一套自己的垃圾回收机制来回收内存,在许多情况下并不需要java开发人员操太多的心,但也存在内存泄露问题的,只是比C++小一点。举个很简单的例子,程序中存在被引用但无用的对象:程序引用了该对象,但后续不会或者不能再使用它,那么它占用的内存空间就浪费了

我们先来看看GC是如何工作的:监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,当该对象不再被引用时,释放对象。但是,很多Java程序员过分依赖GC,但问题的关键是,无论JVM的垃圾回收机制做得多好,内存总归是有限的资源,因此就算GC会为我们完成大部分的垃圾回收,但适当地注意编码过程中的内存优化还是很必要的。这样可以有效的减少GC次数,同时提升内存利用率,最大限度地提高程序的效率。

优化程序代码:

1、不要显式调用System.gc(),即:尽量避免强制系统做垃圾回收。此函数建议JVM进行主GC,虽然只是建议而非一定,但很多情况下它会触发主GC,从而增加主GC的频率,也即增加了间歇性停顿的次数,大大的影响系统性能。

2、尽量减少临时对象的使用。临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,也就减少了主GC的机会。

3、对象不用时,最好显式置为Null。一般而言,为Null的对象都会被作为垃圾处理,所以将不用的对象显式地设为Null,有利于GC收集器判定垃圾,从而提高了GC的效率。

4、尽量使用StringBuffer,而不用String来累加字符串。由于String是固定长的字符串对象,累加String对象时,并非在一个String对象中扩增,而是重新创建新的String对象。如Str5=Str1+Str2+Str3+Str4,这条语句执行过程中会产生多个垃圾对象,因为每次“+”操作时都必须创建新的String对象,但这些过渡对象对系统来说是没有实际意义的,只会增加更多的垃圾。避免这种情况可以改用StringBuffer来累加字符串,因StringBuffer是可变长的,它在原有基础上进行扩增,不会产生中间对象。

5、能用基本类型如Int、long,就不用Integer、Long对象。基本类型变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好使用基本类型变量。

6、尽量少用静态对象变量。静态变量属于全局变量,不会被GC回收,它们会一直占用内存。

7、分散对象创建或删除的时间。集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM在面临这种情况时,只能进行主GC,以回收内存或整合内存碎片,从而增加主GC的频率。集中删除对象,道理也是一样的,它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主GC的机会。

8、谨慎使用集合数据类型,如数组,树,图,链表等数据结构,这些数据结构对GC来说回收更复杂。

9、避免显式申请数组空间,不得不显式申请时,尽量准确估计其合理值

10、尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费

11、做远程方法调用类应用开发时,尽量使用瞬间值变量,除非远程调用端需要获取该瞬间值变量的值。

12、尽量在合适的场景下使用对象池技术以提高系统性能

总体而言,Java虚拟机的内存优化应从两方面着手:Java虚拟机和Java应用程序。前者指根据应用程序的设计,通过虚拟机参数控制虚拟机逻辑内存分区的大小,以使虚拟机的内存与程序对内存的需求相得益彰;后者指优化程序算法,降低GC负担,提高GC回收成功率。

猜你喜欢

转载自blog.csdn.net/u012556994/article/details/81276141
今日推荐