使用javap分析你的程序性能(以字符串拼接为例)
javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
语法:
javap [ 命令选项 ] class. . .
javap 命令用于解析类文件。其输出取决于所用的选项。若没有使用选项,javap 将输出传递给它的类的 public 域及方法。javap 将其输出到标准输出设备上。
命令选项
-help 输出 javap 的帮助信息。
-l 输出行及局部变量表。
-b 确保与 JDK 1.1 javap 的向后兼容性。
-public 只显示 public 类及成员。
-protected 只显示 protected 和 public 类及成员。
-package 只显示包、protected 和 public 类及成员。这是缺省设置。
-private 显示所有类和成员。
-J[flag] 直接将 flag 传给运行时系统。
-s 输出内部类型签名。
-c 输出类中各方法的未解析的代码,即构成 Java 字节码的指令。
-verbose 输出堆栈大小、各方法的 locals 及 args 数,以及class文件的编译版本
-classpath[路径] 指定 javap 用来查找类的路径。如果设置了该选项,则它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。
- bootclasspath[路径] 指定加载自举类所用的路径。缺省情况下,自举类是实现核心 Java 平台的类,位于 jrelib
t.jar 和 jrelibi18n.jar 中。
-extdirs[dirs] 覆盖搜索安装方式扩展的位置。扩展的缺省位置是 jrelibext
1、创建一个Java文件Concatenation.java :
1 public class Concatenation { 2 public static void main(String[] args) { 3 } 4 5 /** 6 * Using String mode 7 * @param fields 8 * @return 9 */ 10 public String implicit(String[] fields) { 11 String result = ""; 12 for (int i = 0; i < fields.length; i++) { 13 result += fields[i]; 14 } 15 return result; 16 } 17 18 /** 19 * Using StringBuilder mode 20 * @param fields 21 * @return 22 */ 23 public String explicit(String[] fields) { 24 StringBuilder result = new StringBuilder(); 25 for (int i = 0; i < fields.length; i++) { 26 result.append(fields[i]); 27 } 28 return result.toString(); 29 } 30 }
2、将文件拷贝至目录D盘下(你也不一定非要拷贝这里,任意位置)
3、执行编译命令,先生成class文件,生成结束后D盘将会多出一个Concatenation.class的文件
D:\>javac Concatenation.java
4、执行javap命令,执行完命令后会在命令框内显示很多行字符串,据说懂汇编的能看懂,不过咱也可以认识一些关键字,大概知道啥意识
D:\>javap -c Concatenation
输出内容如下:
implicit方法:
从第8行到第35行构成了一个循环体(根据goto语句认出来的),然后可以看到第11行,是在循环体内哦,每次都会New一次StringBuilder对象...
explicit方法:
再看看这个方法,不仅循环部分的代码更简短、更简单、而且它至生成了一个StringBuilder对象
tip:StringBuilder与StringBuffer的区别
1. 在执行速度方面的比较:StringBuilder > StringBuffer
2. StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
3. StringBuilder:线程非安全的 StringBuffer:线程安全的 当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
对于三者使用的总结:
1.如果要操作少量的数据用 = String
2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
本文引自《Java 编程思想(第四版)》的第284页,有兴趣的可以看看:)