编写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:

   :   aload_0

   ; //Method java/lang/Object."<init>":()V

   :   return



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

  Code:

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

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

   ; //String m 进入操作数栈顶

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

   :   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:

   :   aload_0

   ; //Method java/lang/Object."<init>":()V

   :   return



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

  Code:

   ; //String t 进入操作数栈顶

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

   ; //String t 进入操作数栈顶

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

   :   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:

   :   aload_0

   ; //Method java/lang/Object."<init>":()V

   :   return



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

  Code:

   ; //String tm 进入操作数栈顶

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

   ; //String tm 进入操作数栈顶

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

   :   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:

   :   aload_0

   ; //Method java/lang/Object."<init>":()V

   :   return



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

  Code:

   ; //String t 进入操作数栈顶

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

   ; //String m 进入操作数栈顶

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

   ; //class java/lang/StringBuilder 创建StringBuilder类型对
象 
   :   dup          //复制栈顶一个字长的数据,将复制后的数据压栈 
   :  aload_1      //tmp 进入操作数栈顶

   ; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;

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

   ; //String m

   ; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   ; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

   :  astore_3

   :  return

}

从上面的代码能够看出。string的相加要通过stringbuilder。而且因为tmp是变量。所以调用的invokevirtual指令(在编译器无法确定),这说明不是
在编译期完毕,因此s1与s2时不相等的

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

  1. javap命令反编译

    javap命令反编译生成的是程序员可以认识的字节码文件 -help --help -? 输出此用法消息 -version 版本信息,其实是当前javap所在jdk的版本信息,不是class在哪个jdk ...

  2. JDK自带javap命令反编译class文件和Jad反编译class文件(推荐使用jad)

    一.前言 我们在日常学习中,对一个java代码有问题,不知道jvm内部怎么进行解析的时候:有个伟大壮举就是反编译,这样就可以看到jvm内部怎么进行对这个java文件解析的!我们可以使用JDK自带的ja ...

  3. javap 命令 反编译代码

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

  4. 使用javap进行反编译Java枚举

    这是一个枚举类Day.java public enum Day { MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY(" ...

  5. Java反编译代码分析(一)

    浅析如何读懂这种反编译过来的文件,不喜勿喷. 赋值 Node node; Node node1 = _$3.getChildNodes().item(0); node1; node1; JVM INS ...

  6. 反编译字节码角度分析synchronized关键字的原理

    1.synchronized介绍 synchronized是java关键字.JVM规范中,synchronized关键字用于在线程并发执行时,保证同一时刻,只有一个线程可以执行某个代码块或方法:同时还 ...

  7. java7(1)——反编译深入理解增强的switch(读字节命令实战)

    [本文介绍] 本文主要讲java_7 的改进switch的底层实现.反编译一个使用带String的switch的demo并一步步解析反编译出来的字节命令,从编译的角度解读switch的底层实现. [正 ...

  8. 使用javap反编译class文件

    一个普通的Java类: package org.ccnt.concurrence; public class VolatileTest { public static volatile int rac ...

  9. @使用javap反编译Java字节码文件

    在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下). 我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件.在 ...

随机推荐

  1. leetcode Reverse Integer python

    class Solution(object): def reverse(self, x): """ :type x: int :rtype: int "&quo ...

  2. codeforces 401D. Roman and Numbers 数位dp

    题目链接 给出一个<1e18的数, 求将他的各个位的数字交换后, 能整除m的数的个数. 用状态压缩记录哪个位置的数字已经被使用了, 具体看代码. #include<bits/stdc++. ...

  3. PHP上传图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. Russia

    一.莫斯科 Moscow(Москва) 24日-周四(Day1) 1.广州 9:30公园前地铁站内集合,10:30分到达白云机场(CAN机场),12:50起飞. 18:20经停乌鲁木齐(URC机场) ...

  5. 关于CSS动画几点要注意的地方

    关于CSS动画几点要注意的地方 js操作transition无效果 先看这个demo以及stackoverflow的问题 http://jsfiddle.net/ThinkingStiff/QNnnQ ...

  6. python基础学习笔记1

    一.字符串: 1.不可变性.分片赋值对于字符串是不合法的. 2.字符串格式化 % eg: print 'The price is: %d' % 30 print 'The price is: %.2f ...

  7. windows中使用Git工具连接GitHub(配置篇)

    Git在源码管理领域目前占很大的比重了,而且开源的项目很多都转到GitHub上面了.例如:jQuery, reddit, Sparkle, curl, Ruby on Rails, node.js,  ...

  8. svn在linux下的使用(svn命令行)ubuntu 删除 新增 添加 提交 状态查询 恢复

    合并步骤:(1)先切换到分支:(2)svn merge trunk . (3)svn sw trunk (4)svn merge --reintegrate branch . svn merge ht ...

  9. Git库文件的状态

    git库所在的文件夹(即.git所在的文件夹)中的文件的状态: (1)untracked:未跟踪,此文件在文件夹中,但并没有加入git库,不参与版本控制. 通过”git add”,”git commi ...

  10. 编译器DIY——词法分析

    在上一篇文章中已经介绍了读文件的操作,那么这一篇文章中将会细致解释词法分析. 在源文件里解析出的单词流必须识别为保留字,标识符,常量,操作符和界符五大类 1.显然我们须要列举出全部的保留字,而这里与保 ...