What are these natives and how do these methods work?
Minimal example to make things clearer:
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;
}
Compile and run:
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
Tested on Ubuntu 14.04. Also worked with Oracle JDK 1.8.0_45.
Example on GitHub for you to play with.
Interpretation:
It allows you to:
- call a compiled dynamically loaded library (here written in C) with arbitrary assembly code from Java
- and get results back into Java
This could be used to:
- write faster code on a critical section with better CPU assembly instructions (not CPU portable)
- make direct system calls (not OS portable)
with the tradeoff of lower portability.
It is also possible for you to call Java from C, but you must first create a JVM in C: How to call Java functions from C++?
Example in the OpenJDK 8
Let's find find where Object#clone
is defined in jdk8u60-b27.
First we find:
find . -name Object.java
which leads us to jdk/src/share/classes/java/lang/Object.java#l212:
protected native Object clone() throws CloneNotSupportedException;
Now comes the hard part, finding where clone is amidst all the indirection. The query that helped me was:
find . -iname object.c
which would find either C or C++ files that might implement Object's native methods. It leads us to 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]));
}
which leads us to the JVM_Clone
symbol:
grep -R JVM_Clone
which leads us to hotspot/src/share/vm/prims/jvm.cpp#l580:
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
After expanding a bunch of macros, we come to the conclusion that this is the definition point.