从 AOT 编译的二进制文件中提取 Java 类信息
Java 领域的预编译(AOT)编译一直是一个备受争议的话题,但直到 GraalVM 的出现,才有了能够实现良好 AOT 编译的工具,更不用说推动整个生态系统了。尽管 GraalVM 提供了 native-image 工具来有效地协助开发者进行 AOT 编译,但由于 Java 生态系统的复杂性和多样性,特别是在各种常用框架中广泛使用反射和代理技术,要实现 Java 应用程序的开箱即用 AOT 编译仍然非常具有挑战性。
Spring Native 项目
得益于 Spring Framework 团队的 Spring Native 项目,他们能够通过 Maven 或 Gradle 插件实现项目的一键 AOT 编译。然而,目前它仅适用于 Spring Boot 项目。
请使用 Spring Native 生成 AOT 编译的 Java 程序
以下是生成 AOT 编译 Java 应用程序的官方 Spring Native 示例(测试环境:Ubuntu 20.04,Docker 20.10.6)
git clone https://github.com/spring-projects-experimental/spring-native.git
cd spring-native/sample/petclinic-jpa
./build.sh
经过相当长的编译时间和大量的内存消耗后,我们可以在 target 目录中获得一个 AOT 编译的 Java 程序。这是一个独立的二进制文件,可以在没有任何依赖的情况下独立运行。

petclinic-jpa 是由 AOT 编译生成的程序,可以直接运行
从 AOT 编译的二进制文件中提取 Java 类信息
Java 代码保护一直是过去非常困难的问题,而 AOT 也被认为是 Java 代码保护的一种解决方案。不幸的是,许多 Java 程序现在无法脱离框架。由于框架的复杂性,即使由 AOT 编译的程序也必须在最终生成的二进制文件中包含类信息。这些 class 文件实际上整齐地排列在二进制文件的资源区域中。
以下工具可以从 AOT 编译的二进制文件中扫描和提取类信息
https://github.com/3-keys/binary-classfile-reader
git clone https://github.com/3-keys/binary-classfile-reader
cd binary-classfile-reader
./gradlew run --args='<二进制文件路径> <输出目录>'
以上一步获得的 petclinic-jpa 为例,从中提取类信息并与源代码进行比较。可以看到 model 信息、controller 信息和 service 信息都可以被获取。
