首页 > 代码库 > java内存回收提高性能

java内存回收提高性能

这是本人的第二篇文章。通过上一篇文章的总结后,我觉得有必要对java内存回收问题再详细叙述一下。因为大多数javaer估计都是习惯了自己的java编码风格,尤其是对象声明等,想在哪声明就在哪声明,之后就不管了,因为他知道java有一个很好的内存管理机制,那就是GC(垃圾回收机制)。其实这对一般的java程序猿来说这是无可厚非的。呵呵。。。因为我也是这样过来的。然而,随着接触的项目庞大和性能的要求,我们开始审视自己写的代码,看看有没有一些代码需要优化,或者其他编码风格需要改变从而对系统的性能提升有所帮助呢。答案是肯定的。接下来我就详细叙述一下我在平时的项目接触和网上看到对自己有帮助的方法。希望对大家有所帮助。

(1)尽量使用直接量
  当需要使用字符串,还有Byte,Short,Integer,Long,Float,Double,Boolean,Charater包装类的实例时,程序不应该采用new的方式来创建对象,而应该直接采用直接量来创建它们。
例如,程序需要"hello"字符串,应该采用如下代码String str="hello"‘
上面这种方式创建一个"hello"字符串,而且JVM的字符串缓存池还会缓存这个字符串。但如果程序采用String str=newString("hello"); 此时程序同样创建了一个缓存在字符串缓存池中的"hello"字符串。除此之外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组里依次存放了h,e,l,l.o等字符串。

(2)使用StringBuffer和StringBuilder进行字符串拼接

如果程序中采用多个String对象进行字符串连接运算,在运行时将生成大量临时字符串,这些字符串会保存在内存中从而导致程序性能下降。

3)尽早释放无用对象的引用
  大部分时候,方法局部引用变量所引用的对象会随着方法结束而变成垃圾,因为局部变量的生存周期很短,当方法运行结束之时,该方法内的局部变量就结束了生命周期。因此,大部分时候程序无需将局部引用变量显工设为null.
但是下面程序中的情形则需显式设为null比较好了

public void info()
{
    Object obj=new Objec();
    System.out.println(obj.toString());
    System.out.println(obj.toString());
    obj=null;
    //执行耗时,耗内存的操作
    //或者调用耗时,耗内存的操作的方法
  }

  对于上面程序所示的info()方法,如果需要“执行耗时,耗内存的操作”或者"或者调用耗时,耗内存的操作的方法",那么上面程序中显式设置obj=null就是有必要的了。可能的情况是:当程序在“执行耗时,耗内存的操作”或者"或者调用耗时,耗内存的操作的方法",obj之前所引用的对象可能被垃圾回收了。 

(4)尽量少用静态变量
  从理论来说,Java对象何时被回收由垃圾回收机制决定,对程序员来说是不确定的。由于垃圾回收机制判断一个对象是否是垃圾的唯一标准就是该对象是否有引用变量引用它,因此要尽早释放对象的引用。
  最坏的情况是某个对象被static变量所引用,那么垃圾回收机制通常是不会回收这个对象所占用的内存的。

Class Person
{
    static Object obj=new Object();
}
  对于上面的Object对象而言,只要obj变量还引用它,就会不会被垃圾回收机制所回收Person类所对应的Class对象会常驻内存,直到程序结束,因此obj所引用的Object对象一旦被创建,也会常驻内存,直到程序运行结束。

(5)避免在经常调用的方法,循环中创建Java对象

public class Test
{
    public static void main(String[] args)
    {
        for(int i=0;i<10;i++)
        {
            Objectobj=new Object();
            //执行其它操作...
        }
    }
}

  上面物循环产生了10个对象,系统要不断地为这些对象分配内存空间,执行初始化操作。它们的生存时间并不长,接下来系统又需要回收它们所占用的内存空间是,这种不断分配内存,回收操作中,程序的性能受到了很大的影响。

(6)缓存经常使用的对象
  如果有些对象需要经常使用,可以考虑把这些对象用缓存池保存起来,这样下次需要时就可直接拿出来这些对象来用。典型的缓存谅是数据连接池,数据连接池里缓存了大量的数据库连接,每次程序需要访问数据库时都可直接取出数据库连接。
  除此之外,如果系统里还有一些常用的基础信息,比如信息化信息里包含的员工信息,物料信息等,也可以考虑对它们进行缓存。
使用缓存通常有两种方法
1.使用HashMap进行缓存
2.直接使用开源缓存项目。(如OSCache,Ehcahe等)

(7)尽量不要用finalize方法
  在一个对象失去引用之后,垃圾回收器准备回收该对象之前,垃圾回收器会先调用对象的finalize()方法来执行资源清理。出于这种考虑,可能有些开发者会考虑使用finalize()方法来进和清理。
在垃圾回收器本身已经严重制约应用程序性能的情况下,如果再选择使用finalize方法进行资源清理,无疑是一种火上浇油的行为,这将导致垃圾回收器的负担更大,导致程序运行效率更低

(8)考虑使用SoftReference软引用
  当程序需要创建长度很大的数组是,可以考虑使用SoftReference来包装数组元素,而不是直接让数组元素来引用对象。

SoftReference是一个很好的选择:当内存足够时,它的功能等同于普通引用;当内存不够时,它会牺牲自己,释放软引用所引用的对象。

    经过以上的介绍,我们应该对Java的内存泄漏有了一定的认知了,如果我们在平时开发中,多关注Java内存管理方面的话是可以远离Java内存泄漏的,这样可以大大提高我们的代码强壮性、高效性。