在Java中使用native

时间:2010-05-25 06:59:23

标签: java native

有人可以解释在Java中使用native关键字的原因和原因吗?

8 个答案:

答案 0 :(得分:6)

  1. 您可能有一个非Java库,无论出于何种原因,您必须在Java项目中使用
  2. 您可能需要集成一些旧的或很少使用的硬件,并且需要实现可能在C / C ++中更容易的界面
  3. 如果您想解决本机代码的性能问题,那么99.5%的可能性是错误的方法; - )

答案 1 :(得分:6)

  

有人可以解释在Java中使用native关键字的原因和原因吗?

一旦你看到一个小例子,它就变得清晰了:

<强> 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));
    }
}

<强> MAIN.C

#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便携式)在关键部分写入更快的代码
  • 进行直接系统调用(不是OS便携式)

与较低的便携性进行权衡。

您也可以从C调用Java,但必须先在C中创建JVM:How to call Java functions from C++?

Example on GitHub让你玩。

免责声明:此答案的一部分来自my earlier answer。我相信我已经在每个问题上直接回答了OP的问题。

答案 2 :(得分:2)

根据我的经验,使用本机代码库的缺点很重要:

  • JNI / JNA倾向于破坏JVM的稳定性,特别是如果你试图做一些复杂的事情。如果您的本机代码错误地导致本机代码内存管理,则可能会导致JVM崩溃。如果您的本机代码是不可重入的并且从多个Java线程调用,则会发生不好的事情......偶尔会发生。等等。

  • 使用本机代码的Java比纯Java或纯C / C ++更难调试。

  • 本机代码可能会为平台无关的Java应用程序引入重要的平台依赖性/问题。

  • 本机代码需要单独的构建框架,并且可能还存在平台/可移植性问题。

一般来说,使用本机代码不会获得太多(如果有的话)额外性能。虽然您可能认为您的C / C ++比Java更具性能,但JIT编译器在优化这些天方面做得非常好,您必须考虑在JNI边界上进行JNI调用和其他交互的性能成本。

一般来说,你应该将JNI / JNA视为“最后的手段”选项。如果有任何其他方法可以解决问题,那么这种方式可能更好。

答案 3 :(得分:1)

作为网络开发者,如果您使用Google Web Toolkit,则更有可能遇到native。使用该框架,您基本上可以编写Java代码,然后将其编译为可以在浏览器中运行的Javascript。在GWT中,native关键字用于调用“本机”Javascript代码。

要查找的字词是JSNI.

答案 4 :(得分:1)

  • 性能
  • 与原生环境更紧密的整合
  • 需要使用具有独特功能的本机库

示例: JAI (图像处理), Java 3D (OpenGL), JDIC (桌面集成)

答案 5 :(得分:0)

Java与平台无关,这意味着您用Java编写的程序可以在任何操作系统上运行 - 您甚至不需要重新编译,编译的类文件应该在任何操作系统上运行。

但是,有时候,您需要在程序中执行某些特定于某个操作系统的操作,并且可能没有纯Java方法来执行您需要执行的操作;或者您可能需要调用现有的非Java库。 Java平台提供JNI(Java Native Interface)作为调用特定于操作系统的代码的方法。

但是,您应该谨慎使用本机代码,因为它将您的程序绑定到特定的操作系统。

答案 6 :(得分:0)

以下是 Effective Java 2nd Edition的一些引用,第54项:明智地使用本机方法

  

历史上,本机方法有三个主要用途。它们提供对特定于平台的工具的访问,例如注册表和文件锁。他们提供了对遗留代码库的访问,这些代码可以反过来提供对遗留数据的访问。最后,使用本机方法以本机语言编写性能关键的应用程序部分,以提高性能。

     

使用本机方法访问特定于平台的工具是合法的,但随着Java平台的成熟,它提供了以前只在主机平台中才能找到的mroe和更多功能。 [...] 很少使用原生方法来提高性能 [...]

     

使用原生方法有严重的缺点。由于本机语言不是安全,因此使用本机方法的应用程序不再能够免受内存损坏错误的影响。由于本机语言与平台相关,因此使用本机方法的应用程序的可移植性要低使用本机代码的应用程序很难进行调试。进出本机代码有固定的成本,因此如果只做少量工作,原生方法可以降低性能。最后,本机方法需要“粘合代码”,这些代码难以阅读且编写起来很乏味。

整个项目对问题有更详细的解释。与整本书一起,强烈推荐。

另见

答案 7 :(得分:0)

GWT的HTML小部件类具有漂亮打印的宝石。当您想要检查漂亮的打印机代码时,没有太多帮助:(

    /**
    * All of the markup and content within a given element.
    */
        public final native void setInnerHTML(String html) /*-{
        this.innerHTML = html || '';
    }-*/;