JAVA虚拟机——利用javap反编译class文件分析代码执行过程

我们经常会看到或者听到java代码要如何如何优化,这样写不对,那样写性能不高等等,可是我们如何去伪求真呢?就以 Java 代码性能优化总结文章中的内容例子,来求证一下吧

先热热身

String字符串拼接和StringBuffer一样吗

看看下面这段代码:

public class TestClass{ public String incStringJoint(){ String str = "a"; String str1 = str + "b"; return str1; } public String incStringBuffer(){ StringBuffer str = new StringBuffer(3); str.append("a"); str.append("b"); return str.toString(); } }

抛开其他方面,这两段代码性能一样吗? 带着这个问题,我们去探索一番。

javac TestClass.java //将java文件编译成class文件 javap -verbose TestClass.class //反编译class文件

反编译结果:

{ public TestClass(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public java.lang.String incStringJoint(); // incStringJoint()方法执行情况 descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: ldc #2 // String a 2: astore_1 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: aload_1 11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: ldc #6 // String b 16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: astore_2 23: aload_2 24: areturn LineNumberTable: //反编译结果对应源码的行数 line 4: 0 line 5: 3 line 6: 23 public java.lang.String incStringBuffer(); // incStringBuffer()方法执行情况 descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=3, locals=2, args_size=1 0: new #8 // class java/lang/StringBuffer 3: dup 4: iconst_3 5: invokespecial #9 // Method java/lang/StringBuffer."<init>":(I)V 8: astore_1 9: aload_1 10: ldc #2 // String a 12: invokevirtual #10 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer; 15: pop 16: aload_1 17: ldc #6 // String b 19: invokevirtual #10 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer; 22: pop 23: aload_1 24: invokevirtual #11 // Method java/lang/StringBuffer.toString:()Ljava/lang/String; 27: areturn LineNumberTable: //反编译结果对应源码的行数 line 10: 0 line 11: 9 line 12: 16 line 13: 23 } SourceFile: "TestClass.java"

我们先大致看一下反编译的结果,可以发现其实String字符串拼接实质上是用StringBuilderappend方法实现,那么我们再看一下StringBufferStringBuilder的源码:可以发现,两个类的append方法调用的是同一个方法实现字符串拼接。

public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }

这里就有一个问题了,那为什么在字符串拼接的时候,要使用StringBuffer(线程安全)或者使用StringBuilder(线程不安全)呢?

现在我们修改一下代码:

public String incStringJoint(){ String str = "a"; String str1 = str + "b"; String str2 = str1 + "c"; return str2; }

多次拼接,看看结果怎么?

public java.lang.String incStringJoint(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=2, locals=4, args_size=1 0: ldc #2 // String a 2: astore_1 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: aload_1 11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: ldc #6 // String b 16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: astore_2 23: new #3 // class java/lang/StringBuilder 26: dup 27: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 30: aload_2 31: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 34: ldc #8 // String c 36: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 39: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: astore_3 43: aload_3 44: areturn LineNumberTable: line 4: 0 line 5: 3 line 6: 23 line 7: 43

注意第3行第23行,new了两个StringBuilder。这就说明,利用String本身进行字符串拼接的时候,每拼接一次,就要new一个StringBuilder,再调用append方法。

new String()到底创建了几个对象

看下面代码:

public class TestClass{ public String incString(){ String str = "a"; return str; } public String incNewString(){ String str = new String("a"); return str; } } { public TestClass(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public java.lang.String incString(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=1 0: ldc #2 // String a 2: astore_1 3: aload_1 4: areturn LineNumberTable: line 20: 0 line 21: 3 public java.lang.String incNewString(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=3, locals=2, args_size=1 0: new #3 // class java/lang/String 3: dup 4: ldc #2 // String a 6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V 9: astore_1 10: aload_1 11: areturn LineNumberTable: line 25: 0 line 26: 10 }

持续更新

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

P2P技术揭秘.P2P网络技术原理与典型系统开发

Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E