native 约束与兼容性
2026年8月12日 上午11:24:42
Solon AOT / Native 对代码有一些硬约束和软建议。硬约束违反会在 AOT 或 native 构建阶段直接报错;软建议是为了让打包更顺利。写代码前先过一遍本文。
1、代理组件四约束(硬约束)
Solon 中被代理的 bean(如 @Component 且需要 AOP 增强的类),AOT 阶段会为其生成静态代理类。以下四类不能作为代理组件,违反会在 AOT 阶段直接抛错:
| 约束 | 报错信息 | 说明 |
|---|---|---|
| 抽象类 | Abstract classes are not supported as proxy components | abstract 类不做代理 |
| final 类 | Final classes are not supported as proxy components | final 类无法继承生成代理 |
| 非 public 类 | Not public classes are not supported as proxy components | 包内/私有类不做代理 |
| 泛型类 | Generic type classes are not supported as proxy components | 带类型参数的类不做代理 |
应对:
- 这类 bean 如果不需要 AOP 增强,可以不加代理(如不配置拦截、不标记需要增强的注解);
- 需要增强则必须改造成 public 非 final 非泛型非抽象类。
2、启动副作用约束(硬约束)
AOT 阶段会真实启动一次应用来收集容器信息:
- 主类
main里的初始化逻辑会执行(发消息、写库、定时任务、预热缓存等); - 启动依赖的外部服务(DB、Redis、配置中心)在打包机上必须可用;
- 启动抛异常会中断 maven 打包(
SolonAotProcessor会把异常向上抛)。
应对:把启动副作用代码放进条件判断:
public class DemoApp {
public static void main(String[] args) {
Solon.start(DemoApp.class, args, app -> {
// 打包机上的 AOT 处理阶段,跳过有副作用的初始化
if (NativeDetector.isNotAotRuntime()) {
initSendMessage();
initWarmCache();
}
});
}
}
3、环境约束(硬约束)
| 阶段 | 约束 |
|---|---|
-P aot | 任意 JDK 8+(v3.7.2 起) |
-P native | GraalVM JDK 17+(native-image 组件) |
| 操作系统 | 构建机需安装对应原生工具链: macOS(Xcode Command Line Tools) Linux(gcc、glibc-devel、zlib-devel) Windows(Visual Studio Build Tools) |
| 内存 | native-image 构建较耗内存,建议构建机 ≥ 8G 可用内存 |
4、代码编写建议(软建议)
| 建议 | 说明 |
|---|---|
| 反射只作用于已登记类 | 动态反射的目标类,要么由 AOT 自动登记,要么手动登记 |
不依赖 Class.forName 动态加载业务类 | 运行期动态加载的类无法被 AOT 探测 |
不依赖 ClassLoader.getResources 扫资源 | 用 ScanUtil / ResourceUtil(native 下从 solon-resource.json 读取) |
| 不用动态编译 / 运行时字节码生成 | 换脚本引擎或表达式工具(Solon 生态的表达式组件) |
| 第三方库选型先验证 | 参考 《native 项目开发定制》 的 A/B/C/D 分类,新项目先做技术选型实验 |
| 需要序列化的类显式登记 | 方法参数/返回值会自动登记,其它 registerSerialization |
5、运行时环境探测(NativeDetector)
内核提供 org.noear.solon.core.runtime.NativeDetector,用于区分三种运行环境:
| 方法 | 返回 true 的场景 | 典型用途 |
|---|---|---|
isAotRuntime() | AOT 处理阶段(打包时启动的那次) | 跳过打包机上的副作用初始化 |
inNativeImage() | native 可执行文件运行时 | 切换原生环境专属逻辑 |
isNotAotRuntime() | 非 AOT 处理阶段(普通运行 + native 运行) | 与 isAotRuntime() 相反 |
notInNativeImage() | 非 native 镜像(JVM 运行 + AOT 处理阶段) | 与 inNativeImage() 相反 |
常见写法:
- 普通运行时与 native 运行时行为一致 → 用
isNotAotRuntime(); - 仅 native 才有的优化 → 用
inNativeImage()。