深入剖析 Java 新特性
范学雷
前 Oracle 首席软件工程师,Java SE 安全组成员,OpenJDK 评审成员
16539 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 23 讲
深入剖析 Java 新特性
15
15
1.0x
00:00/00:00
登录|注册

13 | 外部函数接口,能不能取代Java本地接口?

你好,我是范学雷。今天,我们一起来讨论 Java 的外部函数接口。
Java 的外部函数接口这个新特性,我写这篇文章的时候,还在孵化期,还没有发布预览版。由于孵化期的特性还不成熟,不同的版本之间的差异可能会很大。我建议你使用最新版本,现在来说就是 JDK 17 来体验孵化期的特性。
Java 的外部函数接口这个特性,有可能会是 Java 自诞生以来最重要的两个特性之一,它和外部内存接口一起,会极大地丰富 Java 语言的生态环境。提前了解一下这样的新特性,有助于我们思考现在的技术手段和未来的技术规划。
我们从阅读案例开始,来看一看 Java 的外部函数接口为什么可能会带来这么大的影响,以及它能够给我们的代码带来什么样的变化吧。

阅读案例

我们知道,像 Java 或者 Go 这样的通用编程语言,都需要和其他的编程语言或者环境打交道,比如操作系统或者 C 语言。Java 是通过 Java 本地接口(Java Native Interface, JNI)来支持这样的做法的。 本地接口,拓展了一门编程语言的生存空间和适用范围。有了本地接口,就不用所有的事情都在这门编程语言内部实现了。
比如下面的代码,就是一个使用 Java 本地接口实现的“Hello, world!"的小例子。其中的 sayHello 这个方法,使用了修饰符 native,这表明它是一个本地的方法。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java的外部函数接口是一项新的孵化阶段特性,旨在解决Java本地接口(JNI)存在的安全性和跨平台性等问题。通过对比使用JNI和外部函数接口的代码,文章阐述了外部函数接口的优势,包括无需编写C代码、编译、链接生成C的动态库,避免了平台相关问题,并在安全性方面有所提升。外部函数接口可能会导致JNI退出,因为安全问题具有一票否决权。总的来说,外部函数接口为Java语言的生态环境带来了新的协作方案,未来可能需要逐步退出传统的基于JNI的解决方案。文章建议读者对外部函数接口有一个基本的印象,以便在未来的技术规划中考虑切换到外部函数接口。文章还提供了使用JShell快速学习新技术的方法,并鼓励读者在留言区分享阅读体验和代码设计。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入剖析 Java 新特性》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(11)

  • 最新
  • 精选
  • JavaGuide
    另外,请问一下老师,这个提案https://openjdk.java.net/jeps/191中不是已经将Java 的外部函数接口这个特性的开发暂时停止了么?

    作者回复: JEP 191被更好的方案取代了:https://openjdk.java.net/jeps/412

    2021-12-22
    2
  • ABC
    在JDK18的JShell里面也试了一下,同样报错.

    作者回复: JDK 18已经修复了,可能要等到下一个build才能见效。

    2021-12-14
  • ABC
    在JShell里面运行,发现报错: java.lang.IllegalCallerException:Illegal native access from: unnamed module @f2a0b8e 在OpenJDK的描述里面提示了,需要设置: java --enable-native-access=M 才能正确运行,但是JShell里面无法设置.老师,请问要怎么才能正常运行?谢谢.

    作者回复: 使用“-R--enable-native-access=ALL-UNNAMED”的jshell命令行选项。

    2021-12-14
    2
  • Jxin
    我的想法是,外部函数接口应该是现有RPC交互的一种暴露接口的新模式。就像暴露http接口,不同语言都暴露相同模式的“外部函数”接口,有一套跨语言的统一规则/协议。调用方与服务方皆遵循统一规则/协议交互。像现在这样,必须调用特定语言的调用规则,在泛化上走不通(要感知异构系统的语言),适用范围就会很局限。

    作者回复: 还在孵化器,论证和构造原型为主。现在的设计,已经有点泛化的意思了。试图统一规则和协议的想法,最怕的就是一厢情愿,很难做成。

    2021-12-14
  • 小飞同学
    idea里面的–add-exports页面上一直没加上去,放弃了。jshell17.0.1执行结果,有遇到的小伙伴么?怎么解决的,java.lang.IllegalCallerException:Illegal native access from: unnamed module @6aa8ceb6 | at Reflection.ensureNativeAccess (Reflection.java:112) | at CLinker.getInstance (CLinker.java:131)

    作者回复: 估计Github上的代码没有处理好编译/运行选项,应该设置“--enable-native-access=ALL-UNNAMED”参数。 workspace.xml: <option name="VM_PARAMETERS" value="--enable-preview --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector,jdk.incubator.foreign" />

    2021-12-14
    3
  • 小飞同学
    helloworld.c文件中没有写形参,gcc编译会报错。

    作者回复: 谢谢,漏掉了。

    2021-12-13
  • kimoti
    外部函数借口是不是在内部编译,链接C语言程序,只不过这个过程对Java程序员透明而已?

    作者回复: 应该是链接到C的动态库就行。

    2021-12-13
  • 学习
    感知不强,可能还需要时间来沉淀吧
    2021-12-13
    2
  • JavaGuide
    JNA 这个库貌似是目前的备用选择,JDK 官方也提到过这个库。 地址:https://github.com/java-native-access/jna
    2021-12-22
    1
  • ABC
    JShell运行: jshell --add-modules jdk.incubator.foreign -R--enable-native-access=ALL-UNNAMED import java.lang.invoke.MethodType; import java.lang.invoke.MethodHandle; import jdk.incubator.foreign.*; try (ResourceScope scope = ResourceScope.newConfinedScope()) { CLinker cLinker = CLinker.getInstance(); MemorySegment helloWorld = CLinker.toCString("Hello, world!\n", scope); MethodHandle cPrintf = cLinker.downcallHandle( CLinker.systemLookup().lookup("printf").get(), MethodType.methodType(int.class, MemoryAddress.class), FunctionDescriptor.of(CLinker.C_INT, CLinker.C_POINTER)); cPrintf.invoke(helloWorld.address()); }
    2021-12-15
    1
    1
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部