Usage of native in Java
有人可以解释在Java中使用native关键字的原因和原因吗?
Can someone explain the whys and the wherefores for using native keyword in Java?
一旦你看到一个小例子,它变得清晰:
Main.java:
1 2 3 4 5 6 7 |
MAIN.C:
1 2 3 4 5 6 7 | #include <jni.h> #include"Main.h" JNIEXPORT jint JNICALL Java_Main_intMethod( JNIEnv *env, jobject obj, jint i) { return i * i; } |
编译并运行:
1 2 3 4 5 | javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ -I${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main |
输出:
1 | 4 |
使用Oracle JDK 1.8.0_45在Ubuntu 14.04上进行了测试。
所以很明显它允许你:
- 使用Java中的任意汇编代码调用已编译的动态加载库(此处用C语言编写)
- 并将结果返回Java
这可以用于:
- 使用更好的CPU汇编指令(不是CPU便携式)在关键部分编写更快的代码
- 进行直接系统调用(不是OS便携式)
与低便携性的权衡。
您也可以从C调用Java,但必须首先在C中创建JVM:如何从C ++调用Java函数?
GitHub上的示例供您玩。
免责声明:这个答案的一部分来自我之前的回答。我相信我已经在每个问题上直接回答了OP的问题。
如果你想解决本机代码的性能问题,那么99.5%的可能性是错误的方法;-)
根据我的经验,使用本机代码库的缺点很重要:
-
JNI / JNA倾向于破坏JVM的稳定性,特别是如果你试图做一些复杂的事情。如果您的本机代码错误地导致本机代码内存管理,则可能会导致JVM崩溃。如果您的本机代码是不可重入的并且从多个Java线程调用,则会发生不好的事情......偶尔会发生。等等。
-
使用本机代码的Java比纯Java或纯C / C ++更难调试。
-
本机代码可能会为平台独立的Java应用程序引入重要的平台依赖性/问题。
-
本机代码需要单独的构建框架,并且可能还存在平台/可移植性问题。
一般来说,使用本机代码不会获得太多(如果有的话)额外性能。虽然您可能认为您的C / C ++将比??Java更具性能,但JIT编译器在优化这些天方面做得非常好,您必须考虑在JNI边界上进行JNI调用和其他交互的性能成本。
一般来说,你应该将JNI / JNA视为"最后的选择"选项。如果有任何其他方法可以解决问题,那么这种方式可能会更好。
- 性能
- 与原生环境更紧密地整合
- 需要使用具有独特功能的本机库
示例:JAI(图像处理),Java 3D(OpenGL),JDIC(桌面集成)
作为Web开发人员,如果您使用Google Web Toolkit,则更有可能遇到
要寻找的术语是JSNI。
GWT的HTML小部件类具有漂亮打印的宝石。当你想检查漂亮的打印机代码时不太有用:(
1 2 3 4 5 6 | /** * All of the markup and content within a given element. */ public final native void setInnerHTML(String html) /*-{ this.innerHTML = html || ''; }-*/; |
以下是Effective Java 2nd Edition的一些引用,第54项:明智地使用本机方法:
Historically, native methods have had three main uses. They provide access to platform-specific facilities such as registries and file locks. They provided access to libraries of legacy code, which could in turn provide access to legacy data. Finally, native methods were used to write performance-critical parts of applciations in native languages for improved performance.
It is legitimate to use native methods to access platform-specific facilities, but as the Java platform matures, it provides mroe and more features previously found only in host platforms. [...] It is rarely advisable to use native methods for improved performance [...]
The use of native methods has serious disadvantages. Because native languages are not safe, applications using native methods are no longer immune to memory corruption errors. Because native languages are platform dependent, applications using native methods are far less portable. Applications using native code are difficult do debug. There is a fixed cost associated with going into and out of native code, so native methods can decrease performance if they do only a small amount of work. Finally, native methods require"glue code" that is difficult to read and tedious to write.
整个项目对问题有更详细的解释。与整本书一起,强烈推荐。
也可以看看
- 维基百科/ Java原生界面
Java与平台无关,这意味着您用Java编写的程序可以在任何操作系统上运行 - 您甚至不需要重新编译,编译的类文件应该在任何操作系统上运行。
但是,有时您需要在程序中执行某些特定于某个操作系统的操作,并且可能没有纯Java方法来执行您需要执行的操作;或者您可能需要调用现有的非Java库。 Java平台提供JNI(Java Native Interface)作为调用操作系统特定代码的方法。
但是,您应该谨慎使用本机代码,因为它将您的程序绑定到特定的操作系统。