使用javap分析Java字节码的一个例子 SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
I have the following source code in 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();
}
}
Get de-assembled byte code via javap:
Navigate to the part for method way1():
According to instruction list explanation in wiki:
0: invokestatic #42 // Method getInitializedOuter:()Ljava8/Outer; Call static method getInitializedOuter, whose return type is Outer 3: astore_0 Store returned Outer reference to local variable with id 0 4: aload_0 Since in Java source code, the reference outer will be compared against null via outer != null, so here aload_0 loads the reference stored in local variable #0 to stack. 5: ifnull 41 If the current value is null, execution will go to code #41, which is directly return.
or else continue to execute from #8: aload_0 to fetch outer into stack again. Why repeated call a_load_0 for loading outer reference is needed here? Again check the instruction list table:
For instruction ifnull, the value in the stack before executed is value, value is gone after ifnull is executed.
From the list above, we can also see another instruction ifnonnull. So here the interesting fact is, according to the analysis so far, the source code below:
if (outer != null && outer.nested != null && outer.nested.inner != null) {
System.out.println(outer.nested.inner.foo);
}
is actually compiled by Java as the execution approach below:
if (outer == null )
return;
if( outer.nested == null )
return;
if( outer.nested.inner == null)
return;
System.out.println(outer.nested.inner.foo);
The usage of LineNumber Table:
LineNumberTable is one of the optional attributes that holds metadata for debugging purposes. In this case, it specifies which offsets in the bytecode correspond to each line in the original source code. This is useful for printing more informative stack traces and for providing features like single step in the debugger. The example above illustrates the mapping relationship from byte code and original source code.
When change way1 from public to private, in javap output you cannot find byte code for way1() itself any more.
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
上一篇: davinci mail配置
下一篇: react环境搭建
推荐阅读
-
使用SAP CRM中间件从ERP下载Customer的错误消息 SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
-
一个有用的Chrome扩展应用:SAP UI5 Inspector SAP UI5SAPSAP云平台SAP Cloud PlatformSAP成都研究院
-
SAP Fiori应用里出现http request错误的原因分析 SAPSAP云平台SAP Cloud PlatformSAP成都研究院C4C
-
使用SAP CRM中间件从ERP下载Customer的错误消息 SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
-
使用SAP CRM中间件下载customer的错误消息:Number not in interval XXX – XXX SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
-
国内SAP UI5使用者关于性能优化和UI5 Web Component的讨论 SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
-
使用Chrome开发者工具分析JavaScript garbage collector(垃圾回收器)的实现原理 chromeSAPSAP云平台SAP Cloud PlatformSAP成都研究院
-
ABAP Debugging Script(调试器脚本)使用的一些实际例子 sapSAP云平台SAP Cloud PlatformSAP成都研究院Cloud
-
两种使用代码获得SAP CRM product sales status的办法 SAPSAP云平台SAP Cloud PlatformSAP成都研究院ABAP
-
SAP Repository Information System查找Message ID的一个小技巧 SAPSAP云平台SAP Cloud PlatformSAP成都研究院Cloud