编写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. Xcode GDB 命令list

    此文下半部分为转载:但是这里有一些我自己使用技巧,结合下面的文章,我们会有更多的收获,在此感谢原创者.     --------------------- 关于调试异常崩溃: 一般崩溃是由内存使用错误 ...

  2. 1501 二叉树最大宽度和高度 (BFS+树的遍历)

    题目:http://www.wikioi.com/problem/1501/ 给你一颗二叉树,求该数的宽和高, 首先求出树的高,直接进行二叉树遍历,能够得到二叉树的高 然后是得到宽,本人采用的是一层一 ...

  3. OSG选中效果展示

    <OpenSceneGraph三维渲染引擎编程指南>书中选中高亮效果示例.osgFX特效 2.得到鼠标的位置 osgFX特效1.高亮,在开头的时候写了: 2.线框: #include< ...

  4. Minix

    [1]  MINIX是一种基于微内核架构的类UNIX计算机操作系统,由Andrew S. Tanenbaum发明.MINIX最初发布于1987年,开放全部源代码给大学教学和研究工作.2000年重新改为 ...

  5. JAVA泛型-擦除

    package com.xt.thinks15_7; import java.util.Arrays; class EraseObject1<A> { } class EraseObjec ...

  6. windows7下,protel 99se元件库加载问题的解决方案

    方法一:到C盘(系统盘),系统文件夹(c:\windows)下的ADVPCB99SE和ADVSch99SE文件先配置原理图,用本文打开ADVPCB99SE文件,在[Change Library Fil ...

  7. 如何使用Excel和Word编辑和打印条形码

    本文介绍如何使用Microsoft Office Excel 2007和Microsoft Office Word 2007进行条形码的编辑后,通过普通的办公打印机将条形码打印出来. 对于少量,简单的 ...

  8. Delphi 重启应用程序(创建Bat文件的Process)

    Delphi 重启应用程序在工程主文件中加入Delay(500); //启动程序时请延时一段时间,否则只能重启一次 procedure RestartApp; var BatchFile: TextF ...

  9. VS2015如何另存解决方案文件-修改解决方案sln文件的路径

    原文:VS2005如何另存解决方案文件-修改解决方案sln文件的路径 修改解决方案sln文件的路径 方法一:工具→选项→项目和解决方案,可设置项目的默认保存位置.方法二:"解决方案资源管理器 ...

  10. Hibernate 配置详解(12) 其实我也不想用这么土的名字

    hibernate.hbm2ddl.import_files 这个配置用于在hibernate根据映射文件执行DDL之前,如果我们自己设置了要事先运行的SQL文件,hibernate就会先执行这些SQ ...