密集计算场景下的 JNI 实战

在 Java 发展历程中,JNI 一直都是一个不可或缺的角色,但是在实际的项目开发中,JNI 这项技术应用的很少。在笔者经过艰难的踩坑之后,终于将 JNI 运用到了项目实战,本文笔者将简单介绍 JNI 技术,并介绍简单的原理和性能分析。通过分享我们的实践过程,带各位读者体验 JNI 技术的应用。

一、 背景

计算密集型场景中,Java 语言需要花费较多时间优化 GC 带来的额外开销。并且在一些底层指令优化方面,C++ 这种“亲核性”的语言有着较好的优势和大量的业界实践经验。那么作为一个多年的 Java 程序员,能否在 Java 服务上面运行 C++ 代码呢?答案是肯定的。

JNI (Java Native Interface) 技术正是应对该场景而提出的解决方案。虽然 JNI 技术让我们能够进行深度的性能优化,其较为繁琐的开发方式也不免让新人感到头疼。本文通过 step by step 的方式介绍如何完成 JNI 的开发,以及我们优化的效果和思考。

开始正文前我们可以思考三个问题:

  1. 为什么选择使用 JNI 技术?

  2. 如何在 Maven 项目中应用 JNI 技术?

  3. JNI 真的好用吗?

二、关于 JNI:为什么会选择它?

2.1 JNI 基本概念

JNI 的全称叫做 Java Native Interface ,翻译过来就是 Java 本地接口。爱看 JDK 源码的小伙伴会发现,JDK 中有些方法声明是带有 native 修饰符的,并且找不到具体实现,其实是在非 Java 语言上,这就是 JNI 技术的体现。

早在 JDK1.0 版本就已经有了 JNI,官方给 JNI 的定义是:

Java Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform.

JNI 是一种标准的程序接口,用于编写 Java 本地方法,并且将 JVM 嵌入 Native 应用程序中。是为了给跨平台上的 JVM 实现本地方法库进行二进制兼容。

JNI 最初是为了保证跨平台的兼容性,而设计出来的一套接口协议。并且由于 Java 诞生很早,所以 JNI 技术绝大部分情况下调用的是 C/C++ 和系统的 lib 库,对其他语言的支持比较局限。随着时间的发展,JNI 也逐渐被开发者所关注,比如 Android 的 NDK,Google 的 JNA,都是对 JNI 的扩展,让这项技术能够更加轻松的被开发者所使用。

我们可以看一下在 JVM 中 JNI 相关的模块,如图 1:

图1 - JVM 内存和引擎执行关系

在 JVM 的内存区域,Native Interface 是一个重要的环节,连接着执行引擎和运行时数据区。本地接口 (JNI) 的方法在本地方法栈中管理 native 方法,在 Execution Engine 执行时加载本地方法库。

JNI 就像是打破了 JVM 的束缚,拥有着和 JVM 同样的能力,可以直接使用处理器中的寄存器,不仅可以直接使用处理器中的寄存器,还可以直接找操作系统申请任意大小的内存,甚至能够访问到 JVM 虚拟机运行时的数据,比如搞点堆内存溢出什么的:)

2.2 JNI 的功能

JNI 拥有着强大的功能,那它能做哪些事呢?官方文档给出了参考答案。

  1. 标准 Java 类库不支持应用程序所需的平台相关特性。
  1. 您已经有一个用另一种语言编写的库,并希望通过 JNI 使其可供 Java 代码访问。
  1. 您想用较低级别的语言(例如汇编)实现一小部分耗时短的代码。

当然还有一些扩充,比如:

  1. 不希望所写的 Java 代码被反编译;
  1. 需要使用系统或已有的 lib 库;
  1. 期望使用更快速的语言去处理大量的计算;
  1. 对图像或本地文件操作频繁;
  1. 调用系统驱动的接口。

或许还有别的场景,可以使用到 JNI,可以看到 JNI 技术有着非常好的应用潜力。

三、JNI 实战:探究踩坑的全过程

我们的业务中存在一个计算密集型场景,需要从本地加载数据文件进行模型推理。项目组在 Java 版本进行了几轮优化后发现没有什么大的进展,主要表现为推理耗时较长,并且加载模型时存在性能抖动。经过调研,如果想进一步提高计算和加载文件的速度,可以使用 JNI 技术去编写一个 C++ 的 lib 库,由 Java native 方法进行调用,预计会有一定的提升。

然而项目组目前也没有 JNI 的实践经验,最终性能是否能有提升,还是要打个问号。本着初生牛犊不怕虎的精神,我鼓起勇气主动认领了这个优化任务。下面就分享一下我实践 JNI 的过程和遇到的问题,给大家抛砖引玉。

3.1 场景准备

实战就不从 Hello world 开始了,我们直接敲定场景,思考该让 C++ 实现哪部分逻辑。

场景如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值