---
title: "native 了解 Aot 技术"
---

### 1、Java Aot（偏概念性）

Aot 是 Ahead-Of-Time 的缩写，大家都知道 Java 是一个半编译、半解释型语言。它把 Java 文件编译成 class 文件，之后 JVM 解释执行 class 文件，JVM 可以把 class 文件解释为对应的机器码，这个就是所谓的 JIT。Aot 则是直接把 class 文件编译系统的库文件，不在依靠 JIT 去做这个事情。

* 好处是：

内存占用低，启动速度快，可以无需 runtime 运行，直接将 runtime 静态链接至最终的程序中

* 坏处是：

无运行时性能加成，不能根据程序运行情况做进一步的优化，程序运行前编译会使程序安装的时间增加


### 2、Solon Aot（偏实践性）

Solon Aot （Ahead-of-Time Processing） 是 Solon Native 的关键技术，参与了 Java Aot 的部分生成命周期。它在编译时，将所有框架可探测到的：

* 动态类代理预编译为Java代码（否则是由Asm字节码生成）
* Jdk 代理接口进行元信息登记
* 反射类进行元信息登记
* 资源文件进行元信息登记
* 等

大概的编译过程：

* 常规编译
* 编译时执行 SolonAotProcessor（solon-aot 里的处理类）
  * 会启动程序（通过程序的自然运行，收集容器信息、原生元信息等）
* 编译时生成动态类代理并编译为class文件
* 编译为原生程序 



> **注意**：AOT 阶段会**真实启动一次应用**。主类 `main` 里的初始化逻辑会执行，依赖的外部服务（DB/Redis 等）在打包机上必须可用，启动异常会中断打包。有副作用的初始化请用 `NativeDetector.isNotAotRuntime()` 包裹（见 《native 约束与兼容性》）。

自动处理的具体范围（哪些类、哪些资源、哪些序列化）见 《native 自动化处理清单》)。

### 3、RuntimeNativeRegistrar

Solon Aot 在自动处理之外，还提供了重要一项目定制接口"RuntimeNativeRegistrar"：

```java
public interface RuntimeNativeRegistrar {
    void register(AppContext context, RuntimeNativeMetadata metadata);
}
```

用于在 SolonAotProcessor 执行时，（由开发者）添加无法自动处理的元信息登记。

### 4、NativeDetector


Solon 内核还提供了一个环境探测工具（用于开发时，做编码控制），共四个方法：

| 方法 | 返回 true 的场景 |
| --- | --- |
| `isAotRuntime()` | AOT 处理阶段（打包时启动的那次，对应属性 `solon.aot.processing`） |
| `isNotAotRuntime()` | 非 AOT 处理阶段（普通运行 + native 运行） |
| `inNativeImage()` | native 镜像运行时（对应属性 `org.graalvm.nativeimage.imagecode`） |
| `notInNativeImage()` | 非 native 镜像（JVM 运行 + AOT 处理阶段） |

### 5、静态扩展约定（native 运行时为什么还能反射/扫描）

Solon 内核通过 `ClassUtil.tryInstance("org.noear.solon.extend.impl.XxxExt")` 的**静态扩展约定**替换默认行为。solon-aot 提供了三套扩展实现：

| 扩展类 | 替换的内核行为 |
| --- | --- |
| `RuntimeServiceExt` | 原生运行时接管运行时服务（含元数据加载） |
| `ScannerExt` | 原生运行时接管资源扫描（从 solon-resource.json 读取） |
| `ReflectionExt` | 原生运行时接管反射（从 reflect-config.json 读取） |

这也是 native 环境下 `ScanUtil` / `ResourceUtil` / `ReflectUtil` 依然可用的原因：它们不是"扫描 classpath"，而是从**构建时登记的元数据**里取。

### 6、多模块合并机制

GraalvmUtil 在 native 运行时通过 `ExtendLoader.load(Solon.cfg().extend(), false)` 加载所有扩展模块，**合并各模块**的 `reflect-config.json` 与 `solon-resource.json`：

* 每个模块（含子模块）的 AOT 产物都放在自己的 `META-INF/native-image/<包路径>/` 下
* 主模块 native 构建时按 extend 配置逐个加载合并
* 这就是多模块项目需要"所有模块先 mvn install"的原因（见 《aot 项目编译示范》）




### 7、批量获取资源或反射方法、反射字段

Native 环境上，是不能直接通过 `ClassLoader:getResources`（获取资源集合），`Class:getMethods()`（获取类的公有方法集合），需要通过从注册元数据里获取。

需要借用两个内核工具：

| 工具                                        | 描述 | 
| ------------------------- | -------- | 
| `ScanUtil`           | 兼容原生编译的资源或文件扫描 |
| `ResourceUtil`     | 兼容原生编译的资源获取或查找     | 
| `ReflectUtil`        | 兼容原生编译的基础反射工具 |


