如果我们查看Java Object类,那么我们可以找到一些方法,如:
public native int hashCode()
protected native Object clone()
这些本地人是什么以及这些方法如何运作?
答案 0 :(得分:36)
这些方法是 Intrinsic 或在“本机”代码中用Java编写,即特定于给定机器。
您提到的是 Intrinsic 和JDK的一部分,但您也可以使用Java Native Interface(JNI)自己编写本机方法。这通常会使用C来编写方法,但是许多其他语言(例如python)允许您以相当容易的方式编写方法。代码以这种方式编写,无论是为了提高性能,还是因为它需要访问平台特定的基础结构,而这些基础结构无法在普通的java中完成。
在hashcode()
的情况下,这是由JVM实现的。这是因为哈希码通常只与JVM知道的东西有关。在早期的JVM中,这与对象在内存中的位置有关 - 在其他JVM上,Object可能在内存中移动,因此可能会使用更复杂(但仍然非常快)的方案。
答案 1 :(得分:19)
大多数原生方法都是使用其他答案中提到的JNI实现的。
但是,Object.hashCode
等性能关键方法通常作为内在函数实现。当字节代码被编译成机器代码时,Java编译器识别方法调用并直接内联适当的代码。这显然要比通过JNI获得一个简单的方法快得多。
许多人会声称Object.hashCode
会在内存中返回对象表示的地址。在现代实现中,对象实际上在内存中移动而是使用对象标题的一个区域来存储该值,该值可能是在首次请求该值时从内存地址延迟导出的。
答案 2 :(得分:11)
本机方法主要在C中实现,并编译为直接在计算机上运行的本机代码。 这与普通方法形成对比,普通方法在Java中实现并编译为Java字节代码,由Java虚拟机(JVM)执行。
要从Java接口这些方法,您需要使用Java Native Interface (JNI)。
本机代码主要用于访问低级别的东西。在 hashCode 的情况下,这是内存中对象的地址。我对 clone 的猜测是它将原始内存从give对象复制到克隆对象。本机代码的其他用途是用于访问OS功能或硬件。
使用本机代码的缺点是您失去了JVM的安全性,即您的程序可能会因本机代码中的错误而崩溃或出现安全漏洞。
答案 3 :(得分:10)
这些本地人是什么以及这些方法如何运作?
最小的例子让事情变得更加清晰:
<强> 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 <jni.h>
#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。
<强>解释强>:
它允许您:
这可以用于:
与较低的便携性进行权衡。
您也可以从C调用Java,但必须先在C中创建JVM:How to call Java functions from C++?
OpenJDK 8中的示例
让我们找到jdk8u60-b27中定义Object#clone
的位置。
首先我们找到:
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");
在扩展了一堆宏之后,我们得出结论,这是定义点。
答案 4 :(得分:0)
Java中的本机方法是使用“Java Native Interface”实现的,称为JNI。