-
Notifications
You must be signed in to change notification settings - Fork 3
Upcall Guide
squid233 edited this page Aug 10, 2025
·
3 revisions
Upcalls are calls from native code back to Java code. OverrunGL wraps upcalls into a functional interface which you may use lambda to define.
For example, the GLFWerrorfun in C is defined as:
typedef void (* GLFWerrorfun)(int error_code, const char* description);In Java, this is:
@FunctionalInterface
public interface GLFWErrorFun extends Upcall {
void invoke(int error_code, MemorySegment description);
}The description is not converted to String.
The upcall interface typically provides an alloc method that allows you to allocate an upcall stub with a specified arena.
glfwSetErrorCallback(GLFWErrorFun.alloc(Arena.global(), (error_code, description) ->
System.err.println("GLFW error " + error_code + ": " + MemoryUtil.nativeString(description))));- The implementation of upcall interfaces should not throw any exceptions, or the JVM will terminate abruptly.
- The automatic arena (
Arena::ofAuto) should not be used without holding a strong reference of the upcall stub. JVM is unable to trace usages of upcall after one passed to native code, causing use-after-free issues.
A minimal reproducible example of how automatic arena causes JVM crash:
void main() {
glfwSetErrorCallback(GLFWErrorFun.alloc(Arena.ofAuto(), (_, _) -> {}));
// after passing to native code, the upcall stub allocated above is no longer used in Java code,
// making garbage collector think it not used
System.gc(); // try to close arena
glfwInitHint(0, 0); // JVM crash!
}A simple fix to this is to introduce a variable, so that the upcall stub will be valid until main returns.
var stub = GLFWErrorFun.alloc(Arena.ofAuto(), ...);
glfwSetErrorCallback(stub);Copyright (c) 2022-2025 Overrun Organization. In case of any problems with this wiki, please search or create an issue.