Java内存管理的技巧

掌握Java的内存回收、垃圾回收机制是为了更好地管理Java虚拟机内存,这样能够好的提高Java程序的运行效率。下面总结几个内存管理的小技巧,希望时刻提醒自己的编程习惯。

1、避免在经常调用的方法、循环中创建Java对象

先看下面代码:

public class test2 {
	public static void main(String[] args) {
		List<String> list1 = new ArrayList<String>();
		//此处略去list1的初始化过程......
		List<String> list2 = new ArrayList<String>();
		for (String src : list1) {
			String str = src;
			list2.add(str);
		}
		//此处略去后续操作
	}
}
从上面的代码中可以看到,循环多少次就创建多少个str对象。虽然str对象是局部的,当循环执行结束str会自动被回收,但是这会导致两点不足:

1)java内存紧张,在循环还没有退出的时候就抛出java.lang.OutOfMemoryError: Java heap space ,即java内存溢出。

2)str对象生命周期非常短,循环退出之后GC会自动回收str对象们所占用的内存空间,这种不断的分配、回收操作中,程序性能受到巨大的影响。

建议:尽量不要在循环内创建java对象。

2、尽量使用直接量

当使用字符串,或者包装类(如Byte,Integer,Long,Boolean等)的实例时候,程序不应该用new的方式创建对象,最好采用直接量来创建它们。例如:

String str="hello";
这种方式会创建“hello”字符串,而且JVM的常量缓存池会缓存这个字符串。

如果程序使用如下代码:

String str=new String("hello");
此时,程序创建了一个“hello”字符串,除此之外,str所引用的对象的底层还包含了一个cha[]数组,依次存放了h、e、l、l、o字符。

但是,应该注意,当str经常地变化时候,应该避免使用,因为常量池中缓存的字符串失去引用后不会被GC回收。
3、使用StringBuilder和StringBuffer进行字符串的连接

String,StringBuilder,StringBuffer都代表字符串,但是String代表的字符串序列是不可变的,而后两者是可变的。

如果程序需要使用多个String对象进行字符串连接操作,在运行时候会产生大量的临时字符串,这些字符串保存在内存中不被回收,从而导致程序性能下降。例如:

String str="hello";//此处生成一个"hello"对象存在常量池中
str+=" world";//此处又重新生成了"hello world"这个新对象存在常量池中,上面的"hello"失去引用,但在常量池中不会被回收

而StringBuilder和StringBuffer由于是可变的,都是在当前字符串基础上修改,因此不会生成大量无用的中间量。

4、尽量少用静态变量

GC在进行垃圾回收的时候判断一个对象是否是垃圾的唯一标准就是该对象是否有引用变量引用它,因此推荐尽量早的释放对象的引用。但是static变量恰恰是最坏的情况,静态变量属于整个类,它的生命周期与类相同,因此在类不卸载的情况下,静态变量就会常驻内存,直至程序运行结束。

5、尽量早的释放无用对象的引用

如果在某对象obj之后执行耗时,耗内存的操作,而且对象obj已经不会使用,那么尽量在耗时,耗内存的操作之前就将obj置空(obj=null;),这样可能的情况就是:当程序在执行耗时耗内存的操作时,GC会对obj所引用的对象进行垃圾回收。

6、缓存经常使用到的对象

如果有些对象经常被使用到,可以考虑把这些对象用缓存池保存起来,这样下次使用的时候就可以直接从缓存池中拿出来用。典型的应用就是数据连接池,数据连接池中缓存了大量的数据连接,每次程序访问数据库时候都可以直接取出这些数据库连接。实现缓存通常有两种方式:

1)使用HashMap进行缓存。

2)直接使用某些开源的缓存项目。这些缓存项目的大体原理就是:主动分配一个一定大小的缓存容器,再按照一定的淘汰算法淘汰掉容器中很久不用的对象。后续博文会介绍spring的缓存管理。

7、考虑使用SoftReference

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

SoftReference<String> sr = new SoftReference<String>("hello");// 此处初始化一个软连接,其实接收的是String对象
System.out.println(sr.get());// 得到string对象只需要用到SoftReference的get方法即可


未完待续......







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值