专栏首页Jerry的SAP技术分享一个简单的例子教会您使用javap
原创

一个简单的例子教会您使用javap

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的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一个简单的例子教会您使用javap

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

    Jerry Wang
  • 如何使用ABAP Restful API进行代码的全文搜索

    使用这个代码全文搜索的前提条件,是在事务码SFW5里激活业务功能:SRIS_SOURCE_SEARCH

    Jerry Wang
  • Chrome开发者工具中Elements(元素)断点的用途

    SAP Engagement Center UI的这个按钮会每秒钟刷新一次,显示页面已经打开了多长时间。

    Jerry Wang
  • 一个简单的例子教会您使用javap

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

    Jerry Wang
  • JPA + EclipseLink + SAP云平台 = 运行在云端的数据库应用

    JPA(Java Persistence API)的实现Provider有Hibernate,OpenJPA和EclipseLink等等。

    Jerry Wang
  • python之string模块的find

    解释:str:被查找“字串”(气味字符串的函数);pos_start:查找的首字母位置(从0开始计数。默认:0);pos_end:查找的末 尾位置(不包括末尾位...

    py3study
  • CRM和C4C product category hierarchy的可编辑性控制逻辑

    从ERP导入到CRM系统的Product Hierarchy,在CRM系统切换成编辑模式时,会收到一条提示信息:

    Jerry Wang
  • 全场景助力“新基建” | 音视频解决方案系列课程

    ? 赶紧扫码预约课程吧! ? 腾讯云通信 一直致力于 让每个企业 都享受智慧服务带来的改变 END 未来可期 ? 长按扫码关注腾讯云通信官方微信公众号 以获...

    腾讯即时通信IM
  • Python3通过JDBC访问非Kerberos环境的Impala

    在前面Fayson介绍了在Python2的环境下《如何使用Python Impyla客户端连接Hive和Impala》及《Python3环境通过JDBC访问非K...

    Fayson
  • Python3环境通过JDBC访问非Kerberos环境的Hive

    在前面Fayson介绍了在Python2的环境下《如何使用Python Impyla客户端连接Hive和Impala》,本篇文章Fayson主要介绍在Pytho...

    Fayson

扫码关注云+社区

领取腾讯云代金券