zoukankan      html  css  js  c++  java
  • 用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时不相等的

  • 相关阅读:
    python 读写excel,基于win32com实现
    nginx中lua语言获取传参字符串转json打印key,value
    nginx中lua语言打印匹配正则表达式的内容
    nginx 对于post,get参数访问做xss,sql注入过滤
    javaWeb第五天---MVC设计模式
    javaWeb第四天-----jspELJSTL
    javaWeb第三天---http协议和会话技术
    javaWeb第一天
    JDBC第二天---JDBC工具类
    jdbc第三天---配置文件、dao模式
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5182201.html
Copyright © 2011-2022 走看看