Seamlessly Call Go Functions from Java Using JNI: A Step‑by‑Step Guide
Learn how to integrate Go and Java by compiling Go code into a shared library, exposing functions via cgo and JNI, and invoking them from Java with detailed setup, code examples, handling of primitive and complex data types, and full build‑and‑run instructions.
Introduction
This guide explains how to combine Go's high‑performance capabilities with Java's extensive ecosystem by calling Go functions from Java through the Java Native Interface (JNI). It covers everything from environment preparation to handling complex data structures via JSON.
Prerequisites
JDK : Version 11 or higher.
Go compiler : Ensure go is installed and in the PATH.
JNI : Java Native Interface for linking native code.
cgo : Go tool that enables interoperability with C, required for building a JNI‑compatible shared library.
javac & java : Java compiler and runtime.
Writing a Simple Go Function
Create a Go source file that exports a C‑compatible function using the //export directive. The example adds two integers:
package main
import "C"
//export AddNumbers
func AddNumbers(a, b int) int {
return a + b
}
func main() {}Explanation: package main declares the entry point required for building a shared library. import "C" enables cgo to generate C‑compatible binaries. AddNumbers receives two integers and returns their sum. func main() {} is mandatory even though it does nothing.
Compiling Go to a Shared Library
Build the Go file as a C‑shared object:
go build -o libadd.so -buildmode=c-shared main.goThe command produces libadd.so (the shared library) and libadd.h (the C header). Java will load libadd.so via JNI.
Writing the Java Wrapper
Implement a Java class that loads the shared library and declares a native method matching the Go function:
public class GoInvoker {
static {
System.loadLibrary("add"); // loads libadd.so
}
public native int AddNumbers(int a, int b);
public static void main(String[] args) {
GoInvoker invoker = new GoInvoker();
int result = invoker.AddNumbers(10, 20);
System.out.println("Result from Go Function: " + result);
}
}Key points:
The static block loads the shared library at class initialization.
The native keyword declares that the method implementation resides in native code.
The method signature must exactly match the exported Go function.
Compiling and Running the Java Code
Compile the Java source: javac GoInvoker.java Run the program, ensuring the library is discoverable (e.g., set LD_LIBRARY_PATH on Linux or add the directory to PATH on Windows): java GoInvoker When correctly configured, the output is:
Result from Go Function: 30Handling Complex Data Types with JSON
For structures, serialize the Go value to JSON and deserialize it in Java.
Go: Exporting a Struct as JSON
package main
import (
"C"
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
//export GetPersonJSON
func GetPersonJSON() *C.char {
person := Person{Name: "John Doe", Age: 30}
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println("Error marshaling data:", err)
return nil
}
return C.CString(string(jsonData))
}
func main() {}The function creates a Person instance, marshals it to JSON, and returns a C‑compatible string.
Java: Loading JSON from Go
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
public class GoInvoker {
static { System.loadLibrary("add"); }
public native String GetPersonJSON();
public static void main(String[] args) {
GoInvoker invoker = new GoInvoker();
String jsonResult = invoker.GetPersonJSON();
try {
JSONObject personObject = JSON.parseObject(jsonResult);
String name = personObject.getString("name");
int age = personObject.getIntValue("age");
System.out.println("Name: " + name);
System.out.println("Age: " + age);
} catch (Exception e) {
e.printStackTrace();
}
}
}The Java code loads the shared library, calls GetPersonJSON, parses the JSON, and prints the fields.
Full Build & Run Workflow
Compile Go to shared library:
go build -o libadd.so -buildmode=c-shared main.goCompile Java code (include JSON library on classpath): javac -cp .:fastjson2.jar GoInvoker.java Run the Java program, ensuring libadd.so is reachable: java -cp .:fastjson2.jar GoInvoker Expected output:
Name: John Doe
Age: 30Conclusion
The article provides a complete, practical solution for Java‑Go interoperation using JNI and cgo, covering both primitive and complex data exchanges. By compiling Go code into a C‑shared library and invoking it from Java, developers can leverage Go's performance while retaining Java's ecosystem, a valuable pattern for backend services, cloud‑native applications, and multi‑language micro‑service architectures.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
