从java汇编来看java程序的性能优化

本文详细探讨了在Java编程中避免过度使用迭代器、优化String连接运算的方法,通过对比实例展示了使用迭代器带来的性能损耗,并提出了在特定场景下更高效的选择。同时,介绍了Java 1.5版本中对String连接性能的优化,以及如何正确利用新特性提高代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文作者为我们指出了一条提高Java 性能的有效方法:使用Java 汇编,但是如何权衡效率与其他软件性能(如可维护性、扩展性)等等,需要读者根据项目需要做出取舍。

这些天一直在用Oolong学习Java汇编,也试图反编译一些java代码。在这之间突然意识到原来自己过去犯了很多编程的误区,导致代码效率低下。这里列出一些需要注意的地方


1.尽量避免使用iterator(不是必要的话)

原来自己看C++的书,看到STL里的iterator的用法,很多书上说这种用法好,如果实现一变,iterator的代码可以不用修改。我是一个很信书的人,自从那时候开始,我就喜欢上用iterator了,比如以下代码(第一段)

for(int i=0;i<results.size();i++){
String result = results.get(i);
}

都换成了(第二段)

Iterator<String> iter = results.iterator();
while(iter.hasNext()){
String result = iter.next();
}

最近学习Oolong,反编译这两段代码,妈妈啊

第一段的Java汇编是

.line 11
l9: iconst_0
l10: istore 5
l12: iload 5
l14: aload 4
l16: invokevirtual java/util/ArrayList/size ()I
l19: if_icmpge l40
.line 12
l22: aload 4
l24: iload 5
l26: invokevirtual java/util/ArrayList/get (I)Ljava/lang/Object;
l29: checkcast java/lang/String
l32: astore 6
.line 11
l34: iinc 5 1
l37: goto l12
第二段的Java汇编是

.line 15
l40: aload 4
l42: invokevirtual java/util/ArrayList/iterator ()Ljava/util/Iterator;
l45: astore 5
.line 16
l47: aload 5
l49: invokeinterface java/util/Iterator/hasNext ()Z 1
l54: ifeq l72
.line 17
l57: aload 5
l59: invokeinterface java/util/Iterator/next ()Ljava/lang/Object; 1
l64: checkcast java/lang/String
l67: astore 6
.line 18
l69: goto l47
仔细一看,前一段用的是invokevirtual,后面那段用的是invokeinterface,原理上来说invokeinterface的速度比invokevirtual要慢得多,测试两段代码发现,后一段代码耗时比前一段多一个数量级,以后千万不要乱用iterator了

二如果没有必要,尽量不要使用接口

原来写程序的时候,迷信类型分装,结果不分青红皂白,返回对象清一色的接口

比如一个返回中间结果的方法变成了这样:

public List<String> getList(){
List<String> results = new ArrayList<String>();

return results;
}

处理的方法象这样

public void handle(List<String> contents){
for(int index=0;index<contents.size();index++){
String content = contents.get(index);
}
}

反编译handle发现

.line 9
l0: iconst_0
l1: istore_2
l2: iload_2
l3: aload_1
l4: invokeinterface java/util/List/size ()I 1
l9: if_icmpge l29
.line 10
l12: aload_1
l13: iload_2
l14: invokeinterface java/util/List/get (I)Ljava/lang/Object; 2
l19: checkcast java/lang/String
l22: astore_3
.line 9
l23: iinc 2 1
l26: goto l2
哎哟,又是invokeinterface,赶紧的改回来

public void handle(ArrayList<String> contents){
for(int index=0;index<contents.size();index++){
String content = contents.get(index);
}
}

public ArrayList<String> getList(){
ArrayList<String> results = new ArrayList<String>();

return results;
}
这会好了,不在是invokeinterface,是invokevirtual,快啊

.line 9
l0: iconst_0
l1: istore_2
l2: iload_2
l3: aload_1
l4: invokevirtual java/util/ArrayList/size ()I
l7: if_icmpge l25
.line 10
l10: aload_1
l11: iload_2
l12: invokevirtual java/util/ArrayList/get (I)Ljava/lang/Object;
l15: checkcast java/lang/String
l18: astore_3
.line 9
l19: iinc 2 1
l22: goto l2
三. 1.5的新特性,小心使用

看到1.5的新特性,好用啊,这个

for(String content:contents){
}

反编译,怎么还是iterator?,小心,别乱用哦

l0: aload_1
l1: invokevirtual java/util/ArrayList/iterator ()Ljava/util/Iterator;
l4: astore_2
l5: aload_2
l6: invokeinterface java/util/Iterator/hasNext ()Z 1
l11: ifeq l27
l14: aload_2
l15: invokeinterface java/util/Iterator/next ()Ljava/lang/Object; 1
l20: checkcast java/lang/String
l23: astore_3
.line 10
l24: goto l5
四.1.5中的String不再是可怕的性能瓶颈啦

在effective java里曾经说过,尽量少用String做连接运算,做字符串连接运算时,StringBuffer性能更好,可以减少new String的次数

可是在1.5里尝试以下代码

String contents = "";
for(int i=0;i<10000;i++)
contents += "Hello";

结果反编译一看,完全不是那么回事

.line 9
l0: ldc ""
l2: astore_1
.line 10
l3: iconst_0
l4: istore_2
l5: iload_2
l6: sipush 10000
l9: if_icmpge l38
.line 11
l12: new java/lang/StringBuilder
l15: dup
l16: invokespecial java/lang/StringBuilder/<init> ()V
l19: aload_1
l20: invokevirtual java/lang/StringBuilder/append (Ljava/lang/String;)Ljava/lang/StringBuilder;
l23: ldc "Hello"
l25: invokevirtual java/lang/StringBuilder/append (Ljava/lang/String;)Ljava/lang/StringBuilder;
l28: invokevirtual java/lang/StringBuilder/toString ()Ljava/lang/String;
l31: astore_1
.line 10
l32: iinc 2 1
l35: goto l5
这里用的就是StringBuffer的替代品StringBuilder,当然可能是IBM的Java编译器优化,或者是1.5的编译器优化了(今后在证实),反正目前在ibm JRE1.5上编译出来的String连接代码完全是高效的,至少目前我能放心的用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值