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 setjmp and 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 setjmp and 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:

  1. It varies by architecture even with the same C library, and
  2. 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.