JNA seems a fair bit easier to use to call native code compared to JNI. In what cases would you use JNI over JNA?
JNA does not support mapping of c++ classes, so if you're using c++ library you will need a jni wrapper
If you need a lot of memory copying. For example, you call one method which returns you a large byte buffer, you change something in it, then you need to call another method which uses this byte buffer. This would require you to copy this buffer from c to java, then copy it back from java to c. In this case jni will win in performance because you can keep and modify this buffer in c, without copying.
These are the problems I've encountered. Maybe there's more. But in general performance is not that different between jna and jni, so wherever you can use JNA, use it.
EDIT
This answer seems to be quite popular. So here are some additions:
If you need to map C++ or COM, there is a library by Oliver Chafic, creator of JNAerator, called BridJ. It is still a young library, but it has many interesting features:
Dynamic C / C++ / COM interop : call C++ methods, create C++ objects (and subclass C++ classes from Java!)
Straightforward type mappings with good use of generics (including much nicer model for Pointers)
Full JNAerator support
works on Windows, Linux, MacOS X, Solaris, Android
As for memory copying, I believe JNA supports direct ByteBuffers, so memory copying can be avoided.
So, I still believe that wherever possible, it is better to use JNA or BridJ, and revert to jni if performance is critical, because if you need to call native functions frequently, performance hit is noticeable.
It's difficult to answer such a generic question. I suppose the most obvious difference is that with JNI, the type conversion is implemented on the native side of the Java/native border, while with JNA, the type conversion is implemented in Java. If you already feel quite comfortable with programming in C and have to implement some native code yourself, I would assume that JNI won't seem too complex. If you are a Java programmer and only need to invoke a third party native library, using JNA is probably the easiest path to avoid the perhaps not so obvious problems with JNI.
Although I've never benchmarked any differences, I would because of the design, at least suppose that type conversion with JNA in some situations will perform worse than with JNI. For example when passing arrays, JNA will convert these from Java to native at the beginning of each function call and back at the end of the function call. With JNI, you can control yourself when a native "view" of the array is generated, potentially only creating a view of a part of the array, keep the view across several function calls and at the end release the view and decide if you want to keep the changes (potentially requiring to copy the data back) or discard the changes (no copy required). I know you can use a native array across function calls with JNA using the Memory class, but this will also require memory copying, which may be unnecessary with JNI. The difference may not be relevant, but if your original goal is to increase application performance by implementing parts of it in native code, using a worse performing bridge technology seems not to be the most obvious choice.
You are writing code a few years ago before there was JNA or are targeting a pre 1.4 JRE.
The code you are working with is not in a DLL\SO.
You are working on code that is incompatible with LGPL.
That is only what I can come up with off the top of my head, though I am not a heavy user of either. It also seems like you might avoid JNA if you wanted a better interface than the one they provide but you could code around that in java.
By the way, in one of our projects, we kept a very small JNI foot print. We used protocol buffers for representing our domain objects and thus had only one native function to bridge Java and C (then of course that C function would call a bunch of other functions).
It's not a direct answer and I have no experience with JNA but, when I look at the Projects Using JNA and see names like SVNKit, IntelliJ IDEA, NetBeans IDE, etc, I'm tend to believe it's a pretty decent library.
Actually, I definitely think I would have used JNA instead of JNI when I had to as it indeed looks simpler than JNI (which has a boring development process). Too bad, JNA wasn't released at this time.
I actually did some simple benchmarks with JNI and JNA.
As others already pointed out, JNA is for convenience. You don't need to compile or write native code when using JNA. JNA's native library loader is also one of the best/easiest to use I've ever seen. Sadly, you can't use it for JNI it seems. (That's why I wrote an alternative for System.loadLibrary() that uses the path convention of JNA and supports seamless loading from the classpath (ie jars).)
The performance of JNA however, can be much worse than that of JNI. I made a very simple test that called a simple native integer increment function "return arg + 1;". Benchmarks done with jmh showed that JNI calls to that function are 15 times faster than JNA.
A more "complex" example where the native function sums up an integer array of 4 values still showed that JNI performance is 3 times faster than JNA. The reduced advantage was probably because of how you access arrays in JNI: my example created some stuff and released it again during each summing operation.
Code and test results can be found at github.
If you want JNI performance but are daunted by its complexity, you may consider using tools that generate JNI bindings automatically. For example, JANET (disclaimer: I wrote it) allows you to mix Java and C++ code in a single source file, and e.g. make calls from C++ to Java using standard Java syntax. For example, here's how you'd print a C string to the Java standard output:
native "C++" void printHello() {
const char* helloWorld = "Hello, World!";
`System.out.println(#$(helloWorld));`
}
JANET then translates the backtick-embedded Java into the appropriate JNI calls.
I investigated JNI and JNA for performance comparison because we needed to decide one of them to call a dll in project and we had a real time constraint. The results have showed that JNI has greater performance than JNA(approximately 40 times). Maybe there is a trick for better performance in JNA but it is very slow for a simple example.
Unless I'm missing something, isn't the main difference between JNA vs JNI that with JNA you can't call Java code from native (C) code?
In my specific application, JNI proved far easier to use. I needed to read and write continuous streams to and from a serial port -- and nothing else. Rather than try to learn the very involved infrastructure in JNA, I found it much easier to prototype the native interface in Windows with a special-purpose DLL that exported just six functions:
DllMain (required to interface with Windows)
OnLoad (just does an OutputDebugString so I can know when Java code attaches)
OnUnload (ditto)
Open (opens the port, starts read and write threads)
QueueMessage (queues data for output by the write thread)
GetMessage (waits for and returns data received by the read thread since the last call)
Related
I'm working on an OpenCV project that is currently prototyped in python, but I want to make work in Android.
I thought it would be better to start with straight java and then move that to Android, but OpenCV for java doesn't seem to be as fully implemented as it is for Python and C++ (for example it doesn't have imshow). So now I'm not sure how easy the conversion from Python to Java will be.
Since Python to C++ has been relatively easy in the past for me when working with OpenCV, it got me thinking of other options. I see that you can run pre-compiled C++ code in Android, so that may be an option. The issue that I see is that I'm not sure how well I can pass the data I need. What sorts of limitations are there when communicating between Android Java and the pre-compiled C++? And is the pre-compiled C++ allowed access to the filesystem, so it can read images?
You can pass any data that java supports. Obviously you can't pass C++ classes as is (though you can pass a pointer as long, keep in Java and then pass it back to C++ where it can be used again).
On C++ side, through JNI APIs you can do everything you can do with Java code. However, it will require an extra work and clear understanding about thread binding, JNI context and JNI/Java memory management.
On Java side, you can pass to C functions strings, primitive types (easy) or complex types and then use JNI to access fields, call methods, throw exceptions and so on.
There are some pitfalls about memory management, if you allocate Java heap from inside C++/JNI, read carefully about allocations, lifecycle and reference types.
Android-specific, you also may want to read some JNI Tips
Android native can access IO and filesystem at least with the same functionality as regular Android Java apk. You may look here for an example and a discussion File Operations in Android NDK
I have to use some static windows library (*.lib) from java code, I can write C++ JNI wrappers, but I'd rather not do it (not that experienced in C++).
What would be the easiest (least developement effort) way use it, performance is not important, since that code will just be fetching some data, that most probrably will be worked on on JAVA side.
Most probably I would use JNA, but AFAIK it needs dynamic libraries, and I have static ones.
I also asked question on converting static libraries to dynamic ones.
You can always create a DLL (dynamic library) project which calls directly into your static library, and then you can use JNA with the new created DLL.
For what it's worth, I had a project like this awhile back. It was pretty easy to auto-generate the JNI wrappers. I think we had about 350 function exports to wrap. It took us about 3 hours to put together a script to auto-generate the wrapper (sorry, don't have the script laying around handy or I'd post it).
We wrote almost no C++ code ourselves - but it did require understanding how JNI works... That's actually a pretty good learning opportunity/project - if you have the time, don't be afraid of JNI - you'll be amazed at how much you learn about how the JVM works...
If you do go this route, I recommend that you keep your wrapper functions really, really lightweight - literally no processing in them at all. Just transform the necessary arguments from JNI values to native (this is mostly needed for strings), call your native function, and transform the results back.
If you have a function that passes in a string pointer and expects the string to come back in the pointer, use a string array with size 1 from the Java side and populate it with the result from the native call.
Or if you are pressed for time, compile your .lib to a .dll and use JNA :-)
I have two options - I can either use JNI or use Runtime.exec to execute a C++ library.
The C++ program is CPU intensive and long running i.e. some calls may take up to a couple of hours to return.
What are the pros and cons of each?
Which approach should I go for?
If you need to interact with the C++ library, go for JNI.
If it's a standalone program that you just want to invoke (and perhaps grab the output), Runtime.exec() is much, much simpler.
Have you looked into JNA as a third option?
From the JNA site:
JNA provides Java programs easy access
to native shared libraries (DLLs on
Windows) without writing anything but
Java codeāno JNI or native code is
required. This functionality is
comparable to Windows' Platform/Invoke
and Python's ctypes. Access is dynamic
at runtime without code generation.
See their getting started guide for an introduction.
Using JNI may restrict your ability to move from 32bit to 64 bit. You may also find you have to tune the application memory settings as well.
Unless you know how well the C++ stuff is written - it could make your app more unstable. You are lucky in that the C++ bit takes a few hours - so just call it externally.
Is there a way to call STL libraries from JNI, I believe JNI provides a C like interface for native calls, how do we achieve this for the C++ template libraries?
I agree that if you're looking for just the plain STL, you could probably use a Java library instead. However, if you insist on wrapping STL, SWIG provides some STL wrapping in JNI out of the box (see this for the basic mechanism), which should produce relatively stable, tested code.
I know this is possible, although I haven't done it myself. But JNI code can crash the JVM if you are not VERY CAREFUL. Also, JNI code is much more difficult to maintain than Java code. I was on one project where the Java -> JNI -> STL and COM code was thrown away and we replaced it with C# accessing the same STL and COM and a socket. We never looked back.
If you are doing only a small amount of JNI, it may be worth it. If you are creating a large interface via JNI, I strongly recommend instead writing the component that interacts with STL in C# instead of Java, and using a socket to communicate between the C# and Java components. It will be far easier to write, test, and maintain.
I have to ask why you find it necessary to use the STL libraries from Java. Is there something in them that's not provided by Java's own massive set of libraries?
I understand why you'd have to call your own code (and I'm assuming you've profiled the Java code and found it wanting, otherwise your effort is wasted) but you seem to be asking how to call STL stuff directly.
We've often had trouble with JNI and it makes our code less portable, so you have to have a very good reason for wanting to use it in our shop, and you have to prove with hard data, why the Java-supplied stuff is not adequate.
Yes. You required to use the swig typemap to convert C++ STL classes to Java objects... and vice versa.
For more information, please visit,
http://www.swig.org/Doc2.0/Android.html
Has anyone successfully "wrapped up" a C++ API in Java or .NET? I have an application that provides a C++ API for writing plug-ins. What I'd like to do is access that API from .NET or Java.
Would I need to use COM, or are there simpler/better alternatives?
If you have a very straight forward method signatures (i.e. methods that takes and returns primitive types such as int, char[], void* ... etc), it is reasonably easy to do so in .NET and still possible but a bit harder in Java with JNI.
However, if your class methods uses modern C++ programming techniques such as boost shared pointers and STL containers then it is a very different story. You will need to be really careful with memory management in this case.
EDIT:
It is gonna be even more interesting if the method has C++ template arguments because C++ template system is very different from C# or Java generics in that it is only a compile time mechanism. Basically this means the signature of the method or class is different every time you pass a different data type to the template argument. This made the method impossible to wrap in C# or Java.
I think that you may be asking to something similar to the Java Native Inferface It allows you to call code written in languages such as C++. I've never worked with it though. But you may want to check it out. Hope it helps.
On the Java side there are many options here .. this question actually is fairly close to what you are looking for provided your API can be boxed in a DLL, com or activex objects.
I personnaly used JIntegra to wrap API calls to office (Word) and used it directly witin Java. It did take some hacking to get the desired functionnality but we ended up making it work. The fidling was actually on the Word side, the actual integration was relatively easy.
If you are going to use .NET, I would recommend creating a C++/CLI wrapper. C++/CLI lets you mix the managed .NET code with native C++ code. There are some tricks to this approach, but it works very well in majority of cases.
Wikipedia entry has also some good links.
Using SWIG to handle the JNI stuff makes wrapping a cpp API and using it from Java quite painless.
Here's a SWIG tutorial
I'm the lead author on SlimDX. It may not be the largest open source interoperability project out there, but at 150K+ lines across the project, it's fairly substantial. It's written using C++/CLI, which is a Microsoft developed language, largely compatible with C++, that is designed to allow you to build wrappers. It works very well, with the caveat that it is Windows only. Mono will not take it. I don't know how much of a concern that is for you, but it's probably a better alternative than COM. Unfortunately there's a lot of tips and tricks that you have to basically come up with yourself. I've meant to blog about a lot of the ones we use on SlimDX, but somehow I never quite get around to it.
On the Java side, I believe you have to use JNI. Good luck with that. I've never talked to anyone who's worked with JNI without both of us laughing at it, in a bad "ouch that hurt" sort of way.
I maintain software that is implemented in C++ but must have interfaces in multiple languages including Java and .NET, but also including delphi and VB6. Plus, it has to work on multiple platforms (so Java needs to work on unix).
The way it was done was to use a single DLL exporting plain C functions using primitive types. For example, given an class Foo:
long MY_EXPORT_FLAG FooCreate()
{
return (long)new Foo();
}
void MY_EXPORT_FLAG FooDestroy(long Handle)
{
delete (Foo*)Handle;
}
void MY_EXPORT_FLAG BarMethod(long Handle, const char* pStr1, long* pReturnValue)
{
*pReturnValue = ((Foo*)Handle)->BarMethod( pStr1 );
}
Then your JNI/.NET/VB6/Delphi code implements language specific class wrappers, but call these C dll functions. Each class wrapper would contain a Handle, and pass it into the C functions.
This works quite well because most languages tend to use C as the lowest common denominator, so as long as you can export your interfaces through a thin C api you can build interfaces for other languages.
We export a C (and not C++) api in the DLL because function signatures are much more standardized across platforms.
Don't forget, that on C# and Java, you'll have to deal with multibyte string encoding, so you should figure out how to transcode your strings to/from your C++ code. This typically involves knowing about locales, or you can cheap out and just support UTF-8.