当前位置:  开发笔记 > 编程语言 > 正文

什么是Java中的本机实现?

如何解决《什么是Java中的本机实现?》经验,为你挑选了4个好方法。

如果我们查看Java Object类,那么我们可以找到一些方法,如:

public native int hashCode()
protected native Object clone()

这些本地人是什么?这些方法如何运作?



1> Nick Fortesc..:

这些方法是Intrinsic或在Java之外的"本机"代码中编写,即特定于给定机器.

您提到的是Intrinsic和JDK的一部分,但您也可以使用Java Native Interface(JNI)自己编写本机方法.这通常会使用C来编写方法,但是许多其他语言(例如python)允许您以相当容易的方式编写方法.代码以这种方式编写,无论是为了提高性能,还是因为它需要访问平台特定的基础结构,而这些基础结构无法在普通java中完

在这种情况下hashcode(),这是由JVM实现的.这是因为哈希码通常只与JVM知道的东西有关.在早期的JVM上,这与对象在内存中的位置有关 - 在其他JVM上,Object可能在内存中移动,因此可以使用更复杂(但仍然非常快)的方案.


如果hashcode()由JVM实现,为什么它需要*native*?你的*内在*究竟是什么意思?

2> Tom Hawtin -..:

大多数本机方法是使用JNI实现的,如其他答案中所述.

但是,性能关键方法(如Object.hashCode通常作为内在函数实现).当字节代码被编译成机器代码时,Java编译器识别方法调用并直接内联适当的代码.这显然比通过JNI获得一个简单的方法要快得多.

许多人会声称Object.hashCode会在内存中返回对象表示的地址.在现代实现中,对象实际上在内存中移动 而是使用对象标题的区域来存储该值,该值可以在首次请求该值时从存储器地址延迟地导出.


有关详细信息,请访问(http://stackoverflow.com/a/13860488/390695)

3> starblue..:

本机方法主要在C中实现,并编译为直接在机器上运行的本机代码.这与普通方法形成对比,普通方法在Java中实现并编译为Java字节代码,由Java虚拟机(JVM)执行.

要从Java接口这些方法,您需要使用Java Native Interface(JNI).

访问低级别的东西通常需要本机代码.在hashCode的情况下,这是内存中对象的地址.我对克隆的猜测是它将原始内存从给定对象复制到克隆对象.本机代码的其他用途是用于访问OS功能或硬件.

使用本机代码的缺点是您失去了JVM的安全性,即您的程序可能会因本机代码中的错误而崩溃或出现安全漏洞.



4> Ciro Santill..:

这些本地人是什么?这些方法如何运作?

使事情更清晰的最小例子:

Main.java:

public class Main {
    public native int square(int i);
    public static void main(String[] args) {
        System.loadLibrary("Main");
        System.out.println(new Main().square(2));
    }
}

Main.c:

#include 
#include "Main.h"

JNIEXPORT jint JNICALL Java_Main_square(
    JNIEnv *env, jobject obj, jint i) {
  return i * i;
}

编译并运行:

sudo apt-get install build-essential openjdk-7-jdk
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64'
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

在Ubuntu 14.04上测试过.还使用了Oracle JDK 1.8.0_45.

GitHub上的示例供您玩.

解释:

它允许您:

使用Java中的任意汇编代码调用已编译的动态加载库(此处用C语言编写)

并将结果返回Java

这可以用于:

使用更好的CPU汇编指令(不是CPU便携式)在关键部分编写更快的代码

进行直接系统调用(不是OS便携式)

与低便携性的权衡.

您也可以从C调用Java,但必须首先在C中创建JVM:如何从C++调用Java函数?

OpenJDK 8中的示例

让我们找到Object#clonejdk8u60-b27中定义的位置.

首先我们发现:

find . -name Object.java

这导致我们jdk/src/share/classes/java/lang/Object.java#l212:

protected native Object clone() throws CloneNotSupportedException;

现在是困难的部分,找到克隆在所有间接中的位置.帮助我的查询是:

find . -iname object.c

可以找到可能实现Object的本机方法的C或C++文件.它将我们引向jdk/share/native/java/lang/Object.c#l47:

static JNINativeMethod methods[] = {
    ...
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

这导致我们的JVM_Clone符号:

grep -R JVM_Clone

这导致我们到hotspot/src/share/vm/prims/jvm.cpp#l580:

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
    JVMWrapper("JVM_Clone");

在扩展了一堆宏之后,我们得出结论,这是定义点.

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有