Golang程序通过Java运行时出现IllegalArgumentException错误
Golang程序通过Java运行时出现IllegalArgumentException错误 我的Go代码如下:
package main
import "C"
//export MyFunc
func MyFunc(records []string) [][]string {
records := make([][]string, 0)
.
.
.
return records
}
我需要通过Java Native Access运行这个Go文件。 对应的Java代码如下:
public Class MyClass {
public interface MyInterface extends Library {
String[][] MyFunc(String[] records);
}
static{
MyObj = (MyClass) Native.loadLibrary("/path/to/so_file", MyClass.class);
}
public static void main(String[] args) {
String[] strArray = {"abc1|HLJHSA|hgah","abc2|ksahd|","abc3|876987","abc4"};
String[][] records1 = MyObj.MyFunc(strArray );
}
}
我正确执行了所有步骤,但遇到了以下错误:
Exception in thread "main" java.lang.IllegalArgumentException: Unsupported return type class [[Ljava.lang.String; in function MyFunc
at com.sun.jna.Function.invoke(Function.java:373)
at com.sun.jna.Function.invoke(Function.java:223)
at com.sun.jna.Library$Handler.invoke(Library.java:204)
我还尝试了: ArrayList<ArrayList> MyFunc(String[] records); 和 List<List> MyFunc(String[] records);
请帮我找到Java中 make([][]string, 0) 的正确等价形式。
更多关于Golang程序通过Java运行时出现IllegalArgumentException错误的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我相当确定你无法做到这一点。你可以将一个指向Go结构的指针传递给cgo/JNI,但你不能传递一个本身包含指针的结构的指针。切片的切片包含指向指针的指针。我建议以某种格式(例如,JSON对你来说可行吗?)序列化数据,将其传递给Java,执行一些工作,序列化响应,然后将其返回给Go。
更多关于Golang程序通过Java运行时出现IllegalArgumentException错误的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
问题在于JNA不支持直接映射Go的二维字符串切片([][]string)到Java的二维字符串数组(String[][])。JNA对复杂类型的支持有限,需要手动处理内存布局。
以下是解决方案:
1. 修改Go代码,使用C兼容的类型:
package main
import "C"
import "unsafe"
//export MyFunc
func MyFunc(cRecords **C.char, length C.int) (unsafe.Pointer, C.int) {
// 将C字符串数组转换为Go的[]string
goRecords := make([]string, length)
slice := (*[1 << 30]*C.char)(unsafe.Pointer(cRecords))[:length:length]
for i := 0; i < int(length); i++ {
goRecords[i] = C.GoString(slice[i])
}
// 你的业务逻辑
result := make([][]string, 0)
// ... 填充result ...
// 转换为C兼容的格式
// 首先分配一个指针数组
cResult := C.malloc(C.size_t(len(result)) * C.size_t(unsafe.Sizeof(uintptr(0))))
defer C.free(cResult)
ptrs := (*[1 << 30]unsafe.Pointer)(cResult)[:len(result):len(result)]
for i, row := range result {
// 为每行分配字符串数组
rowPtr := C.malloc(C.size_t(len(row)) * C.size_t(unsafe.Sizeof(uintptr(0))))
strPtrs := (*[1 << 30]*C.char)(rowPtr)[:len(row):len(row)]
for j, str := range row {
strPtrs[j] = C.CString(str)
}
ptrs[i] = rowPtr
}
return cResult, C.int(len(result))
}
//export FreeResult
func FreeResult(ptr unsafe.Pointer, rows C.int) {
ptrs := (*[1 << 30]unsafe.Pointer)(ptr)[:rows:rows]
for i := 0; i < int(rows); i++ {
C.free(ptrs[i])
}
C.free(ptr)
}
2. 修改Java代码:
import com.sun.jna.*;
import com.sun.jna.ptr.PointerByReference;
public class MyClass {
public interface MyInterface extends Library {
// 返回指针和行数
PointerByReference MyFunc(String[] records, int length);
int GetResultRows(PointerByReference result);
String[] GetResultRow(PointerByReference result, int rowIndex);
void FreeResult(PointerByReference result);
}
private static MyInterface MyObj;
static {
MyObj = (MyInterface) Native.loadLibrary("/path/to/so_file", MyInterface.class);
}
public static void main(String[] args) {
String[] strArray = {"abc1|HLJHSA|hgah","abc2|ksahd|","abc3|876987","abc4"};
// 调用Go函数
PointerByReference result = MyObj.MyFunc(strArray, strArray.length);
try {
// 获取行数
int rows = MyObj.GetResultRows(result);
// 读取结果
String[][] records1 = new String[rows][];
for (int i = 0; i < rows; i++) {
String[] row = MyObj.GetResultRow(result, i);
records1[i] = row;
}
// 使用records1...
} finally {
// 释放内存
MyObj.FreeResult(result);
}
}
}
3. 或者使用更简单的序列化方式(推荐):
// Go代码 - 使用JSON序列化
package main
import "C"
import "encoding/json"
import "unsafe"
//export MyFunc
func MyFunc(input *C.char) *C.char {
// 解析输入
goInput := C.GoString(input)
var records []string
json.Unmarshal([]byte(goInput), &records)
// 业务逻辑
result := make([][]string, 0)
// ... 填充result ...
// 序列化结果
jsonResult, _ := json.Marshal(result)
return C.CString(string(jsonResult))
}
//export FreeString
func FreeString(str *C.char) {
C.free(unsafe.Pointer(str))
}
// Java代码 - 使用JSON
import com.sun.jna.*;
import com.google.gson.Gson;
public class MyClass {
public interface MyInterface extends Library {
Pointer MyFunc(String input);
void FreeString(Pointer str);
}
private static MyInterface MyObj;
private static final Gson gson = new Gson();
static {
MyObj = (MyInterface) Native.loadLibrary("/path/to/so_file", MyInterface.class);
}
public static void main(String[] args) {
String[] strArray = {"abc1|HLJHSA|hgah","abc2|ksahd|","abc3|876987","abc4"};
// 序列化输入
String inputJson = gson.toJson(strArray);
// 调用Go函数
Pointer resultPtr = MyObj.MyFunc(inputJson);
try {
// 获取结果字符串
String resultJson = resultPtr.getString(0);
// 反序列化结果
String[][] records1 = gson.fromJson(resultJson, String[][].class);
// 使用records1...
} finally {
MyObj.FreeString(resultPtr);
}
}
}
JSON序列化方案更简单,避免了复杂的内存管理问题。

