I'm porting my JNA-based library to "pure" Java using the Foreign Function and Memory API (JEP 424) in JDK 19.
I've successfully implemented the sysctl()
function and am fetching values using:
public static MethodHandle sysctl = Linker.nativeLinker().downcallHandle(
SYSTEM_LIBRARY.lookup("sysctl").orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_INT,
ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS,
ValueLayout.ADDRESS, ValueLayout.JAVA_LONG));
In the process of debugging before getting this working, I was occasionally getting a -1 return value:
Upon successful completion, the value 0 is returned; otherwise the value -1 is returned and the global variable errno is set to indicate the error.
In JNA, this is easily obtainable using Native.getLastError()
. This answer shows how I could write code in JNI to fetch it, but the whole point of JEP 424 is to remove the need for JNA or JNI.
The Windows API has a helpful GetLastError function that can be mapped, as demonstrated in this test in the JDK
However, I was unable to find any native function on macOS that I could map to return errno
. The closest I have found is perror()
which prints the error to STDERR:
public static MethodHandle perror = Linker.nativeLinker()
.downcallHandle(SYSTEM_LIBRARY.lookup("perror").orElseThrow(),
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS));
While output to STDERR was helpful in the near term, I'd like to use this value for exception handling/error messages.
This seems a common enough use case that there should be a method in the JDK for it, but I can't find it.
Any ideas other than temporarily redirecting STDERR into a string I can parse?