tags:

views:

1510

answers:

11

I'm currently developing on a project written in Java. We have a bunch of algorithms written in C/C++ (at least a couple hundred) that need to be incorporated in our project. Our two options are to use JNI to call this code, or to rewrite all the algorithms in Java.

I am aware of the consequences of using JNI, it can open up a whole new set of problems, which is why rewriting all the code in Java is even being considered. But the thought of rewriting it seems...wrong. The algorithms have been tested and work as far as I know, they're just in the wrong language.

In this situation, would JNI make this task easy? Or would it cause more headache than rewriting the code in Java would?


EDIT #1: Related Question - Usefulness of JNI


EDIT #2: FYI - Our Java project is not meant to be portable in any way. That might eliminate one of the downsides of JNI in that it supposedly reduces portability.

+8  A: 

If the "algorithms" are well-packaged, perhaps it's possible to create some automatic glue code, through JNI? That would cut down on the risk of errors (creating hundreds of individual components manually sounds risky), and make the cost independent of the number of algorithms to add, more or less.

Rewriting hundreds of components sounds very risky, I would definitely recommend at least investigating JNI more closely first.

What I/O requirements do the algorithms have with respect to the rest of the project? If they are fairly loosely coupled, perhaps it'd be possible to run them as free-standing separate programs, invoked as sub-processes from Java and using e.g. stdio to share data?

unwind
+10  A: 

I think the answer lies in the amount of coupling there would be between the calling java code and the invoked C/C++ code and in the level of effort the rewrite would entail. If your C code takes a few integers, does some hairy calculation, and returns another int. Use JNI. If there's a lot of complex back and forth, but the algorithms are reasonably simple, rewrite 'em. The fault line is the JNI connection. If that's going to be complex, you may end up writing more JNI interface code than you would algorithm code for a rewrite.

sblundy
Related thought: When I consider rewriting C code in Java, I assess how much effort is needed by going through the original C code and looking how much pointer magic is used. In some cases the overuse of pointer "shortcuts" makes the code plain horrible (not impossible!) to turn into neat OO code.
Esko
+5  A: 

I'd still seriously consider going for JNI, particularly if you're able to minimize the number of cross-language interfaces.

If, for example, there's a whole stack of C functions that all have the same inputs and outputs, but just do different work on the inputs, wrap that up in a single JNI wrapper with an additional parameter to specify which specific algorithm to use.

Alnitak
+1  A: 

Give JNI a try. Then if faced with any problems you may rewrite the problematic ones or wrap JNI calls with webservices and deploy them on different boxes or virtual boxes.

Boris Pavlović
+5  A: 

If you plan to write future projects in Java, as opposed to C/C++. I would bite the bullet now, and port the code over to java. The longer you wait the worse it will become. The JNI sounds attractive in this case, but then you will have the problem of somebody having to maintain the C++ code when everyone else is on the fun new Java projects.

If this is a one time Java project, then why are you writing it in Java?

grieve
It's not a one time Java project, the C/C++ code is old. I never thought about it from that perspective. Good advice.
Ryan Thames
Glad I could help.
grieve
A: 

If this is Windows-only, and they're already in a DLL, perhaps JNA would be of use. (if the performance hit for function calls through JNA isn't too bad)

Jason S
A: 

Read Joel's receint post on "Paying down your technical debt" then go ahead and convert it now rather than pay interest over the next couple years and then paying it off.

Perhaps the repackaged libraries could be useful in more places as well. If they are useful and complex enough to make you consider keeping them in C, they must have even more use once packaged nicely in reusable, easily distributable and understandable classes.

Bill K
+10  A: 

The simple answer is, if the code is going to be called a lot AND performance matters then convert it over to Java.

The more complex answers are:

  • if the library easily wrapped in JNI then go with JNI
  • if the tests you have for the C/C++ code easily converted over to Java then go for the port

I would do the following:

  • take one of the algorithms and wrap it in JNI
  • take the same algorithm and convert it to Java
  • see which is more of a pain to do
  • if speed matters then profile both versions and see which of them is acceptable.
TofuBeer
+1  A: 

The bridge between C and Java is expensive, so if you have to pass a lot of data back and forth there is no win in calling C over JNI.

I have seen JNA listed as a reasonable alternative to JNI with a lot less pain to call methods in a DLL/shared library from Java in a reflection like way. I have not tried it yet.

You may want to consider compiling your C code as a Linux MIPS binary which can be interpreted in Java. Reasonably fast, a bit hard to set up correctly. See http://nestedvm.ibex.org/

Also you may use a llvm backend to gcc to compile to lowlevel bytecodes which can then be interpreted in Java. THis is also the approach taken with the iPhone SDK afaik on Mac OS X. http://llvm.org/

Thorbjørn Ravn Andersen
LLVM generates bitcode and it is not related to JVM bytecode. LLVM is much more low level and to run in the JVM or CLR you need to use the VMKit project which is still in its infancy.
Paulo Lopes
LLVM generates bytecode. Just not Java byte code...
Thorbjørn Ravn Andersen
Thanks for the NestedVM link.
Liran Orevi
@Thorbjørn: I think, big amount of data can be passed by reference. Do you mean with your message, that passing a data is a bottleneck? You you meant that frequent calls to JNI function may be a bottleneck?
dma_k
Unless you design your data structures very carefully (which requires hands-on experience) you will need to transfer data between C data structures and Java objects. That process is "expensive".
Thorbjørn Ravn Andersen
+6  A: 

I think you'll find that using JNI is not as daunting as it seems prior to diving in. There are some important trade-offs and limitations but in general JNI works well and is reasonably easy to leverage as you intend.

As other have said the best case for JNI is:

  • Complex native code (bonus points if that code has already proven very reliable)
  • Minimal back-and-forth between Java and native code (you want to minimize the trips across the JNI layer)
  • Reasonably simple calling interface to the native code (or also back to Java if you're native code needs to leverage Java objects/methods)

It is definitely possible to automate or pseudo-automate the creation of a JNI layer for a reasonably structured set of native components. That would be well worth it if the number of components to wrap is large.

The good news with JNI is that it should be straightforward for you to build and test this interface, for example you should be able to write test cases from Java that exploit existing algorithm behavior and if there are problems they would most likely be in the JNI layer itself and not the algorithms (given your confidence in the native implementation).

Rewriting a large number of C/C++ algorithms in Java seems much more risky to me than using JNI. Without knowing the details it is hard to gauge, of course, but there are subtle differences between the technologies that I could imagine impacting the actual implementation of an algorithm, not to mention just the sheer engineering effort and risk of error.

A final consideration is future life of these algorithms or related components. Is the set of algorithms more or less complete, or are you continuing to add? Either way, is there a strong maintenance and/or future development reason to favor one technology over the other? For example, if everything else is in Java and all new algorithms will be in Java and almost everyone on the team is almost always coding in Java, reimplementing in Java starts to look more attractive long-term.

However even with that said, working trumps consistent. For a large number of well-functioning native components I would still be inclined to start with JNI even if you were going to transition to Java long-term.

Jeremy Rishel
A: 

I've been in this situation. I suggest that you get used to using the multi-threaded data structures that are available in Java. At this point you won't want to go back to your C++ data structures any more.

You'll also realize that you can re-write those algorithms much better using more thoughtful techniques, better polymorphism, adapter patterns and so forth.

When you're sitting in the C/C++ code, you're thinking that you want to hang on to it. You're thinking about all the love you put into it. In a few years, you'll realize that by holding onto it and using JNI that you've created a monster. Every time you get a process crash you'll regret using JNI. After fixing the process crash, someone will want to modify an algorithm in C++ and you'll want to throttle them. They'll have a convenient excuse like "I'm not used to Java yet."

Take a look at immutable data structures in Java. Don't even think about the speed that these old C/C++ algorithms execute. I've found that my new code far out-paces any of my old C/C++ code.

Write unit tests. Use NetBeans.

Kind Regards,

-Stosh

johnstosh