GC优化――对象复用(二)

2014-11-24 03:29:13 · 作者: · 浏览: 4
复用对象的方式就不会浪费这么多空间。下面的代码,只是用一个Employee对象,每次不是new,而是使用setter方法设置值:
NewTest.java:通过静态变量employee每次set对象的值模拟复用,而不是new新对象。实际应用中可以使用对象池,比如commans-pool。

[java]
class NewTest{
private static Random rand = new Random();

private static Employee employee = new Employee("", 0, 0);

// get a employee
public static Employee getEmployee(){
int age = rand.nextInt(100);
double salary = 1000.0 + rand.nextDouble() * 10000;
// generate name: 3-5 characters
int nameLen = 3 + rand.nextInt(3);
StringBuilder nameBuilder = new StringBuilder();
for(int i=0; i nameBuilder.append((char)('a' + rand.nextInt(26)));

}
employee.setAge(age);
employee.setName(nameBuilder.toString());
employee.setSalary(salary);
return employee;
}
}
用相同的命令运行程序,观察gc:
[plain]
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
28.0 128.0 64.0 0.0 6528.0 0.0 13696.0 232.1 21248.0 2991.4 4714 0.847 0 0.000 0.847
可以看到young gc的次数是4714,减少了1135次,整个的gc时间从1.251-0.847,减少了0.4s(优化的力度比较小啊,这是因为Hotspot JVM的新生代采用复制算法,每次只复制那些活对象。而这个例子中每次gc时,大部分对象都是垃圾对象,所以说每次gc的只复制很少的对象,复制成本很低。但是在实际的程序中,因为程序运行的状态更加复杂,不会存在这种情况)。再通过jmap观察对象的分布,看到堆上只有一个Employee对象。这里用到了随机函数,可能会对测算结果的有一些影响,但是young gc次数减少是必然的。在编写程序时,可以对那些传递数据的对象采用复用对象的方式优化gc,这里复用的方式可以采用对象池。在orm中,通过数据库查询返回POJO对象时就是一个很好的利用场景。还有通过JSON数据实例化对象的情况。
总之,JVM的自动内存管理很方便,使程序员有更多的精力关注于业务逻辑。但是,要更加高效的运行程序,编程时还是有很多细节需要处理的。其中,复用对象就是一个。

摘自 chosen0ne的专栏