使用javap分析Java位元組碼的一個例子
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 exceptionprivate 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的原創文章,請關注公眾號"汪子熙":
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2723177/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個簡單的例子教會您使用javapJava
- 【Java】JVM位元組碼分析JavaJVM
- 例項分析理解Java位元組碼Java
- Java 位元組碼Java
- JVM(四):深入分析Java位元組碼-下JVMJava
- JVM(三):深入分析Java位元組碼-上JVMJava
- JAVA動態位元組碼Java
- 位元組碼層面深入分析Java列舉類Java
- JAVA——一個漢字佔用多少位元組?Java
- 位元組碼底層分析String
- Java類轉位元組碼工具Java
- Java位元組碼指令表Java
- 輕鬆看懂Java位元組碼Java
- Dalvik 和 Java 位元組碼的比較Java
- Java位元組碼,你還可以搲的更深一些!Java
- Java位元組碼增強技術Java
- 從一個例子看Go的逃逸分析Go
- Java的位元組碼和ABAP load的比較Java
- 位元組碼指令分析 ++i 和 i++
- 位元組碼
- 學習 Java 之 位元組碼驗證Java
- Java 動態性(4) – 位元組碼操作Java
- 從 Java 位元組碼到 ASM 實踐JavaASM
- ASM位元組碼操作類庫(開啟java語言世界通往位元組碼世界的大門)ASMJava
- ASM位元組碼操作類庫:開啟java語言世界通往位元組碼世界的大門ASMJava
- 開啟java語言世界通往位元組碼世界的大門——ASM位元組碼操作類庫JavaASM
- 一個學習 Koa 原始碼的例子原始碼
- 位元組碼技術在模組依賴分析中的應用
- 你需要知道的那些 Java 位元組碼知識Java
- 教你用Java位元組碼做點有趣的事Java
- 使用java動態位元組碼技術簡單實現arthas的trace功能。Java
- Java 位元組的常用封裝Java封裝
- JWebAssembly:Java 位元組碼到 WebAssembly 編譯器WebJava編譯
- Java char 型別究竟佔幾個位元組?Java型別
- Java陣列物件佔用多少個位元組?Java陣列物件
- Java程式碼如何檢視位元組碼及彙編碼Java
- 位元組碼指令
- Java併發雜談(一):volatile的底層原理,從位元組碼到CPUJava