编写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. hdu 4162 Shape Number 最小表示法

    题目链接 给一个字符串, 将它想象成一个环, 然后从环中任意一个位置断开, 求断开后字典序最小的那种情况. 直接上模板.. #include <iostream> #include < ...

  2. fafu 1100 线段树

    题目链接 单点更新, 区间查询. 这题空间好小.... #include <iostream> #include <vector> #include <cstdio> ...

  3. test md

    [TOC] Glossary SUT SYSTEM UNDER TEST CUT CLASS UNDER TEST MUT METHOD UNDER TEST Tests without Use of ...

  4. 【LeetCode题意分析&解答】42. Trapping Rain Water

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  5. [LeetCode]题解(python):143-Reorder List

    题目来源: https://leetcode.com/problems/reorder-list/ 题意分析: 给定一个链表L:L0→L1→…→Ln-1→Ln,改变链表的排序为: L0→Ln→L1→L ...

  6. poj 2689 大范围内素数筛选

    /** 给定一定范围求其内的素数 注意: **/ #include <iostream> #include <math.h> #include <cstring> ...

  7. php错误 mysql_query():supplied argument is not a valid MySQL result resource

    出现这种错误,原因是出现该错误的函数的参数出现了问题 参数出现问题有多种情况: 1.sql查询语句有问题,可能多了一个逗号,少了一个逗号,多了括号之类的: 2.与数据库连接的参数有问题,用户名.密码. ...

  8. Mysql 笔记:

    1:可以查看information_schema.index_statistics 来查看索引的使用信息.还可以使用pt-index-usage 这个工具来分析日志再结合explain 来分析使用的索 ...

  9. CAD教程/视频教程/软件类专题资料免费下载整理合集

    CAD教程&视频教程类专题资料免费下载 资源列表:http://www.xiaodianlv.com/group/cad/ [1] <AUTOCAD2012中文版全套视频教程大合集> ...

  10. 简单测试运行时类信息(RTTI),附详细例子

    新建一个单元文件,填写如下代码,然后保存为 ClassInfoUnit.pas,这里定义了一个结构,用来读取指定类的信息. unit ClassInfoUnit; interface uses Cla ...