TLDR: I didn’t think it would work, and it didn’t.
Today I had a goal to call an established C library from Java, but it uses
longjmp for error reporting.
I had been hoping/planning to use Java Native Access to interact with the libraries. This is just a simple hobby project, so I want to keep it as simple as I realistically can. That means I don’t want to add a C build step to my project at all, not to mention having the build target multiple OS platforms and CPU architectures.
But I didn’t really expect
longjmp to work in Java. I have no idea what the JVM does with the execution environment and I expected
longjmp would interfere with it in a way that would very probably corrupt the JVM’s state.
I tried it anyway. It didn’t work. The program crashed with SIGABRT after
longjmp (running on Linux).
I encountered some things I found a little more interesting than just “it doesn’t work”, though:
jmp_buf’s size isn’t predictable
setjmp requires that you allocate a
jmp_buf to store the environment in.
jmp_buf is defined in the system
setjmp.h. On my 64-bit Linux system,
sizeof(jmp_buf) == 200, and it’s defined as a 1-element array containing a struct, so it can be allocated easily then passed by reference.
I dug into
setjmp.h first to understand it more, and realized the size of
jmp_buf isn’t really predictable:
- It varies by architecture even with the same C library, and
- It’s not specified by the standard that it even has to be a struct or anything. It could just be a handle or whatever.
setjmp could be a macro
The standard doesn’t specify whether
setjmp is a function or macro. JNA can only call functions, since macros are inlined by the compiler at build time.
(I didn’t check how it’s implemented in other C libraries, like MSVCRT on Windows or libSystem on macOS.)
Not exactly related, but I also happened to call
fflush(stdout) from Java. It turns out that
stdout is actually specified in C89/C99 to be a macro. In glibc, it’s also exported as
extern FILE *stdout so I was able to use that, but then my code would not conform to standard.
I guess I’m gonna have to write a C adapter library that’s more Java-friendly.