Usage of native in Java [duplicate]
Can someone explain the whys and the wherefores for using native keyword in Java?
Can someone explain the whys and the wherefores for using native keyword in Java?
Once you see a small example, it becomes clear:
Main.java:
public class Main {
public native int intMethod(int i);
public static void main(String[] args) {
System.loadLibrary("Main");
System.out.println(new Main().intMethod(2));
}
}
Main.c:
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_intMethod(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
Compile and run:
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 with Oracle JDK 1.8.0_45.
So it is clear that 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 on GitHub for you to play with.
DISCLAIMER: part of this answer comes from my earlier answer. I believe that I have directly answered the OP's question in each.
- You may have a non-Java library that for whatever reasons you have to use in your Java project
- You may need to integrate some old or rarely used hardware and need to implement the interface which may be much easier in C/C++
If you want to solve a performance issue with native code than there's a 99.5% chance that this is the wrong approach ;-)
In my experience, the downsides of using native code libraries are significant:
JNI / JNA have a tendency to destabilize the JVM, especially if you try to do something complicated. If your native code gets native code memory management wrong, there's a chance that you will crash the JVM. If your native code is non-reentrant and gets called from more than one Java thread, bad things will happen ... sporadically. And so on.
Java with native code is harder to debug than pure Java or pure C/C++.
Native code can introduce significant platform dependencies / issues for an otherwise platform independent Java app.
Native code requires a separate build framework, and that may have platform / portability issues as well.
Generally speaking, you don't gain much (if any) extra performance by using native code. While you might think your C/C++ will be more performant than Java, the JIT compiler does a pretty good job of optimizing these days, and you have to consider the performance costs of making JNI calls and other interactions across the JNI boundary.
Generally specking, you should treat JNI / JNA as a "last resort" option. If there is any other way of solving the problem, that way is probably better.
As a web developer you are more likely to come across native
if you use Google Web Toolkit. With that framework you essentially write Java code which is then compiled to Javascript that can run in a browser. In GWT, the native
keyword is used to make calls to "native" Javascript code.
The term to look for is JSNI.
- performance
- tighter integration with native environment
- need to use native library with unique features
examples: JAI (image processing), Java 3D (OpenGL), JDIC (desktop integration)
Java is platform-independent, which means that the programs you write in Java can run on any operating system - you don't even need to recompile, the compiled class files should run on any operating system.
Sometimes, however, you need to do something in your program that's very specific to a certain operating system, and there might not be a pure Java way to do what you need to do; or you might need to call an existing non-Java library. The Java platform provides JNI (Java Native Interface) as a way to call operating system specific code.
You should use native code sparingly, however, because it ties your program to a specific operating system.
Here are some quotes from Effective Java 2nd Edition, Item 54: Use native methods judiciously:
Historically, native methods have had three main uses. They provide access to platform-specific facilities such as registries and file locks. They provided access to libraries of legacy code, which could in turn provide access to legacy data. Finally, native methods were used to write performance-critical parts of applciations in native languages for improved performance.
It is legitimate to use native methods to access platform-specific facilities, but as the Java platform matures, it provides mroe and more features previously found only in host platforms. [...] It is rarely advisable to use native methods for improved performance [...]
The use of native methods has serious disadvantages. Because native languages are not safe, applications using native methods are no longer immune to memory corruption errors. Because native languages are platform dependent, applications using native methods are far less portable. Applications using native code are difficult do debug. There is a fixed cost associated with going into and out of native code, so native methods can decrease performance if they do only a small amount of work. Finally, native methods require "glue code" that is difficult to read and tedious to write.
The entire item has more detailed explanations on the issues. Along with the entire book, it is highly recommended.
See also
- Wikipedia/Java Native Interface
GWT's HTML widget class has this gem for pretty-printing. Not too helpful when you want to inspect the pretty-printer code :(
/**
* All of the markup and content within a given element.
*/
public final native void setInnerHTML(String html) /*-{
this.innerHTML = html || '';
}-*/;
精彩评论