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的原创文章,请关注公众号"汪子熙":
相关推荐
`javap`是Java开发工具包(JDK)的一部分,用于反汇编Java字节码。它可以显示已编译的Java类文件中的内容,包括类和接口的签名、字段、方法等。这对于理解Java字节码的工作方式非常有用。 #### 三、案例分析:Java...
本文将深入探讨Java中的方法调用、值传递与引用传递,并通过字节码分析来进一步理解这些概念。 首先,我们来看方法调用。在Java中,方法是一组完成特定任务的代码块,可以通过方法名来调用执行。方法调用的基本语法...
接下来,文章通过一个简单的Java类编译成Class文件的例子来说明如何逐字节分析字节码。Class文件开头的四个字节(u4)是魔数(Magic Number),通常为"cafebabe",这是Class文件的标记,用于快速识别文件类型。紧...
通过使用像`javap`这样的工具,我们可以查看Java字节码,进一步了解这些过程。字节码是JVM直接执行的低级指令,它揭示了编译器如何将源代码转换为运行时的指令。理解字节码可以帮助我们更好地理解Java程序的工作原理...
javap 命令是 JDK 自带的一个工具,它可以对代码反编译,也可以查看 Java 编译器生成的字节码,对代码的执行过程进行分析,了解 JVM 内部的工作。javap 命令可以将 class 文件反编译成易于阅读的格式,展示类的结构...
Java 语言提供了 `javap` 工具来反编译字节码文件,通过分析反编译后的字节码文件可以从更深层面了解对象的初始化过程。 输 入 cmd 命令,进入命令方式界面。输 入 `javap -verbose S`,屏幕上将显示类 `S` 的编译...
#### 五、Java字节码文件 - **知识点**: - 编译Java源文件后生成的字节码文件扩展名为 `.class`。 - 字节码文件可以在任何支持Java虚拟机(JVM)的平台上运行。 #### 六、Java程序开发流程 - **知识点**: - 开发...
这一过程将生成可执行的Java字节码文件,其扩展名为`.class`。例如,上面的命令会生成`X.class`文件。这里,我们实际上是在编译源代码为一种中间语言——字节码(Bytecode),而不是直接编译为特定硬件平台的机器...
ASM是一个强大的Java字节码操控和分析框架,它可以直接生成和修改Java类和接口的字节码。在本文中,我们将深入探讨如何使用ASM库中的`ClassWriter`类来生成接口。`ClassWriter`是ASM提供的一种用于创建字节码表示的...
2. **JDK中的工具**:JDK(Java Development Kit)包含了多种工具,其中`javac`是编译器,`java`是解释器,`jdb`是调试器,而`javap`是反编译工具,用于查看类文件的字节码信息。 3. **main方法**:Java程序的入口...
javap是JDK提供的一个反编译工具,可以查看.class文件中的Java字节码。使用它,开发者可以查看生成的字节码,这有助于理解Java虚拟机是如何执行程序的。例如: ```bash javap -c com.example.MyClass ``` 这条命令...
Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 ...
- **工具**:`javac`编译源代码为字节码,`java`执行字节码,`jdb`用于调试,`javap`反编译,`javadoc`生成API文档,`appletviewer`解释Java小应用程序。 6. **Java类型系统** - **原始类型(Primitive Types)**...
3. 使用`javac`编译器将源代码编译为字节码文件,命令为:`javac Test.java`,生成`Test.class`文件。 4. 最后,通过`java`命令执行字节码文件,如:`java Test`,这会将`Test.class`加载到JVM并运行。 ### Java...
javap.exe是Java反汇编器,可以将编译后的class文件反汇编成可读的Java字节码。 2. Java基础语法: 在Java中,基本数据类型包括int、byte、short、long、float、double、char和boolean。int[] a = new int[8]; 创建...
介绍了Java堆的分析方法,以一个实例为基础,展示对堆的分析过程。 第九课 锁 baise锁 轻量级锁 自旋锁 介绍JVM中对多线程锁的实现。 第十课 class文件结构 ASM库介绍 介绍JVM规范中的最重要的内容——Class文件...
在反编译过程中,我们可以使用 javap 命令来反编译字节码,从而获得源代码。 在 Java 中,反编译是一个非常重要的技术,它可以帮助我们了解 Java 程序的执行过程和机理。通过反编译,我们可以了解 Java 程序的内部...
Java 语言中的 `i=i++` 这个表达式是一个典型的自增运算符使用的例子,它揭示了 Java 编译器处理这种复合赋值语句的机制与 C/C++ 的不同之处。在 Java 中,`i++` 和 `++i` 两者的主要区别在于操作顺序:`i++` 是先...
通过使用`javap`命令,可以查看一个简单类的字节码信息,从而验证这一点。 **5. 继承的原则** - 子类可以继承父类中声明为`public`和`protected`的成员变量和方法。 - 如果子类和父类位于同一个包内,子类还可以...