如何通过JNI从Java调用Go函数?及Go实现类JNA跨语言调用方案
Alright, let's tackle both of your questions about connecting Java and Go—this is a super common use case, so I’ll walk you through each step clearly.
JNI (Java Native Interface) lets Java talk to native code, and since Go can compile to C-compatible shared libraries via cgo, we can use that as a bridge. Here's how to make it work:
Step 1: Write your Go code with cgo exports
First, you need to mark your Go functions for export to C using the //export comment, and include the mandatory import "C" line (it has to be on its own line, no other imports grouped with it). Here's your example code, with a tiny addition (an empty main function, since we’re compiling a library but Go requires a main package):
package main import "fmt" import "C" //export Add func Add(x, y int) int { fmt.Printf("Go says: adding %v and %v\n", x, y) return x + y } // Empty main function required for main package (won't execute when built as a library) func main() {}
Step 2: Compile Go to a C shared library
Run this command to build a shared library that C (and JNI) can use. The exact output extension depends on your OS:
- Linux/macOS:
libadd.so(macOS might use.dylibinstead) - Windows:
add.dll
Command:
go build -buildmode=c-shared -o libadd.so add.go
This generates two files: libadd.so (the shared library) and libadd.h (a C header with the exported function signatures).
Step 3: Write your Java JNI code
Create a Java class that declares the native method and loads the shared library:
public class GoJNI { // Load the compiled Go shared library static { System.loadLibrary("add"); // Omit prefix/suffix like lib/.so/.dll } // Declare the native method that maps to our Go Add function private native int add(int x, int y); public static void main(String[] args) { GoJNI app = new GoJNI(); int result = app.add(3, 5); System.out.println("Java says: result is " + result); } }
Step 4: Generate JNI header & write a C bridge
JNI requires a C function with a specific signature to connect Java's native method to the Go function. First, compile your Java file and generate the header:
# Compile Java class javac GoJNI.java # Generate JNI header javah -jni GoJNI
This creates a GoJNI.h file with a function signature like Java_GoJNI_add. Now write a C bridge file (go_jni_bridge.c) to link this JNI function to our Go Add:
#include "GoJNI.h" #include "libadd.h" // Include the header generated by Go JNIEXPORT jint JNICALL Java_GoJNI_add(JNIEnv *env, jobject obj, jint x, jint y) { // Call the exported Go function, converting types as needed return (jint)Add((int)x, (int)y); }
Step 5: Compile the C bridge & run
Compile the C bridge into a shared library, linking it with the Go library. On Linux, that looks like:
gcc -shared -fpic -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux go_jni_bridge.c -L. -ladd -o libgojni.so
Finally, run your Java program, specifying the library path:
java -Djava.library.path=. GoJNI
You should see output from both Go and Java!
JNA (Java Native Access) skips the C bridge entirely—you just declare a Java interface that maps to the native library's functions. This is way simpler for most cases. Here's how to do it with Go:
Step 1: Reuse your Go code & compile to shared library
Use the same Go code from Question 1, and compile it to a shared library with the same command:
go build -buildmode=c-shared -o libadd.so add.go
Step 2: Set up JNA in your Java project
First, get the JNA libraries—you can add them via Maven:
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.13.0</version> </dependency>
Or download the JARs directly and add them to your classpath.
Step 3: Write the Java JNA code
Create an interface that extends Library and declares the Go function, then use it in your main class:
import com.sun.jna.Library; import com.sun.jna.Native; // Interface mapping to the Go shared library public interface GoAddLibrary extends Library { // Load the shared library (again, omit prefix/suffix) GoAddLibrary INSTANCE = (GoAddLibrary) Native.load("add", GoAddLibrary.class); // Declare the function—name and types must match the exported Go function int Add(int x, int y); } public class GoJNA { public static void main(String[] args) { int result = GoAddLibrary.INSTANCE.Add(3, 5); System.out.println("Java says: result is " + result); } }
Step 4: Run the Java program
Make sure the JNA JARs and your Go shared library are in the right places, then run:
java -cp .:jna.jar GoJNA
That's it—no C code needed!
Quick note on JNI vs JNA
- JNI: More work (requires a C bridge), but slightly better performance. Great for high-throughput scenarios.
- JNA: No C code, faster to implement. Performance is good enough for most applications.
内容的提问来源于stack exchange,提问作者dmotta

