views:

214

answers:

2

I've google'd around a bit, and haven't really found a good answer for my question: What is the customary way to pass back error information to java from native jni code?

I would normally just pick a design and go with it, but this code is called every 5 milliseconds, (approx), so I thought I'd ask if there's a customary 'clean / efficient' way to do this.

The way I see it, I have four obvious options:

  1. On each call, in java create an "error return" object and pass it through to the JNI. If there's a problem, the native code fills in the error description in this object, and the java code checks it on return. Since errors are not the common case, this creates a lot of objects for the GC to clean up, and 99.99% of them are unnecessary.

  2. Similar to #1, create some single "error return" object in the java class which is passed to each method call over and over. Check it in the java code on each return for errors. This seems dodgy to me, but maybe it's the proper option?

  3. Create an object in the native code which contains a description of the error if applicable, and pass it back as a return value to java. After the call in java, check the return for null. This seems less wasteful than #1, but it seems a bit awkward.

  4. Simply build a integer return value on the jni method, and pass back an int corresponding to the "exit" value of the native code. Enumerate all possible native exit states in a java map. Compare the return value to '0', and look up the error in this map if necessary. This appears more efficient than the others, but seems more clumsy, since a change in native code would require someone to go back and update the "error table".

I feel as though I'm missing something obvious... is there a guru out there that can offer any insight?

Thanks!

+4  A: 

Throw java exceptions: http://java.sun.com/docs/books/jni/html/exceptions.html?

ewanm89
Yep. The specific function you want is ThrowNew (http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp16104)
Matthew Flaschen
As the link I put describes, one needs to tell it to find the exception class to throw first.
ewanm89
True. Also, if you want to throw a exception object using a constructor other than single-arg String, you just construct it manually and use Throw.
Matthew Flaschen
Thank you so much, I've been in this C code now for 3 months, and I think it warped my brain- I was still thinking in C mode. It didn't occur to me that I could throw exceptions from C into java, so I was missing something after all. Thanks again.
JPDecker
you can catch them in C I believe too...
ewanm89
+1  A: 

Regarding the methods you noted:

  1. As you mentioned, this generates a lot of allocation/deallocation calls which.
  2. This method won't work if you have more than 1 thread calling your native code.
  3. This assumes you don't need the return value for anything else. There's also the question of where and when your error object is 'freed'.
  4. Assuming you're not using the return value for anything else and that you don't need any 'extra' information about the error, this is a good solution. The possible errors shouldn't change often enough that it would create a problem in updating the Java code.

Of course, if you do need your return value, and if you want more detailed information regarding the actual error, you should use exceptions.

Tal Pressman
I thought technically it is customary in java to throw an exception rather than use a return value?
ewanm89
It is in Java, but once you call native code it depends on the what it is you're calling exactly.
Tal Pressman
Yep, in this native code the pattern is that each method returns a success or failure value, and outputs are populated in passed references/pointers. So, I was still thinking in that mode for my solution. Thanks for the answers!
JPDecker