.NET Native AOT生成的库在Linux下被Java调用后触发段错误
.NET 9 Native AOT共享库Linux下Java FFM调用后段错误的解决方案
解决步骤
1. 修改项目配置文件(csproj)
在<PropertyGroup>中添加<NativeLibrary>true</NativeLibrary>属性,明确告知.NET将该项目编译为供其他进程动态加载的原生库,而非独立可执行文件:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net9.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <IsTrimmable>True</IsTrimmable> <IsAotCompatible>True</IsAotCompatible> <PublishAot>True</PublishAot> <LangVersion>latest</LangVersion> <NativeLibrary>true</NativeLibrary> <!-- 新增配置 --> </PropertyGroup> </Project>
2. 使用Release模式发布AOT库
Debug模式的Native AOT编译会保留大量调试逻辑和未优化代码,容易加剧跨运行时的资源冲突问题,改用Release模式发布:
dotnet publish -r linux-x64 -c Release
原因分析
- 默认情况下,未设置
<NativeLibrary>true</NativeLibrary>时,.NET Native AOT编译的共享库会沿用独立可执行文件的初始化/终止逻辑,包含进程级别的资源清理操作。 - 当Java的
Arena释放并卸载该共享库时,.NET运行时会尝试执行进程级的终止流程,而此时Java进程仍在运行,这种跨运行时的资源清理冲突直接导致了段错误。 - 设置
<NativeLibrary>true</NativeLibrary>后,.NET会调整运行时行为,适配被外部进程动态加载的场景,避免在库卸载时触发进程级别的资源清理,从而解决冲突。
验证
重新发布库后,执行以下命令验证:
javac Main.java java --enable-native-access=ALL-UNNAMED Main
此时程序会正常输出Hello from native,且不会触发段错误。
内容的提问来源于stack exchange,提问作者Lennart
相关产品推荐
相关产品推荐

