Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the native keyword in Java for?

While playing this puzzle (It's a Java keyword trivia game), I came across the native keyword.

What is the native keyword in Java used for?

like image 874
whirlwin Avatar asked May 23 '11 18:05

whirlwin


People also ask

Is native a Java key word?

native is a java keyword. It marks a method, that it will be implemented in other languages, not in Java. The method is declared without a body and cannot be abstract . It works together with JNI (Java Native Interface).

What is the use of native?

Adjective people who are native to France She has a native ability to learn quickly. The island is home to several native species of trees. Noun She's a native of France who moved to the United States when she was 15. He wishes he could speak Spanish like a native.

What is public native in Java?

A native method is a Java method (either an instance method or a class method) whose implementation is also written in another programming language such as C/C++. Moreover, a method marked as native cannot have a body and should end with a semicolon: [ public | protected | private] native [return_type] method ();

What is native method stack in Java?

Native Method Stacks. An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support native methods (methods written in a language other than the Java programming language).


1 Answers

Minimal runnable example

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 AMD64. Also worked with Oracle JDK 1.8.0_45.

Example on GitHub for you to play with.

Underscores in Java package / file names must be escaped with _1 in the C function name as mentioned at: Invoking JNI functions in Android package name containing underscore

Interpretation

native 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++?

Analogous native extension APIs are also present in many other "VM languages" for the same reasons, e.g. Python, Node.js, Ruby.

Android NDK

The concept is exact the same in this context, except that you have to use Android boilerplate to set it up.

The official NDK repository contains "canonical" examples such as the hello-jni app:

  • https://github.com/googlesamples/android-ndk/blob/4df5a2705e471a0818c6b2dbc26b8e315d89d307/hello-jni/app/src/main/java/com/example/hellojni/HelloJni.java#L39
  • https://github.com/googlesamples/android-ndk/blob/4df5a2705e471a0818c6b2dbc26b8e315d89d307/hello-jni/app/src/main/cpp/hello-jni.c#L27

In you unzip an .apk with NDK on Android O, you can see the pre-compiled .so that corresponds to the native code under lib/arm64-v8a/libnative-lib.so.

TODO confirm: furthermore, file /data/app/com.android.appname-*/oat/arm64/base.odex, says it is a shared library, which I think is the AOT precompiled .dex corresponding to the Java files in ART, see also: What are ODEX files in Android? So maybe the Java is actually also run via a native interface?

Example in the OpenJDK 8

Let's find find where Object#clone is defined in jdk8u60-b27.

We will conclude that it is implemented with a native call.

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.