深入JVM字节码探索assert关键字
引言
如果熟悉 C 语言,那么也许会使用过assert.h
中的assert
函数,在 Java 中的assert
关键字也能够提供运行时断言这一功能,不过不同之处在于,Java 的断言可以在运行中决定是否开启,因此不必重新编译字节码。
本文主要对assert
这个关键字在 JVM 字节码层面的实现原理进行分析,讨论其运行时配置断言启用与禁用的方式。
目录
assert
关键字基础assert
实现原理分析assert
运行时配置启用与禁用
1. assert
关键字基础
class Main {
public static void main(String[] args) {
assert null instanceof Object : "Hello, world!";
}
}
用法很简单,只需要一个参数或者两个参数,在运行时检查第一个参数的值是否为true
。
这段程序直接运行不会输出任何内容,因为默认禁用断言,启用断言可以使用-ea
选项。
$ javac Main.java
$ java -ea Main
Exception in thread "main" java.lang.AssertionError: Hello, world!
at Main.main(Main.java:3)
2. assert
实现原理分析
首先看一看上面这个类的字节码:
class Main {
static final boolean $assertionsDisabled;
Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field $assertionsDisabled:Z
3: ifne 23
6: aconst_null
7: instanceof #3 // class java/lang/Object
10: ifne 23
13: new #4 // class java/lang/AssertionError
16: dup
17: ldc #5 // String Hello, world!
19: invokespecial #6 // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
22: athrow
23: