GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing javaevolved.dev — Calling out to C code from Java | java.evolved
Language
Advanced
Calling out to C code from JavaFFM lets Java call C libraries directly, without JNI boilerplate or C-side Java knowledge. Code Comparison
✕ Java 1.1+
public class CallCFromJava {
static { System.loadLibrary("strlen-jni"); }
public static native long strlen(String s);
public static void main(String[] args) {
long ret = strlen("Bambi");
System.out.println("Return value " + ret); // 5
}
}
// Run javac -h to generate the .h file, then write C:
// #include "CallCFromJava.h"
// #include <string.h>
// JNIEXPORT jlong JNICALL Java_CallCFromJava_strlen(
// JNIEnv *env, jclass clazz, jstring str) {
// const char* s = (*env)->GetStringUTFChars(env, str, NULL);
// jlong len = (jlong) strlen(s);
// (*env)->ReleaseStringUTFChars(env, str, s);
// return len;
// }
✓ Java 22+
void main() throws Throwable {
try (var arena = Arena.ofConfined()) {
// Use any system library directly — no C wrapper needed
var stdlib = Linker.nativeLinker().defaultLookup();
var foreignFuncAddr = stdlib.find("strlen").orElseThrow();
var strlenSig = FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS);
var strlenMethod = Linker.nativeLinker() .downcallHandle(foreignFuncAddr, strlenSig);
var ret = (long) strlenMethod.invokeExact(arena.allocateFrom("Bambi"));
System.out.println("Return value " + ret); // 5
}
}
// Your own C library needs no special Java annotations:
// long greet(char* name) {
// printf("Hello %s\n", name);
// return 0;
// }
See a problem with this code? Let us know.
Why the modern way wins
👁
C code stays plain CThe C function requires no JNI annotations or JNIEnv boilerplate — any existing C library can be called as-is. ⚡
More flexibleDirectly call most existing C/C++ libraries without writing adapter code or generating header files. 🛠️
Easier workflowNo need to stop, run javac -h, and implement the interface defined in the generated .h file. Old Approach
JNI (Java Native Interface)
Modern Approach
FFM (Foreign Function & Memory API)
Since JDK
22
Difficulty
Advanced
JDK Support
Calling out to C code from Java
Available
Standardized in JDK 22 (March 2024); previously incubating since JDK 14 How it works
Java has two approaches for calling native C/C++ code: the traditional JNI and the modern FFM API. With JNI, you declare a method as native, run javac -h to generate a C header file, then implement the function using the cumbersome JNI C API (JNIEnv, jstring, etc.). FFM, introduced as a standard API in Java 22, eliminates all of that: C code is just plain C — no JNI conventions needed. This makes it far easier to call existing C/C++ libraries without modification. The Java side uses Arena for safe off-heap memory management and MethodHandle for the downcall, ensuring both flexibility and safety. Related Documentation
Proof
Related patterns
I/O
Advanced
File memory mappingJava 8
try (FileChannel channel =
FileChannel.open(path,
StandardOpenOption.READ,
StandardOpenOption.WRITE)) {
MappedByteBuffer buffer =
channel.map(
FileChannel.MapMode.READ_WRITE,
0, (int) channel.size());
// Limited to 2GB
// Freed by GC, no control
}
Java 22+
FileChannel channel =
FileChannel.open(path,
StandardOpenOption.READ,
StandardOpenOption.WRITE);
try (Arena arena = Arena.ofShared()) {
MemorySegment segment =
channel.map(
FileChannel.MapMode.READ_WRITE,
0, channel.size(), arena);
// No size limit
// ...
} // Deterministic cleanup
JDK 22+
→
Language
Beginner
Compact source filesJava 8
public class HelloWorld {
public static void main(String[] args) {
System.out.println(
"Hello, World!");
}
}
Java 25
void main() {
IO.println("Hello, World!");
}
JDK 25+
→
Language
Beginner
Unnamed variables with _Java 8
try {
parse(input);
} catch (Exception ignored) {
log("parse failed");
}
map.forEach((key, value) -> {
process(value); // key unused
});
Java 22+
try {
parse(input);
} catch (Exception _) {
log("parse failed");
}
map.forEach((_, value) -> {
process(value);
});
JDK 22+
→
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |