在Java中使用本机
有人能解释一下在Java中使用本机关键字的原因吗在Java中使用本机,java,native,Java,Native,有人能解释一下在Java中使用本机关键字的原因吗 您可能有一个非Java库,无论出于何种原因,您必须在Java项目中使用它 您可能需要集成一些旧的或很少使用的硬件,并且需要实现在C/C中更容易实现的接口++ 如果您想用本机代码解决性能问题,则有99.5%的可能性认为这是错误的方法;-) Java是独立于平台的,这意味着用Java编写的程序可以在任何操作系统上运行—您甚至不需要重新编译,编译的类文件应该在任何操作系统上运行 然而,有时,您需要在程序中执行某些特定于某个操作系统的操作,并且可能没有一
如果您想用本机代码解决性能问题,则有99.5%的可能性认为这是错误的方法;-) Java是独立于平台的,这意味着用Java编写的程序可以在任何操作系统上运行—您甚至不需要重新编译,编译的类文件应该在任何操作系统上运行 然而,有时,您需要在程序中执行某些特定于某个操作系统的操作,并且可能没有一种纯Java的方式来执行您需要执行的操作;或者您可能需要调用现有的非Java库。Java平台提供(Java本机接口)作为调用操作系统特定代码的方式 但是,您应该谨慎使用本机代码,因为它将您的程序与特定的操作系统联系在一起。这里引用了《有效Java第二版》第54项:明智地使用本机方法: 历史上,本地方法有三个主要用途。它们提供对特定于平台的设施(如注册表和文件锁)的访问。它们提供了对遗留代码库的访问,而这些库又可以提供对遗留数据的访问。最后,使用本机方法以本机语言编写应用程序的性能关键部分,以提高性能 使用本机方法访问特定于平台的设施是合法的,但随着Java平台的成熟,它提供了mroe和以前仅在主机平台中发现的更多功能。[…]很少建议使用本机方法来提高性能[…] 使用本地方法有严重的缺点。因为本机语言不安全,所以使用本机方法的应用程序不再能够避免内存损坏错误。因为本机语言依赖于平台,所以使用本机方法的应用程序的可移植性要差得多。使用本机代码的应用程序很难进行调试。进入和退出本机代码有一个固定的成本,因此本机方法如果只做少量工作,就会降低性能。最后,本机方法需要“粘合代码”,这很难阅读,也很乏味 整个项目对这些问题有更详细的解释。连同整本书,这是强烈推荐 另见
本机
。使用该框架,您可以编写Java代码,然后将其编译为可以在浏览器中运行的Javascript。在GWT中,native
关键字用于调用“native”Javascript代码
要寻找的术语是- 演出
- 与本机环境的更紧密集成
- 需要使用具有独特功能的本机库
示例:JAI(图像处理)、java3d(OpenGL)、JDIC(桌面集成)根据我的经验,使用本机代码库的缺点非常明显:
- JNI/JNA倾向于破坏JVM的稳定性,特别是当您试图做一些复杂的事情时。如果本机代码的本机代码内存管理错误,则有可能导致JVM崩溃。如果您的本机代码是不可重入的,并且被多个Java线程调用,那么糟糕的事情就会发生。。。零星等等
- 带有本机代码的Java比纯Java或纯C/C++更难调试
- 本机代码可能会为其他与平台无关的Java应用程序带来重大的平台依赖性/问题
- 本机代码需要一个单独的构建框架,并且可能存在平台/可移植性问题
通常,您应该将JNI/JNA视为“最后的选择”。如果有任何其他方法可以解决这个问题,那么这种方法可能更好。GWT的HTML小部件类有一个非常适合打印的宝石。如果要检查漂亮的打印机代码,则没有太大帮助:( 有人能解释一下在Java中使用本机关键字的原因吗 一旦你看到一个小例子,你就会明白: Main.java:
public class Main {
public native int intMethod(int i);
public static void main(String[] args) {
System.loadLibrary("Main");
System.out.println(new Main().intMethod(2));
}
}
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_intMethod(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
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
4
Main.c:
public class Main {
public native int intMethod(int i);
public static void main(String[] args) {
System.loadLibrary("Main");
System.out.println(new Main().intMethod(2));
}
}
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_intMethod(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
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
4
输出:
public class Main {
public native int intMethod(int i);
public static void main(String[] args) {
System.loadLibrary("Main");
System.out.println(new Main().intMethod(2));
}
}
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_intMethod(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
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
4
在带有Oracle JDK 1.8.0_45的Ubuntu 14.04上测试
因此,很明显,它允许您:
- 使用Java中的任意汇编代码调用编译的动态加载库(此处用C编写)
- 并将结果返回到Java中
- 使用更好的CPU汇编指令在关键部分编写更快的代码(不是CPU可移植的)
- 直接进行系统调用(非操作系统便携式)
免责声明:这个答案的一部分来自。我相信我已经直接回答了OP的问题。这真的有助于提高性能吗?人们对此有不同的想法!Java在访问底层硬件或操作系统提供的功能时总是需要一些本机代码。这取决于您是否需要了解about它(例如,因为如此