Is it possible to use sun.misc.Unsafe to call C functions without JNI?(是否可以在没有 JNI 的情况下使用 sun.misc.Unsafe 调用 C 函数?)
问题描述
一段 C/C++ 代码可以提供一个带有函数指针数组的 JNI 方法.但是有没有办法直接从Java代码内部(不使用JNI或类似的)调用数组指针指向的函数堆栈?JNI 不知何故做了类似的事情,所以一定有办法.JNI 是如何做到的?是通过 sun.misc.Unsafe 吗?即使不是,我们是否可以使用一些不安全的解决方法来获取执行此操作的 JVM 代码?
我当然不打算将其用于商业用途.我什至不是专业人士,我只是真的很喜欢编码,而且我最近一直在研究 CUDA,所以我想也许我可以尝试将所有东西混合在一起,但是 JNI 调用的开销会破坏使用 GPU 加速代码的目的.
JNI有那么慢吗?
JNI 已经优化了很多,你应该先尝试一下.但它确实有一定的开销,
<小时>P.S. JDK 中正在进行的工作是实现 Native MethodHandles,它将作为 JNI 的更快替代方案.但是它不太可能出现在 JDK 10 之前.
- http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html
- http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/000225.html
A piece of C/C++ code could provide a JNI method with an array of function pointers. But is there a way to call to the stack the functions that array's pointers are pointing to, directly from inside Java code (without using JNI or similar)? JNI somehow does something like that, so there must be a way. How does JNI do it? Is it via sun.misc.Unsafe? Even if it is not, could we use some Unsafe workaround to get our hands on the JVM code that does that?
I don't plan to use that commercially of course. I'm not even a professional, I just really enjoy coding and I've been studying CUDA lately so I thought maybe I could experiment with mixing everything together, but the overhead of JNI calls would defeat the purpose of having GPU accelerated code.
Is JNI that slow?
JNI has already been optimized a lot, you should give it a try first. But it indeed has certain overhead, see details.
This overhead can be significant if a native function is simple and is called frequently. JDK has a private API called Critical Natives to reduce overhead of calling functions that do not require much of JNI functionality.
Critical Natives
A native method must satisfy the following conditions to become a critical native:
- must be static and not synchronized;
- argument types must be primitive or primitive arrays;
- implementation must not call JNI functions, i.e. it cannot allocate Java objects or throw exceptions;
- should not run for a long time, since it will block GC while running.
The declaration of a critical native looks like a regular JNI method, except that
- it starts with
JavaCritical_
instead ofJava_
; - it does not have extra
JNIEnv*
andjclass
arguments; - Java arrays are passed in two arguments: the first is an array length, and the second is a pointer to raw array data. That is, no need to call
GetArrayElements
and friends, you can instantly use a direct array pointer.
E.g. a JNI method
JNIEXPORT jint JNICALL
Java_com_package_MyClass_nativeMethod(JNIEnv* env, jclass klass, jbyteArray array) {
jboolean isCopy;
jint length = (*env)->GetArrayLength(env, array);
jbyte* buf = (*env)->GetByteArrayElements(env, array, &isCopy);
jint result = process(buf, length);
(*env)->ReleaseByteArrayElements(env, array, buf, JNI_ABORT);
return result;
}
will turn to
JNIEXPORT jint JNICALL
JavaCritical_com_package_MyClass_nativeMethod(jint length, jbyte* buf) {
return process(buf, length);
}
Critical natives are supported only in HotSpot JVM starting from JDK 7. Moreover, "critical" version is called only from compiled code. Therefore you need both critical and standard implementation to make this work correctly.
This feature was designed for internal use in JDK. There is no public specification or something. Probably the only documentation you may find is in the comments to JDK-7013347.
Benchmark
This benchmark shows critical natives can be several times faster than regular JNI methods when the native workload is very small. The longer is method, the smaller is relative overhead.
P.S. There is an ongoing work in JDK to implement Native MethodHandles that will serve as a faster alternative to JNI. However it is unlikely to appear prior to JDK 10.
- http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html
- http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/000225.html
这篇关于是否可以在没有 JNI 的情况下使用 sun.misc.Unsafe 调用 C 函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:是否可以在没有 JNI 的情况下使用 sun.misc.Unsafe 调用 C 函数?


- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01