用javap命令反编译来分析字符串问题

编写Test.java,编译完后生成Test.class文件,然后对该文件执行javap -c Test命令,生成字节码指令,阅读并得出结论

一、s1和s2指向常量池的不同常量

①java代码

public class Test {

public static void main(String[] args) throws IOException {

String s1="t";

String s2="m";

}

}

②反编译可以看到字节码指令执行如下:

Compiled from "Test.java"

public class typ.Test extends java.lang.Object{

public typ.Test();

Code:

0:   aload_0

1:   invokespecial   #8; //Method java/lang/Object."<init>":()V

4:   return

public static void main(java.lang.String[])   throws java.io.IOException;

Code:

0:   ldc     #19; //String t 进入操作数栈顶

2:   astore_1     //String t 出操作数栈,赋值给变量1,即s1

3:   ldc     #21; //String m 进入操作数栈顶

5:   astore_2     //String m 出操作数栈,赋值给变量2,即s2

6:   return

}

从上面可以看出,两次ldc入栈操作分别指向的是常量#19和#21

二、s1和s2指向常量池的相同常量

①java代码

public class Test {

public static void main(String[] args) throws IOException {

String s1="t";

String s2="t";

}

}

②反编译可以看到字节码指令执行如下:

Compiled from "Test.java"

public class typ.Test extends java.lang.Object{

public typ.Test();

Code:

0:   aload_0

1:   invokespecial   #8; //Method java/lang/Object."<init>":()V

4:   return

public static void main(java.lang.String[])   throws java.io.IOException;

Code:

0:   ldc     #19; //String t 进入操作数栈顶

2:   astore_1     //String t 出操作数栈,赋值给变量1,即s1

3:   ldc     #19; //String t 进入操作数栈顶

5:   astore_2     //String t 出操作数栈,赋值给变量2,即s2

6:   return

}

从上面可以看出,两次ldc入栈的操作数都是将指向的常量#19,所以可以看出是s1和s2都是指向常量池的同一个常量“t”

三、进一步看下面

①java代码

public class Test {

public static void main(String[] args) throws IOException {

String s1="tm";

String s2="t"+"m";

}

}

②反编译可以看到字节码指令执行如下:

Compiled from "Test.java"

public class typ.Test extends java.lang.Object{

public typ.Test();

Code:

0:   aload_0

1:   invokespecial   #8; //Method java/lang/Object."<init>":()V

4:   return

public static void main(java.lang.String[])   throws java.io.IOException;

Code:

0:   ldc     #19; //String tm 进入操作数栈顶

2:   astore_1     //String tm 出操作数栈,赋值给变量1,即s1

3:   ldc     #19; //String tm 进入操作数栈顶

5:   astore_2     //String tm 出操作数栈,赋值给变量2,即s2

6:   return

}

可以看出,两次ldc(load命令, 将操作数入栈)入栈的操作数都是将指向的常量#19即“tm”,说明在编译期间,“t”+"m"就已经变为“tm”这一个常量了

四、再进一步

①java代码

public class Test {

public static void main(String[] args) throws IOException {

String tmp = "t";

String s1 = "m";

String s2 = tmp + "m";

}

}

②反编译可以看到字节码指令执行如下:

Compiled from "Test.java"

public class typ.Test extends java.lang.Object{

public typ.Test();

Code:

0:   aload_0

1:   invokespecial   #8; //Method java/lang/Object."<init>":()V

4:   return

public static void main(java.lang.String[])   throws java.io.IOException;

Code:

0:   ldc     #19; //String t 进入操作数栈顶

2:   astore_1     //String t 出操作数栈,赋值给变量1,即tmp

3:   ldc     #21; //String m 进入操作数栈顶

5:   astore_2     //String m 出操作数栈,赋值给变量2,即s1

6:   new     #23; //class java/lang/StringBuilder 创建StringBuilder类型对

   9:   dup          //复制栈顶一个字长的数据,将复制后的数据压栈

   10:  aload_1      //tmp 进入操作数栈顶

11:  invokestatic    #25; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;

14:  invokespecial   #31; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V

17:  ldc     #21; //String m

19:  invokevirtual   #34; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

22:  invokevirtual   #38; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

25:  astore_3

26:  return

}

从上面的代码可以看出,string的相加要通过stringbuilder,并且由于tmp是变量,所以调用的invokevirtual指令(在编译器无法确定),这说明不是

在编译期完成,因此s1与s2时不相等的

用javap命令反编译来分析字符串问题,布布扣,bubuko.com

时间: 2024-10-09 11:06:24

用javap命令反编译来分析字符串问题的相关文章

javap 命令 反编译代码

javap 命令 javap -c classname 一个好的分析class二进制文件的 链接 http://blog.csdn.net/pwlazy/article/details/7954169

Java反编译代码分析(一)

浅析如何读懂这种反编译过来的文件,不喜勿喷. 赋值 Node node; Node node1 = _$3.getChildNodes().item(0); node1; node1; JVM INSTR swap ; node; getChildNodes(); 0; item(); getChildNodes(); 0; item(); getNodeValue(); String s; s; 原始语句: Node node; Node node1 = currDocument.getChi

IDEA设置External Tools之Javap反编译字节码

通过Jdk的命令javap可以反编译查看字节码,但是在使用idea的时候一直用命令行去操作不太好操作,而且因为idea会把class码 放在target里面,经常会忘记切换目录.这个时候idea的External Tools就派上用场了. 具体操作如下,先到idea的设置界面 进入Tools >  External Tools中 添加工具,分别设置program,argument等,其中arguments中是javap的参数,具体的参数信息可以去看下help信息 之后在打开的java文件界面右键

JDK自带反编译工具javap

在JDK的bin文件夹下,有许多自带工具: javap就是其中的一个,对应为 javap.exe javap可反编译查看Java编译器编译生成的字节码文件, 语法: javap [ options ] class options: -help 帮助 -l 输出行和变量的表 -public 只输出public方法和域 -protected 只输出public和protected类和成员 -package 只输出包,public和protected类和成员,这是默认的 -p -private 输出所

为eclipse配置javap命令

javap命令常用来对java类文件来进行反编译,主要用来对java进行分析的工具,在学习Thinking in Java时,由于需要对类文件反编译,以查看jvm到底对我们写的代码做了哪些优化和处理,比如我看的使用+=对字符串进行拼接时,jvm的处理方式.废话不多说,下面直接带上配置的教程: 点击菜单栏 Run --->  External tools ---> External tools Configurations...    然后如下图点击New 输入: Name: javap Loc

java7(1)——反编译深入理解增强的switch

[本文介绍] 本文主要讲java_7 的改进switch的底层实现.反编译一个使用带String的switch的demo并一步步解析反编译出来的字节码,从编译的角度解读switch的底层实现. [正文] 在java7中,switch()可以放进去String 类型了,这无非是一大便利.底层JVM的swtich并没有真正的改进,只是在编译阶段,编译器把关于String的switch拆分成if语句而已. 我们写一个简单的例子测试一下: (1)Test类:switch()使用String public

ApkTool反编译apk,去除广告或者汉化后重新打包apk,并签名

http://my.oschina.net/mopidick/blog/135581 以ubuntu的环境为例子,window的大同小异 首先下载apktool工具:https://code.google.com/p/android-apktool/ 注意:这个地址下载时,由于官网把apktool和apktool-install-linux-r05-ibot(或者是window下的)两个工具分开了,所以用户需要同时下载: <!-- lang: shell --> 1.apktool1.5.2.

反编译Android应用

转载请注明出处:http://blog.csdn.net/allen315410/article/details/44018747 Android反编译介绍 我们在开发Android应用的时候,常常会"参考""借鉴"一下别人"想法",你们懂的!然而,很多时候我们是看不见别人的源码的,这时候唯一解决的方法就是反编译apk,我们知道,当一个Android应用开发好了以后,会打包生成apk文件,然而Android打包工具会将java源码编译成.clas

Android应用程序破解(反编译)

一.apktools进行反编译 1.首先安装需要JAVA环境(JDK和JRE) 设置JAVA环境变量 CLASSPATH       %JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar JAVA_HOME     C:\Program Files\Java\jdk1.8.0_20 Path    %JAVA_HOME%\bin;C:\Program Files\Java\jre1.8.0_20\bin 2.下载apktools并解压 (1)下载apk