Những người bản xứ này là gì và các phương pháp này hoạt động như thế nào?
Minimal dụ để làm cho mọi việc rõ ràng hơn:
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;
}
Biên dịch và chạy:
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
Output:
4
Thử nghiệm trên Ubuntu 14.04. Cũng làm việc với Oracle JDK 1.8.0_45.
Example on GitHub để bạn có thể chơi cùng.
Giải thích:
Nó cho phép bạn:
- gọi một thư viện tự động nạp biên soạn (ở đây viết bằng C) với mã lắp ráp tùy ý từ Java
- và nhận được kết quả trở lại vào Java
Điều này có thể được sử dụng để:
- viết mã nhanh hơn trên một phần rất quan trọng với các hướng dẫn tốt hơn CPU lắp ráp (không CPU di động)
- thực hiện cuộc gọi hệ thống trực tiếp (không phải hệ điều hành di động)
với sự cân bằng của tính di động thấp hơn.
Nó cũng có thể để bạn có thể gọi Java từ C, nhưng trước tiên bạn phải tạo một JVM trong C: How to call Java functions from C++?
Ví dụ trong OpenJDK 8
Hãy tìm thấy nơi Object#clone
được định nghĩa trong jdk8u60-b27.
Đầu tiên chúng ta thấy:
find . -name Object.java
đó đưa chúng ta đến jdk/src/share/classes/java/lang/Object.java#l212:
protected native Object clone() throws CloneNotSupportedException;
Bây giờ đến phần cứng, tìm nơi clone là trong bối cảnh tất cả các gián tiếp. Truy vấn đã giúp tôi là:
find . -iname object.c
sẽ tìm thấy tệp C hoặc C++ có thể triển khai phương pháp gốc của Object.Nó đưa chúng ta đến 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]));
}
dẫn chúng ta đến JVM_Clone
biểu tượng:
grep -R JVM_Clone
đó đưa chúng ta đến hotspot/src/share/vm/prims/jvm.cpp#l580:
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Sau khi mở rộng một loạt các macro, chúng ta đến kết luận rằng đây là điểm định nghĩa.
nếu hashcode() được thực hiện bởi JVM chỉ tại sao nó yêu cầu phải là * gốc *? Chính xác bạn ngụ ý gì bởi * nội tại * ở đây? – Geek