博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用javap命令反编译来分析字符串问题
阅读量:5229 次
发布时间:2019-06-14

本文共 3253 字,大约阅读时间需要 10 分钟。

编写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时不相等的

转载于:https://www.cnblogs.com/zfyouxi/p/5182201.html

你可能感兴趣的文章
java的Array和List相互转换
查看>>
layui父页面执行子页面方法
查看>>
如何破解域管理员密码
查看>>
Windows Server 2008 R2忘记管理员密码后的解决方法
查看>>
IE11兼容IE8的设置
查看>>
windows server 2008 R2 怎么集成USB3.0驱动
查看>>
Foxmail:导入联系人
查看>>
vue:axios二次封装,接口统一存放
查看>>
vue中router与route的区别
查看>>
js 时间对象方法
查看>>
网络请求返回HTTP状态码(404,400,500)
查看>>
Spring的JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate
查看>>
Mac下使用crontab来实现定时任务
查看>>
303. Range Sum Query - Immutable
查看>>
图片加载失败显示默认图片占位符
查看>>
【★】浅谈计算机与随机数
查看>>
《代码阅读方法与实现》阅读笔记一
查看>>
解决 sublime text3 运行python文件无法input的问题
查看>>
javascript面相对象编程,封装与继承
查看>>
Atlas命名空间Sys.Data下控件介绍——DataColumn,DataRow和DataTable
查看>>