我是靠谱客的博主 纯真荷花,这篇文章主要介绍java使用jna调用go代码调用流程示例代码测试结果,现在分享给大家,希望可以做个参考。

调用流程

在 Java 中使用jna调用 Go 的大致过程如下

复制代码
1
2
java -> jna -> c -> cgo -> go

整个过程要解决的问题主要两个

  • 数据类型在两种语言中如何转化
  • 内存的释放

示例代码

以下是简单的示例,并解决了内存泄露的问题

Go代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//export add func add(a, b C.int) C.int { aGo := int(a) bGo := int(b) res := aGo + bGo return C.int(res) } //export hello func hello(name *C.char) *C.char { data := C.GoString(name) cs := C.CString("Hello " + data + "!") return cs } //export freePoint func freePoint(cs *C.void) { C.free(unsafe.Pointer(cs)) } func main() {}

Go代码编译为共享库

windows环境编译

使用windows 10的操作系统,gcc使用TDM-GCC-64

windows 64bit 共享库

复制代码
1
2
go build -buildmode=c-shared -o ../resources/win32-x86-64/awesome.dll awesome.go

windows 32bit 共享库

复制代码
1
2
3
4
set CGO_ENABLED=1 set GOARCH=386 go build -buildmode=c-shared -o ../resources/win32-i686/awesome.dll awesome.go

linux x86 环境编译

使用ubuntu操作系统

linux 64bit 共享库

复制代码
1
2
GOARCH=amd64 GOOS=linux CGO_ENABLED=1 go build -buildmode=c-shared -o ../resources/linux-x86-64/libawesome.so awesome.go

linux arm64 环境编译

使用ubuntu操作系统
交叉编译器:gcc-8-aarch64-linux-gnu

linux 64bit 共享库

复制代码
1
2
CC=aarch64-linux-gnu-gcc-8 GOARCH=arm64 GOOS=linux CGO_ENABLED=1 go build -buildmode=c-shared -o ../resources/linux-aarch64/libawesome.so awesome.go

JNA的动态库加载方式

将go打包生成的dll、so或dylib放在java的resources 下的{OS}-{ARCH}/{LIBRARY} 目录内

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
resources/ |── linux-aarch64 | └── libawesome.dylib ├── linux-x86-64 │ └── libawesome.so ├── win32-x86-64 │ └── awesome.dll ├── win32-i686 │ └── awesome.dll ├── darwin │ └── libawesome.dylib

JAVA代码

在pom.xml中引入jna

复制代码
1
2
3
4
5
6
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.6.0</version> </dependency>

共享库接口定义

复制代码
1
2
3
4
5
6
7
8
9
10
11
public interface AuthLibrary extends Library { AuthLibrary INSTANCE = Native.load("awesome", AuthLibrary.class); int add(int a, int b); Pointer hello(Pointer name); void freePoint(Pointer pointer); }

接口封装

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class AuthServer { public static String hello(String name) { // 申请jna的内存空间 Pointer p = new Memory(name.getBytes(StandardCharsets.UTF_8).length + 1); // 设置传入参数值 p.setString(0, name); Pointer ptr = null; try { ptr = AuthLibrary.INSTANCE.hello(p); return ptr.getString(0, "utf8"); } finally { // 释放传入jna的指针对应的内存空间 Native.free(Pointer.nativeValue(p)); // 解决多次调用崩溃的问题 Pointer.nativeValue(p, 0); if (ptr != null) { // 释放go中申请的C的内存 AuthLibrary.INSTANCE.freePoint(ptr); } } } private static void freeJna(Pointer pointer) { // 释放传入jna的指针对应的内存空间 Native.free(Pointer.nativeValue(pointer)); // 解决多次调用崩溃的问题 Pointer.nativeValue(pointer, 0); } }

测试代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public class JNATest { public static void main(String[] args) { System.out.println(AuthLibrary.INSTANCE.add(1, 2)); int count = 1; for (int i = 0; i < count; i++) { String msg = "测试 java -> go,java -> go,java -> go,java -> go,java -> go,java -> go,java -> go,java -> go"; System.out.println(AuthServer.hello(msg)); } count = 999999999; }

测试结果

  • 在x86的windows、linux及arm架构的linux均可正常使用
  • 在测试代码中将count数量设得很大时,观察到内存使用在200M左右,很稳定,无明显的内存泄露

参考链接

  • https://liujiacai.net/blog/2020/08/08/go-meet-java/

最后

以上就是纯真荷花最近收集整理的关于java使用jna调用go代码调用流程示例代码测试结果的全部内容,更多相关java使用jna调用go代码调用流程示例代码测试结果内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(92)

评论列表共有 0 条评论

立即
投稿
返回
顶部