admin管理员组文章数量:1125947
I have a .NET 9 project that gets published as a native AOT library for Windows and Linux. This library exports some methods, that are in turn called from Java via FFM from Windows or Linux again. In general this works pretty well. The native library does some fairly complex operations and I can use it without issues under Windows. Under Linux this works as well except for one error: After the program finishes, I get a segfault from Java. The calls itself seem to work well, I get all the expected results and the calls itself don't seem to cause the error, i.e. the program runs to the end and causes the segfault afterwards.
I can reproduce this under a dedicated Debian 12 installation and with a WSL2 Debian distro.
I have reduced this to an absolute minimal example without any logic that still reproduces that:
using System.Runtime.InteropServices;
namespace NativeTest
{
public class Class1
{
[UnmanagedCallersOnly(EntryPoint = "BasicTest")]
public static void BasicTest()
{
Console.WriteLine("Hello from native");
}
}
}
csproj:
<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>
</PropertyGroup>
</Project>
Java:
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
Linker linker = Linker.nativeLinker();
SymbolLookup library = SymbolLookup.libraryLookup("./NativeTest.so", arena);
MethodHandle myMethod = linker.downcallHandle(library.find("BasicTest").orElseThrow(), FunctionDescriptor.ofVoid());
myMethod.invoke();
} catch (Throwable t) {
System.out.println("Error is " + t.getMessage());
}
}
}
Executed using:
dotnet publish -r linux-x64 -c Debug
javac Main.java
java --enable-native-access=ALL-UNNAMED Main
Results in:
Hello from native
[1] 815 segmentation fault (core dumped) java --enable-native-access=ALL-UNNAMED Main
Versions:
# java --version
java 23.0.1 2024-10-15
Java(TM) SE Runtime Environment (build 23.0.1+11-39)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)
# dotnet --version
9.0.101
What am I missing here?
I have a .NET 9 project that gets published as a native AOT library for Windows and Linux. This library exports some methods, that are in turn called from Java via FFM from Windows or Linux again. In general this works pretty well. The native library does some fairly complex operations and I can use it without issues under Windows. Under Linux this works as well except for one error: After the program finishes, I get a segfault from Java. The calls itself seem to work well, I get all the expected results and the calls itself don't seem to cause the error, i.e. the program runs to the end and causes the segfault afterwards.
I can reproduce this under a dedicated Debian 12 installation and with a WSL2 Debian distro.
I have reduced this to an absolute minimal example without any logic that still reproduces that:
using System.Runtime.InteropServices;
namespace NativeTest
{
public class Class1
{
[UnmanagedCallersOnly(EntryPoint = "BasicTest")]
public static void BasicTest()
{
Console.WriteLine("Hello from native");
}
}
}
csproj:
<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>
</PropertyGroup>
</Project>
Java:
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
Linker linker = Linker.nativeLinker();
SymbolLookup library = SymbolLookup.libraryLookup("./NativeTest.so", arena);
MethodHandle myMethod = linker.downcallHandle(library.find("BasicTest").orElseThrow(), FunctionDescriptor.ofVoid());
myMethod.invoke();
} catch (Throwable t) {
System.out.println("Error is " + t.getMessage());
}
}
}
Executed using:
dotnet publish -r linux-x64 -c Debug
javac Main.java
java --enable-native-access=ALL-UNNAMED Main
Results in:
Hello from native
[1] 815 segmentation fault (core dumped) java --enable-native-access=ALL-UNNAMED Main
Versions:
# java --version
java 23.0.1 2024-10-15
Java(TM) SE Runtime Environment (build 23.0.1+11-39)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)
# dotnet --version
9.0.101
What am I missing here?
Share Improve this question asked 2 days ago LennartLennart 10.3k16 gold badges70 silver badges95 bronze badges 2- The AOT Lib, is it 3rd Party or do you have complete control over all the code? – Fildor Commented 2 days ago
- 1 I have full control over all C# and Java code. – Lennart Commented 2 days ago
1 Answer
Reset to default 1It seems that the issue was the type of Arena (Arena.ofConfined()
). If I use an automatic arena (Arena.ofAuto()
), I don't get a segfault:
public static void main(String[] args) throws Throwable {
Arena arena = Arena.ofAuto();
Linker linker = Linker.nativeLinker();
SymbolLookup library = SymbolLookup.libraryLookup("./NativeTest.so", arena);
MethodHandle myMethod = linker.downcallHandle(library.find("BasicTest").orElseThrow(), FunctionDescriptor.ofVoid());
myMethod.invoke();
}
The difference seems to be that a confined arena has a specifc single owner thread, and that automatic arenas are managed by the garbage collector (see Docs).
Since that doesn't really matter in my case (I initially just used the samples from the docs), I'll go with an automatic arena.
本文标签:
版权声明:本文标题:c# - Calling library generated with .NET Native AOT causes segfault when called from Java on Linux - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736637721a1945920.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论