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.
Related
I want to make a program that would be able to manipulate the desktop based on user input commands (Preferably by voice, but... baby steps). Similar to Windows Speech Recognition, or Cortana.
I would like to make this as easy as possible to use and set up etc. For this reason I had planned on writing it in Java so that it would be cross-platform, and as simple as possible for users.
After looking further into how I would go about this, I saw mentioned here (Manipulating windows from other applications in Java) that I should use JNI.
I'm now wondering if (as mentioned in the top comment) it would be easier if I were to switch to C++ as using JNI might negate the cross-platform capability benefits of Java?
Or if possible, would it be possible to have the program select the appropriate JNI classes automatically based on the operating system?
In short: Does JNI negate the benefits of Java cross-platform compatibility?
Sorry if this post is a bit confusing. I've quite a few questions so this may seem a bit all over the place.
Many Operating System specific tasks cannot be done platform independent. But what Java already does a lot and JNI allows you to do too is that you can have different native binaries for different platforms - and possibly a single Java API to use all of them platform-independent.
Going C++ has the disadvantage that you need to have multiple executables. With Java you could have just 1 that loads different native code.
Although if you need a lot of different native code to implement your idea, maybe it's easier to just implement it for just 1 platform directly in a language that has bindings to all the required native APIs. Like maybe C# for Windows and something else for other platforms?
This may be a bit of an odd question, but I would like to know if you can use Java inside c++14. I don't really care for GTK (I find it confusing and over complicated). Swing, however, is very easy to use, and you can get a working project very quickly. So I would like to know if you can use Java Swing inside c++, so I can use Swing as the foreground, as in what you see like graphics, and use c++ for the background, as in stuff you cant see, like calculations and objects and stuff. So if I can have c++ code tell Swing what to look like, or when to update, that would be very useful for the project I have in mind. Thanks in advance for any advice I may receive.
EDIT: Being able to use c++14 inside Java would be acceptable as well. Also, if anyone could get me example code also, this would be very helpful. Thanks!
You shouldn't run Java from C++, but rather C++ from Java. Oracle gives you a way to load native shared libraries, using JNI.
So you would create your view in Java, using Swing, then you would update your view by calling C++ functions that were pre-compiled and exported in a shared library.
That said, using JNI is quite tricky and the speed improvements of C++ might not be worth it; so you should consider using only Java (or only C++ and a library to create your GUI, such as Qt)
In which direction you go is a matter of taste (loading the JVM from a C++ program or loading DLLs from the JVM side).
Usually you go the way which is more logical, e.g. if you already have a C++ program you likely want to load the JVM from the C++ side. That would be your case. Especially if the Java you want to add is essentially "scripting" the C++ application.
If you already have a Java program and want to access a C++ DLL, you load the DLL from Java and write a simple JNI / native Java class.
In our times you would use tools like JNA for that (instead of JNI): https://github.com/java-native-access/jna
Or you can use SWIG to generate wrappers for your C++ classes: http://www.swig.org/
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)
Are there inexpensive or free gateways from .NET to Java? I'm looking at some data acquisition hardware which has drivers for C/C++ and .NET -- I really don't want to do any programming in .NET.
Update: I haven't done what I originally wanted to do, but I've done something similar, using JNA to encapsulate some functions from a DLL, in order to control a USB hardware device from Java. (the DLL comes from the device manufacturer) It works really nicely. Thanks!
You could also try to use JNA for accessing the native library. 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. If their API is fairly straight foward, this might be the path of least resistance.
See their getting started guide where they call some native code (printf and GetSystemTime).
Well, there's JNBridge and EZ JCom, just from a Google search.
You could also use IKVM which is a slightly different approach.
(Any reason for not wanting to learn .NET, out of interest? It's a nice platform, and C# is a lovely language...)
If they have C++ versions of the drivers then you could write a wrapper around it using JNI and then load that in Java. JNI can be a bit of a pain, but it would let you use the C++ version of their drivers and not have to deal with .Net at all if you don't want.
I am partial to the recommendation to jump in the deep end with C# since it is so similar to Java. I did this and used IKVM to compile my favorite Java libs. to .NET assemblies and you get [nearly] all the core java runtime classes to boot, so if you tire of trying to find just the right C# collection type, you can always go back to java.util. (No generic collections though. Not sure why.)
Depending on what platform you're on, you have several choices for free IDEs too. For windows you can get Visual Studio Express for free but I also use SharpDevelop. You can also get the Mono IDE on Linux (and a few flavours of Unix, I think ?).
The C# learning curve is shallow if you already know Java. I only blew off 1.5 limbs on landmines that came out of nowhere for reasons I still don't understand, but workarounds were easy to come by. The worst thing about it was the darn developer docs which are AWFUL on account of being so slow. I really miss the snappiness of JavaDoc. Not only are the online docs incredibly slow, the problem is compounded by someones's iffy decision to put class summaries, constructors and methods/properties all on seperate pages so it just takes forever. Someone said to get the docs installer and install docs locally for a slightly improved experience. Not a bad idea I suppose.
I am author of jni4net, open source interprocess bridge between JVM and CLR. It's build on top of JNI and PInvoke. No C/C++ code needed. I hope it will help you.
If you have a Java application, the JNI mentioned by the others will be the way to go. You write some wrapper classes, and that's it.
If writing the wrappes is a too big task (depending on the number of methods you have to wrap), have a look at SWIG . I think it generates wrappers automatically, but I never actually used it.
If you want to code in the Java language, but you don't care if your program will run on the JRE/JVM, then you might as well use Microsoft J#. Basically, it's writing Java-Code wich is compiled to .NET-Bytecode and can use the .NET classes of the driver as well as your existing Java classes. With J# you will run into problems if your existing Java-code is newer than Java 1.4, look at this question on how to solve them.
From that point on, you could later add code in J#, C# or any other .NET language. However, you won't get back to the JRE/JVM easily.
Does anyone know of a way to issue commands to a hard drive within Java? Does Java even support this kind of hardware interaction?
For example, if I have a SCSI hard drive that I would like to inquiry, is there a pre-existing Java method to do this, or would I have to write my own?
http://en.wikipedia.org/wiki/SCSI has some general information on SCSI commands in case you aren't familiar.
Java doesn't support talking directly to hardware like that. However, you can use JNI to call a C/C++ function from Java that can.
Three words "JNI or JNA". I strongly recommend taking a look at the latter to see if it suits your situation, instead of just opting for JNI.
No, since Java runs in a "virtual" machine rather than a real one. But it could be used as a bridge as dj mentioned earlier using JNI.
According to Wikipedia JNI can also call assembly directly. JNI could be used to call complete programs written in C or C++
you need to write the HDD interface code in C/C++ and then call that from Java using JNI