2008-02-27
Java 性能优化
关键字: java 性能优化之创建对象--新手容易出现的问题
1.Java 性能优化之创建对象
对于每个java程序员都知道怎样创建对象,但是你知道怎样创建才能提高应用的性能呢?
你知道创建对象的应用规则吗?
(1).要尽量避免在循环体中创建对象.
(2).尽量及时使对象符合垃圾回收标准.
(3).不要采用过深的继承层次.
(4).访问本地变量优于访问类中的变量.
例如:
Vector v=new Vector();
for(int i=0; i<100;i++){
Object obj=new Object();
}
这样的写法大家都不陌生吧。可是这样会浪费大量的内存空间。正确的方法如下。
Vector v=new Vector();
Object obj=null;
for(int i=0; i<100;i++){
obj=new Object();
}
这样内存中保存一个对象的引用,从而减少了浪费内存空间的情况。
还有:
不要对一个对象进行多次初始化。这样也会带来较大的内存开销,相抵系统性能。
public class Test(){
private HashMap map=new HashMap();
public Test(){
map=new HashMap()
}
}
以上的几点都好理解。可是有很多新手会出现上面的问题哦!!!!
对于每个java程序员都知道怎样创建对象,但是你知道怎样创建才能提高应用的性能呢?
你知道创建对象的应用规则吗?
(1).要尽量避免在循环体中创建对象.
(2).尽量及时使对象符合垃圾回收标准.
(3).不要采用过深的继承层次.
(4).访问本地变量优于访问类中的变量.
例如:
Vector v=new Vector();
for(int i=0; i<100;i++){
Object obj=new Object();
}
这样的写法大家都不陌生吧。可是这样会浪费大量的内存空间。正确的方法如下。
Vector v=new Vector();
Object obj=null;
for(int i=0; i<100;i++){
obj=new Object();
}
这样内存中保存一个对象的引用,从而减少了浪费内存空间的情况。
还有:
不要对一个对象进行多次初始化。这样也会带来较大的内存开销,相抵系统性能。
public class Test(){
private HashMap map=new HashMap();
public Test(){
map=new HashMap()
}
}
以上的几点都好理解。可是有很多新手会出现上面的问题哦!!!!
评论
b051
2008-02-28
关键还是垃圾回收机制。你把变量直接引用新实例,只是积极地告诉jvm去回收之前的实例。出了循环体,jvm一样知道需要回收的。其实很难讲具体的jvm和jvm参数下,这样做是否更好。
另一方面,原则上,循环中的变量会比外边的快,就好像方法里的变量会比类里的快,类里的会比全局的快,一个道理。只是太快了以至于看不出来而已。
另一方面,原则上,循环中的变量会比外边的快,就好像方法里的变量会比类里的快,类里的会比全局的快,一个道理。只是太快了以至于看不出来而已。
shikonglaike
2008-02-28
真的很高兴看到这么多同行的发言!
真对这个问题提我还想知道这两种方式。垃圾回收器对对象的回收相同吗。
真对这个问题提我还想知道这两种方式。垃圾回收器对对象的回收相同吗。
香克斯
2008-02-28
在没有实际测试之前不需要所谓的这种从写代码上面来进行的优化。只要你的代码写得够清晰,等出问题的时候回头优化也不晚。而且现在虚拟机的优化已经挺不错了,写程序是过于考虑这些也就是一种杞人忧天的行为
bigcatJavaEye
2008-02-28
LZ的第一条赞成。
尽量不要再loop里面new对象。
所举的例子可能不太符合提议。
1 loop中并没有减少对象的new,只是减少了引用的开销,而一个引用就几个字节。
2 楼上有人说了,现在的jvm已经可以优化了。
下面的例1可以看出来,系统只是在第一次创建很多引用,以后他就偷懒了。
例2进一步可以证明,如果内存中已经存在很多引用的话,他也会偷懒。
测试了一下。
例1
输出结果:
例2 提前放点引用到jvm
输出
尽量不要再loop里面new对象。
所举的例子可能不太符合提议。
1 loop中并没有减少对象的new,只是减少了引用的开销,而一个引用就几个字节。
2 楼上有人说了,现在的jvm已经可以优化了。
下面的例1可以看出来,系统只是在第一次创建很多引用,以后他就偷懒了。
例2进一步可以证明,如果内存中已经存在很多引用的话,他也会偷懒。
测试了一下。
例1
import java.util.Date;
class test{
public static Runtime rt = Runtime.getRuntime();
public static void main(String[] args){
for(int i=0;i<5;i++){
System.out.println("getUseredMemorySize1:" + getUseredMemorySize1());
System.out.println("getUseredMemorySize2:" + getUseredMemorySize2());
System.out.println("-------------------------------------------------");
}
}
public static Long getUseredMemorySize1(){
Long size = rt.freeMemory();
for(int i=0;i<1000;i++){
Date d = new Date();
}
return size - rt.freeMemory();
}
public static Long getUseredMemorySize2(){
Long size = rt.freeMemory();
Date d = null;
for(int i=0;i<1000;i++){
d = new Date();
}
return size - rt.freeMemory();
}
}
输出结果:
------------------------------------------------- getUseredMemorySize1:20784 getUseredMemorySize2:6312 ------------------------------------------------- getUseredMemorySize1:6096 getUseredMemorySize2:6000 ------------------------------------------------- getUseredMemorySize1:6096 getUseredMemorySize2:6000 -------------------------------------------------
例2 提前放点引用到jvm
public static void main(String[] args){
for(int i=0;i<1000;i++){
Date d = new Date();
d.setDate(2);
}
for(int i=0;i<5;i++){
System.out.println("getUseredMemorySize1:" + getUseredMemorySize1());
System.out.println("getUseredMemorySize2:" + getUseredMemorySize2());
System.out.println("-------------------------------------------------");
}
}
输出
------------------------------------------------- getUseredMemorySize1:6696 getUseredMemorySize2:6312 ------------------------------------------------- getUseredMemorySize1:6096 getUseredMemorySize2:6000 ------------------------------------------------- getUseredMemorySize1:6096 getUseredMemorySize2:6000 -------------------------------------------------
coder1982
2008-02-28
我个人的分析如下:
第一种模式:
Object 只是每次循环的时候声明了一次引用,但这个引用每次在程序执行到“}”的时候就没了,它是局部变量,等到循结束后,Object的任何对象都不会存在了。
第二种模式:
看似只声明了一次引用,其实有大大不妥。因为循环结束后,obj仍然还保留着对象。等到下次再执行到"}"时,其对象才会释放。当然,手动的话就再来一次obj=null;
综合来说,我觉得应该根据使用场景不同,来合理使用两种方法。优化代码不单单是减少创建对象,合理控制对象的生命周期和作用域,也是必要的考虑环节。
第一种模式:
Vector v=new Vector();
for(int i=0; i<100;i++){
Object obj=new Object();
}
Object 只是每次循环的时候声明了一次引用,但这个引用每次在程序执行到“}”的时候就没了,它是局部变量,等到循结束后,Object的任何对象都不会存在了。
第二种模式:
Vector v=new Vector();
Object obj=null;
for(int i=0; i<100;i++){
obj=new Object();
}
看似只声明了一次引用,其实有大大不妥。因为循环结束后,obj仍然还保留着对象。等到下次再执行到"}"时,其对象才会释放。当然,手动的话就再来一次obj=null;
综合来说,我觉得应该根据使用场景不同,来合理使用两种方法。优化代码不单单是减少创建对象,合理控制对象的生命周期和作用域,也是必要的考虑环节。
mllee
2008-02-28
movingboy 写道
有没有哪位能用测试数据说话?
试试看,一样的。
但像楼上所说,变量声明在块里面可以把变量作用域限制得更小,所以还是声明在里面好。
也赞成之前的说法,在前面再加一行 Object obj = null 不美观。
public class Test
{
public static class A
{
private byte[] memoryBlock = new byte[5 * 1024 * 1024];
}
public static void main(String[] args) throws Exception
{
final int LOOP_COUNT = 20;
final long SLEEP_MILLIS = 3000;
System.out.println("please open windows task manager and monitor the memory usage...");
Thread.sleep(SLEEP_MILLIS);
System.out.println("variable in for loop...");
for (int i = 0; i < LOOP_COUNT; ++i)
{
A a1 = new A();
}
Thread.sleep(SLEEP_MILLIS);
System.out.println("variable out of for loop...");
A a2 = null;
for (int i = 0; i < LOOP_COUNT; ++i)
{
a2 = new A();
}
Thread.sleep(SLEEP_MILLIS);
System.out.println("exit!");
}
}
vchengyun
2008-02-28
我以前做过类似的测试。
第一种以第二种速度快,内存没测过
即尽量用Object obj=new Object();
还可以减小变量的域。
第一种以第二种速度快,内存没测过
即尽量用Object obj=new Object();
还可以减小变量的域。
movingboy
2008-02-27
shikonglaike 写道
当然有区别了。第二种在内存中保存一个对象的引用,而第一种的编码方式会在内存中产出大量的对象。浪费大量的内存空间,还有也增加了系统做垃圾回收的负荷。仔细想想是不是这样。
记得不太清晰了,但猜测现在的编译器或虚拟机已经比较先进,应该能够对第一种情况进行优化
movingboy
2008-02-27
有没有哪位能用测试数据说话?
yyjn12
2008-02-27
luanma 写道
Object obj=null;
for(int i=0; i<100;i++){
obj=new Object();
}
没必要,而且难看
for(int i=0; i<100;i++){
obj=new Object();
}
没必要,而且难看
有必要的.狮子说的对呢.
一个引用要占4个字节的内存呢.
luanma
2008-02-27
Object obj=null;
for(int i=0; i<100;i++){
obj=new Object();
}
没必要,而且难看
for(int i=0; i<100;i++){
obj=new Object();
}
没必要,而且难看
shikonglaike
2008-02-27
大家说的很好!
你们的意思是这两个一样了?
你们的意思是这两个一样了?
shikonglaike
2008-02-27
mvmouse 写道
这两段代码都创建了100个一般对象和1个Vector,占用的内存为什么不一样呢?
所谓浪费大量的内存空间浪费在哪里了呢?
所谓浪费大量的内存空间浪费在哪里了呢?
上一个有一百个引用.下一个有一个引用.
mvmouse
2008-02-27
这两段代码都创建了100个一般对象和1个Vector,占用的内存为什么不一样呢?
所谓浪费大量的内存空间浪费在哪里了呢?
所谓浪费大量的内存空间浪费在哪里了呢?
edu
2008-02-27
shikonglaike 写道
当然有区别了。第二种在内存中保存一个对象的引用,而第一种的编码方式会在内存中产出大量的对象。浪费大量的内存空间,还有也增加了系统做垃圾回收的负荷。仔细想想是不是这样。
我觉得,第二种方法在内存里面同样保留大量对象的匿名引用
shikonglaike
2008-02-27
当然有区别了。第二种在内存中保存一个对象的引用,而第一种的编码方式会在内存中产出大量的对象。浪费大量的内存空间,还有也增加了系统做垃圾回收的负荷。仔细想想是不是这样。
tinywind
2008-02-27
第一个例子有区别吗?
- 浏览: 15657 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
链接
最新评论
-
IBM MQ API以及其他的资料
狂顶你.
-- by pooslife -
websphere 集群问题
robbin 写道这么容易求证的问题,你怎么不自己动手试试看呢?我试了啊。是不行 ...
-- by shikonglaike -
websphere 集群问题
这么容易求证的问题,你怎么不自己动手试试看呢?
-- by robbin -
职场心得
very good
-- by tt -
IBM MQ API以及其他的资料
thanks,i need this!
-- by archt






评论排行榜