java7(1)——反编译深入理解增强的switch(读字节命令实战)
【本文介绍】
本文主要讲java_7 的改进switch的底层实现。反编译一个使用带String的switch的demo并一步步解析反编译出来的字节命令,从编译的角度解读switch的底层实现。
【正文】
在java7中,switch()可以放进去String 类型了,这无非是一大便利。底层JVM的swtich并没有真正的改进,只是在编译阶段,编译器把关于String的switch拆分成if语句而已。
我们写一个简单的例子测试一下:
(1)Test类:switch()使用String
public class Test {
public void test(String str) {
switch(str){
case "a": System.out.println("a");break;
case "b": System.out.println("b");break;
default : System.out.println("default");
}
}
}
(2)Test2类:switch()使用int
public class Test2 {
public void test(int str) {
switch(str){
case 1: System.out.println("1");break;
case 2: System.out.println("2");break;
default : System.out.println("default");
}
}
}
javac 编译 , javap -c 反编译 Test 后的结果:
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return
public void test(java.lang.String);
Code:
0: aload_1
1: astore_2 ---------------从这里开始------------
2: iconst_m1 // 将int型-1推送至栈顶
3: istore_3 // 赋值,因为此时栈顶元素为-1,所以赋值-1
4: aload_2
5: invokevirtual #2 // Method java/lang/String.hashCode: 调用hasCode方法
()I
8: lookupswitch { // 2 源码本来只有一次switch,现在被拆分成两次,这是第一次switch,下面还有一次公共的
97: 36 case 97 : 跳至36行 aload_2
98: 50 case 98 :跳至50行 aload_2
default: 61 default : 跳至61行 iload_3
}
36: aload_2
37: ldc #3 // String a 下面equal的内容
39: invokevirtual #4 // Method java/lang/String.equals:(L 进行equal的比较
java/lang/Object;)Z
42: ifeq 61 // if 语句
45: iconst_0 // 将int型0推送至栈顶
46: istore_3 // 赋值,因为此时栈顶元素为 0 ,所以赋值0
47: goto 61
50: aload_2
51: ldc #5 // String b 下面equal的内容
53: invokevirtual #4 // Method java/lang/String.equals:(L 进行equal的比较
java/lang/Object;)Z
56: ifeq 61 // if 语句
59: iconst_1 // 将int型1推送至栈顶
60: istore_3 // 赋值,因为此时栈顶元素为 1 , 所以赋值1
61: iload_3 ----------------到这里结束---------------
62: lookupswitch { //
0: 88
1: 99
default: 110
}
88: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
91: ldc #3 // String a
93: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
96: goto 118
99: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
102: ldc #5 // String b
104: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
107: goto 118
110: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
113: ldc #8 // String default
115: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
118: return
}
javac 编译 , javap -c 反编译 Test2 后的结果:
public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return
public void test(int);
Code:
0: iload_1
1: lookupswitch { //
1: 28
2: 39
default: 50
}
28: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
31: ldc #3 // String 1
33: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
36: goto 58
39: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
42: ldc #5 // String 2
44: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
47: goto 58
50: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
53: ldc #6 // String default
55: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
58: return
}
大家看到这么多字节码是不是有点头晕不想再看下去了?其实只需稍稍观察比较就能发现”从这里开始“——”到这里结束“中间那些字节码是下面那个字节码文件所没有的,所以我们研究这几行代码就行了。又看我用红色字体标出来的注释,结果就显而易见了:
(0)用一个int类型变量代表String类型变量
(1)获取String字符串的hashCode
(2)case hashCode
(3)用if语句处理String
(4)为int类型的变量赋值
(5)真正的swtich,现在传入的是上面得出的int类型变量。
把上面的字节码文件翻译成java即:
public class test {
public void test(String str) {
int i = -1;
switch(str.hashCode()){
case 97:
if(str.equals("a")){
i = 0;
}
break;
case 98:
if(str.equals("b")){
break;
}
}
switch(i) {
case 0:
System.out.println("a");
break;
case 1:
System.out.println("b");
break;
default:
System.out.println("default");
}
}
}
java7(1)——反编译深入理解增强的switch(读字节命令实战)的更多相关文章
- 通过反编译深入理解Java String及intern(转)
通过反编译深入理解Java String及intern 原文传送门:http://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作 ...
- 通过反编译深入理解Java String及intern
一.字符串问题 字符串在我们平时的编码工作中其实用的非常多,并且用起来也比较简单,所以很少有人对其做特别深入的研究.倒是面试或者笔试的时候,往往会涉及比较深入和难度大一点的问题.我在招聘的时候也偶尔会 ...
- (转)通过反编译深入理解Java String及intern
原文链接:https://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作中用的非常多,并且用起来非常简单,所以很少有人对其做特别 ...
- 从反编译深入理解JAVA内部类类结构以及finalkeyword
1.为什么成员内部类能够无条件訪问外部类的成员? 在此之前,我们已经讨论过了成员内部类能够无条件訪问外部类的成员,那详细到底是怎样实现的呢?以下通过反编译字节码文件看看到底.其实,编译器在进行编译的时 ...
- android apk 防止反编译技术第二篇-运行时修改字节码
上一篇我们讲了apk防止反编译技术中的加壳技术,如果有不明白的可以查看我的上一篇博客http://my.oschina.net/u/2323218/blog/393372.接下来我们将介绍另一种防止a ...
- Java| 编译和反编译
原文链接: http://www.yveshe.com/articles/2018/05/01/1525172129089.html 什么是编程语言? 在介绍编译和反编译之前,我们先来简单介绍下编程语 ...
- Java 编译与反编译
编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级语言(Low-level Lang ...
- JD-GUI反编译后代码逻辑分析
一,用jd-gui.exe等工具查看源代码.如何你不会,可以参看此文章: http://blog.csdn.net/hp_2008/article/details/8207879 可以到以下连接下载可 ...
- apk 反编译工具的使用
在学习android 开发的时候,我们经常回尝试使用到别人的apk,希望能了解别人怎么编写的代码,于是想要一个能实现其反编译的软件,将软件反编译出来,查看其代码. 工具/原料 反编译软件dex2jar ...
随机推荐
- [开机启动]Linux开机自启和运行级别
嵌入式系统中程序自启动方法 在很多嵌入式系统中,由于可用资源较少,常常在系统启动后就直接让应用程序自动启动,以减少用户操作和节省资源.如何让自己的应用程序自动启动呢? 在Linux系统中,配置应 ...
- ajax——优化0126(增删改查:添加查看详情,返回结果类型为JSON型,在窗口显示)
效果: 鼠标点击查看详情时 数据库: 0126.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...
- 【转】web测试技术经典案例(基础、全面)
觉得有些内容还是挺实用的,就转了 1. 概述 随着web应用的增多,新的模式解决方案中以web为核心的应用也越来越多,很多公司各种应用的架构都以B/S及web应用为主,但是有关WEB测试方面的内容并没 ...
- 第二百四十八节,Bootstrap轮播插件
Bootstrap轮播插件 学习要点: 1.轮播插件 本节课我们主要学习一下 Bootstrap 中的轮播插件. 一.轮播 轮播插件就是将几张同等大小的大图,按照顺序依次播放. 基本实例. 第一步,给 ...
- 【BZOJ】1079: [SCOI2008]着色方案(dp+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=1079 只能想到5^15的做法...........................果然我太弱. 其实 ...
- 【BZOJ】1689: [Usaco2005 Open] Muddy roads 泥泞的路(贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1689 一开始我也想到了贪心,,,策略是如果两个连续的水池的距离小于l的话,那么就将他们链接起来,,, ...
- zabbix2.0 添加自定义监控项
1. key的创建 客户端配置文件如下: root@192.168.100.254:/usr/local/zabbix/sbin# egrep -v "(^#|^$)" ../et ...
- HTTP报文-->MVC
引用 学习Web开发不好好学习HTTP报文,将会“打拳不练功,到老一场空”,你花在犯迷糊上的时间比你沉下心来学习HTTP的时间肯定会多很多. HTTP请求报文解剖 HTTP请求报文由3部分组成(请求行 ...
- TCP连接的建立与终止过程详解
TCP连接的建立与终止: 1.TCP连接的建立 设主机B运行一个服务器进程,它先发出一个被动打开命令,告诉它的TCP要准备接收客户进程的连续请求,然后服务进程就处于听的状态.不断检测是否有客 ...
- LA3485 Bridge[(辛普森自适应)微积分]
做此题完全是为了练积分. [普通求导版] Select Code #include<cstdio> #include<cmath> using namespace std; t ...