Solon v4.0.5

native 故障排查与 FAQ

</> markdown
2026年8月12日 上午11:32:48

native 构建出错是常态(native 导引 里有心理准备提示)。本文把最常见的报错、定位思路和常见问题汇总成一张对照表,按图索骥即可。

1、典型报错对照表

报错/现象原因处理
Abstract classes are not supported as proxy components代理组件是抽象类去掉代理或改造类(见 《native 约束与兼容性》)
Final classes are not supported as proxy components代理组件是 final 类去掉 final
Not public classes are not supported as proxy components代理组件不是 public改成 public
Generic type classes are not supported as proxy components代理组件是泛型类去掉类型参数
打包时提示连接 DB/Redis 失败AOT 阶段真实启动了应用,依赖本地服务打包前起好服务,或 NativeDetector.isNotAotRuntime() 跳过(见 《native 约束与兼容性》)
ClassNotFoundException: xxx(native 运行时)类未被登记反射/未被包含target/classes/META-INF/native-image/.../reflect-config.json 是否登记;没有则手动登记
MissingReflectionRegistrationError反射调用目标类未登记在 《native 项目开发定制》 的 Registrar 里补 registerReflection
java.io.FileNotFoundException(资源找不到)资源未登记registerResourceInclude
NoSuchMethodError / NoSuchFieldError(native 运行时)方法/字段未登记registerMethod / registerField 或对应 MemberCategory
序列化抛 InvalidClassException / 反序列化失败类未登记序列化registerSerialization(方法参数/返回值会自动登记,见 《native 自动化处理清单》)
native 构建 OOM / 卡死构建机内存不足加内存或调整 native-image 构建参数
native 构建失败:找不到 gcc/链接器缺 OS 原生工具链装 Xcode CLT / gcc+glibc-devel / VS Build Tools(见 《native 环境准备》)
AOT 阶段 main 抛业务异常导致打包中断启动代码有问题排查启动逻辑,或条件化跳过(同第 5 行)
运行期 ScanUtil 扫不到资源资源未进 solon-resource.json确认资源在 include 清单里,或用 registerResourceInclude 登记

2、标准排查流程

  1. 确认 AOT 产物是否生成:看 target/classes/META-INF/native-image/<应用包路径>/ 下 5 个 json/properties 文件是否存在(《native 自动化处理清单》)。
  2. 确认报错类是否已登记:在 reflect-config.json / serialization-config.json / resource-config.json 里搜报错的类名或资源名。
  3. 没登记 → 补登记:在 RuntimeNativeRegistrar 实现里补对应 API(参考 《native RuntimeNativeRegistrar API 参考》),重新打包。
  4. 已登记仍报错:检查登记粒度是否够(比如只登记了 INTROSPECT 但需要 INVOKE;只登记了类但没登记字段/方法)。
  5. 还不行:看是否用了动态编译/字节码生成(A/B 类第三方库),考虑换库或换方案。

3、FAQ

  • Q1:需要手动加 solon-aot 依赖吗?

不需要。solon-parent-P aot / -P native profile 会自动引入 solon-aot 依赖并挂载 process-aot 插件。手动加依赖只在不用官方 profile 时才有意义。

  • Q2:-P aot-P native 有什么区别?

-P aot:执行 AOT 处理(生成代理源码 + 原生元数据),任意 JDK 可用;-P native:AOT 处理 + GraalVM 原生编译,需要 graalvm jdk17+,且启用官方可达性元数据仓库。

  • Q3:为什么打包时我的 main 方法会被执行?

AOT 需要"真实启动"应用来收集容器信息,这是设计行为。启动副作用代码用 NativeDetector.isNotAotRuntime() 包裹即可。

  • Q4:为什么 native 下 Class.forName 找不到类?

native 镜像只包含构建时可达的类。运行期动态加载的类不会进入镜像,需手动登记并确认该类被包含。

  • Q5:native 镜像能跑 Java 序列化吗?

能,但序列化类必须登记(registerSerialization)。方法参数/返回值会自动登记,其余需手动。

  • Q6:为什么 native 镜像比 JVM 包大 / 小?

native 只打包可达代码,通常更小;但大量反射登记(尤其 INVOKE)会增大镜像。按需登记、多用 INTROSPECT 少用 INVOKE 可控制体积。

  • Q7:多模块项目 AOT 怎么处理?

只有主模块执行 AOT,其它模块常规构建。所有模块先 mvn install,主模块 AOT 时通过扩展加载机制合并各模块的 reflect-config.json / solon-resource.json(见 《aot 项目编译示范》)。

  • Q8:第三方库支持情况怎么判断?

按 《native 项目开发定制》 的 A/B/C/D 分类:D 类(自带元数据)直接用;C 类补少量配置;B 类要实验调配置;A 类(动态编译/字节码)不支持。