javap是JDK自带的工具:

这篇文章使用下面这段简单的Java代码作为例子进行讲解。

class Outer {Nested nested;Nested getNested() {return nested;}
}
class Nested {Inner inner;Inner getInner() {return inner;}
}
class Inner {String foo;String getFoo() {return foo;}
}
public class NullableTest {public static Outer getInitializedOuter(){Outer outer = new Outer();outer.nested = new Nested();outer.nested.inner = new Inner();outer.nested.inner.foo = "Jerry";return outer;}/* null pointer exception
private static void way0(){
Outer outer = new Outer();
System.out.println(outer.nested.inner.foo);
}*/public static void way1(){Outer outer = getInitializedOuter();if (outer != null && outer.nested != null && outer.nested.inner != null) {System.out.println(outer.nested.inner.foo);}}public static void main(String[] args) {//way0();way1();}
}

使用下面的命令行对NullableTest进行反编译,以java编译器生成的字节码:

javap -v NullableTest >c:\code\1.txt

查看方法way1()对应的字节码:

下面这个wiki包含了java字节码里每个指令的具体说明:

https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

下面对NullableTest反编译得到的字节码做一些说明:

0: invokestatic #42 // Method getInitializedOuter:()Ljava8/Outer;

代表静态方法getInitializedOuter的调用, Ljava8/Outer意思是该方法的返回类型是Outer

3: astore_0

将上述静态方法调用返回的outer引用存储到局部变量中,局部变量的id为0.

4: aload_0

因为在我前面的Java源代码中,我将静态方法返回的对象引用同null做了比较,因此使用指令aload_0将存储在代号为0的局部变量中的对象引用重新加载到栈上,此后才能和null做比较。

5: ifnull 41

这就是我在Java源代码里书写的IF分支。如果IF分支里检测的outer引用为null,则直接返回了。体现在字节码就是,如果ifnull为true,则跳转到第41行字节码,即直接返回。

如果ifnull不为true,则继续执行下去。又将outer引用加载到栈上。

从字节码的分析可以观察到一个有趣的现象,再次看看我们的IF语句。

Java编译时,编译器实际将其转换成了下面的写法:

if (outer == null )return;if( outer.nested == null )return;if( outer.nested.inner == null)return;System.out.println(outer.nested.inner.foo);

这个事实可以通过下图得到确认。

javap生成的字节码里的LineNumberTable也很有用。这张表里每行的line后面的数字代表Java源代码的序号,line XX冒号后面的数字代表字节码里每行指令的序号。看看下图中Java源代码和对应的字节指令在LineNumberTable中的映射关系。

LineNumberTable维护了Java源代码同字节指令的映射关系,确保了Java代码调试的顺利进行。

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

一个简单的例子教会您使用javap相关推荐

  1. .net中的对象序列化(1): 序列化是什么, 以及一个简单的例子

    1. 为什么需要序列化,什么是序列化 对于一个程序来说, 使用到的对象都是存在于内存中的.如果想保存这些对象的运行时状态, 或者需要在不同进程或者网络间传递对象,就需要序列化. 序列化就是讲运行中的对 ...

  2. 一个简单的例子看java线程机制

    一个简单的例子看java线程机制 作者: zyf0808 发表日期: 2006-03-26 11:20 文章属性: 原创 复制链接 import java.util.*; public class T ...

  3. blockchain 区块链200行代码:在JavaScript实现的一个简单的例子

    blockchain 区块链200行代码:在JavaScript实现的一个简单的例子 了解blockchain的概念很简单(区块链,交易链块):它是分布式的(即不是放置在同一台机器上,不同的网络设备上 ...

  4. pycharm安装scrapy失败_Scrapy ——环境搭配与一个简单的例子

    在我刚接触爬虫的时候就已经听过Scrapy大名了,据说是一个很厉害的爬虫框架,不过那个时候沉迷于Java爬虫.现在终于要来揭开它神秘的面纱了,来一起学习一下吧 欢迎关注公众号:老白和他的爬虫 1.环境 ...

  5. java继承类型转换_#java 一个简单的例子理解java继承、成员函数重写、类型转换...

    一个简单的例子理解java继承.成员函数重写.类型转换 1.继承简介 举一个简单的例子:笔分为很多种,比如毛笔.钢笔.圆珠笔等等,这些笔都有一些相同的属性比如长度.笔迹的粗细等等:但他们也有不同的特点 ...

  6. 类模板与运算符重载(一个简单的例子)

    类模板与运算符重载(一个简单的例子) 标签(空格分隔): C++ 算法竞赛 下面是一段简单的代码,表示我们建立了一个类模板Vector,可以看做是对STL中vector的简单实现. 为了让这个Vect ...

  7. 一个简单的例子,学习自定义注解和AOP

    转载自   一个简单的例子,学习自定义注解和AOP 记得今年年初刚开始面试的时候,被问的最多的就是你知道Spring的两大核心嘛?那你说说什么是AOP,什么是IOC?我相信你可能也被问了很多次了. 1 ...

  8. antlr4例子_ANTLR和网络:一个简单的例子

    antlr4例子 网络上的ANTLR:为什么? 我开始在MS-DOS上编写我的第一个程序. 因此,我非常习惯在自己的机器上安装工具. 但是在2016年,网络无处不在,因此那里也可能需要我们的语言. 可 ...

  9. ANTLR和网络:一个简单的例子

    网络上的ANTLR:为什么? 我开始在MS-DOS上编写我的第一个程序. 因此,我非常习惯在计算机上安装工具. 但是在2016年,网络无处不在,因此那里也可能需要我们的语言. 可能的情况: ANTLR ...

最新文章

  1. 学习UI设计能做什么
  2. 101所被《人民日报》点名的大学:低调却颇有实力!
  3. LINQ to Entities 不识别方法“System.String ToString() 的解决方法
  4. javascript笔记:javascript的前世,至于今生嘛地球人都知道了哈
  5. python可变对象 不可变对象_【Python】可变对象和不可变对象
  6. c语言银行卡管理系统程序设计报告,C语言课程设计报告(银行账户信息管理系统).doc...
  7. android 触摸屏 不支持 配置,Android触摸屏配置调试
  8. python输出变量地址_Python——变量
  9. CSS Sprite精灵图如何缩放大小
  10. mysql MyISAM和InnoDB
  11. 螺旋矩阵 详解(C++)
  12. mysql to excel 插件_在Excel中操作MySQL数据库插件MySQL for Excel
  13. 涡旋电磁波:无线通信的革命
  14. 深度测评 | 五大主流多端开发框架全面对比
  15. 从外网到域控(vulnstack靶机实战一)
  16. 四、模拟英语四六级答题卡识别阅卷评分
  17. 摇一摇加好友功能实现
  18. “三高“Mysql - Mysql备份概览
  19. 弗洛伊德,迪杰斯特拉算法
  20. AssemblyBuilder以及Activator双剑合璧

热门文章

  1. Jacoco字节码植入原理(源码分析)
  2. 优化案例(part8)--Robust Recovery of Subspace Structures by Low-Rank Representation
  3. 文献记录(part35)--Mixed pooling and richer attention feature fusion for crack detection
  4. 第三次学JAVA再学不好就吃翔(part107)--字符流的拷贝
  5. 第三次学JAVA再学不好就吃翔(part102)--拷贝图片
  6. 第三次学JAVA再学不好就吃翔(part21)--局部变量与成员变量
  7. 第三次学JAVA再学不好就吃翔(part19)--二维数组
  8. 第三次学JAVA再学不好就吃翔(part5)--基础语法之数据类型转换
  9. pandas基础(part4)--排序/分组/合并
  10. HTML基础(part6)--常用标签之列表