编写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. C++中虚函数功能的实现机制

    要理解C++中虚函数是如何工作的,需要回答四个问题. 1.  什么是虚函数. 虚函数由于必须是在类中声明的函数,因此又称为虚方法.所有以virtual修饰符开始的成员函数都成为虚方法.此时注意是vir ...

  2. 在C#调用C++的DLL方法(一)生成非托管dll

    C#与C/C++相比,前者的优势在于UI,后者的优势在于算法,C++下的指针虽然恶心,若使用得当还是相当方便的,最重要的问题是,市面上很多流行的开发工具库,几乎没有不支持C++的,但全面支持C#只能说 ...

  3. Log4net 自定义字段到数据库

    今天要求做个log4net自定义字段到数据库,在网上找了好多例子,都运行不成功.最后找了个国外的,很简单的就解决了. log4net它已经定义的字段有 <commandText value=&q ...

  4. zoj 2587 Unique Attack 最小割判定

    题目链接 让你判断最小割是否唯一. 判断方法是, 先求一遍最大流, 然后从源点dfs一次, 搜索未饱和边的数目. 从汇点dfs一次, 同样也是搜索未饱和边的数目, 看总和是否等于n. 如果等于n那么唯 ...

  5. [LeetCode]题解(python):145-Binary Tree Postorder Traversal

    题目来源: https://leetcode.com/problems/binary-tree-postorder-traversal/ 题意分析: 后序遍历一棵树,递归的方法很简单,尝试用非递归的方 ...

  6. 精通 VC++ 实效编程280例 - 01 窗口

    窗口是屏幕上的一个矩形区域.窗口分为3种:重叠窗口.弹出窗口和子窗口.每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”.在 MFC 中,CWnd 类为各种窗口提供了基类. 1 通过 HW ...

  7. ArrayList和LinkedList的各项操作性能比较

          如果用java编写程序,我们通常存储易变的数据集合时用到的数据结构往往是ArrayList,不过,在JDK中还存在另一个结构--LinkedList,只不过我们通常不用,原因在于性能问题, ...

  8. Debug目录下没有.exe文件

    记一下小笔记: VC6.0设置.exe文件的输出路径: Project->Settings->Link Category选择"General" 在Output file ...

  9. tar.xz文件怎样解压

    XZ压缩最新压缩率之王 xz这个压缩可能非常多都非常陌生,只是您可知道xz是绝大数linux默认就带的一个压缩工具. 之前xz使用一直非常少,所以差点儿没有什么提起. 我是在下载phpmyadmin的 ...

  10. ftp读取txt数据并插入数据库

    去官网下载http://enterprisedt.com/ .netftp组件 目前最新版本为2.2.3,下载后在bin目录中找到edtFTPnet.dll,在项目中添加引用. using Enter ...