I've tried rewriting some java functions in c++ and called them using jni. I observed that it takes longer time to execute the native c++ functions as compared to java function, due to jni overhead. As it is widely believed that c++ has certain advantages over java. I wanted to know whether rewriting some java code to c++, with a view to improve overall performance of the java application, a good idea? If yes, then what parts of the application should be rewritten and how a java application can use it.
closed as too broad by gnat, GlenH7, Yusubov, MichaelT, Michael Kohne Sep 3 at 18:47
There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.
I would advise against it; in the latest releases JVM was improved very much and the performance differences are minimal, for typical production code. Moreover JNI itself is not free from the performance POV and overall you would lose performance rather than achieve more (as you have found out in your case). In addition to this, native code is not safe (you may have corrupt memory), are less portable and harder to debug.
Try to improve performance by classical techniques (better algorithms and data structures, optimization, reduced I/O overhead etc.) and Java techniques (JVM tuning). Only if you have legacy APIs in native code or you need to perform large computation extensive tasks is JNI recommended.
See also Item 54: Use native methods judiciously in Joshua Bloch's Effective Java (2nd edition) for a more advised reference.
I've used JNI now and then both in standard Java (desktop) applications and Android applications. Here's the gist of it all:
1 . Your question asks specifically if performance is improved by JNI: mostly, no. There are some very few and specific situations where performance is improved. 98.3% of the time this will not be the case. Also, adding JNI solely for performance benefits will greatly complicate your project (as compared to just writing it in Java or C/C++): There are a huge lot of very good tools (IDE, project management tools, libraries, testing tools etc) for Java-only projects (as they are for C and/or C++ -only projects). However there are a lot less (and, IMHO, of lesser quality) such tools that allow to deal with a mixed (Java) + (JNI) +(C and/or C++) project all in one go. More often than not you'll need to bring in separate tools for the Java part of your project, another for the C/C++ part of your project and maybe do a bit of custom tools developement (like scripts and such) for your JNI parts.
Here's an example: I've recently helped a friend with a Java project that had about 90% of its code use the BigDecimal and BigInteger classes. The code did a lot of the common (and some of the more exotic) algebraic operations with these: +-/* but also log, square roots and some I can't remember now. We also tried replacing those parts of the code with JNI and C code that used the MPFR library, after noticing that the features we were using out of Java's BigXXX API were also present in this library. Long story short, in this particular case, the performance gain was of about 10-15 times. Finally we decided to implement the whole module in C and only use Java for the UI along with non-granular JNI calls towards the new C module.
2 . I think the biggest reason why someone would use JNI is if he/she already has a lot of complex C and/or C++ code which needs to be integrated with Java code. One place where this may apply is when porting an existing video game to the Android platform: Most games are made in C/C++. Android, while at it's core runs on a Linux kernel and deals with C/C++ code, offers in fact a Java API (a Java development environment very similar to the JDK/JVM you get on your PC/Mac). In such a context, doing a thin Java wrapper around existing C++ code in orderto get an old game up and running on Android is a lot faster than converting all the C/C++ code to Java entirely. With the Java thin wrapper approache there is a loss of performance, but it may very well be negligeable, depending on the resource demands of the original game, etc.
Here's a quote from Android's documentation on this:
(Bad) Example (which illustrates the last point): I've implemented the A* pathfinding algorithim in Java. I've also made a small, simple graphical demonstration of it as an Android application. I then implemented that same algorithm in C. When running separate benchmarks of the Java and C code, C was sometimes 2-3 times faster (especially if there were a lot of GC when running the Java code). So I modified my all-Java Android app to make it use the C code via JNI. While the project got a whole lot more complicated (even when using the excellent Sequoyah Eclipse plugin) the actual performance gain was now more like 10-20%, no where near the 200-300% I was seeing when running the Java and C version of this particular code separately.
How ever (and here I quote from memory) one of the earlier Android books (from the Android version 2 era) gave an advanced example of taking the Quake C++ source code and using JNI to make it into an Android App in like 20 pages (about 2-3 hours of work). If the Quake C++ code was all translated to Java (hundreds of thousants of lines of code) instead, it would take a lot longer than that. And since even the Android devices of that time were able to "hide" the performance penalities that came with JNI calling the Quake game, it made for a good trade-off to use JNI here.