JNI's throw new does not throw an exception

Discussion in 'Java' started by yarona, Sep 6, 2005.

  1. yarona

    yarona Guest


    I'm trying to throw an exception from my native C++ code, the code
    snippet looks like this:

    jclass clsException = pEnv->FindClass("MyExceptionClass");
    if(clsException )
    pEnv->ThrowNew(clsException, "HelloWorld");

    The 'ThrowNew' method is called, but no exception seems to be thrown or
    caught on the Java side.

    ThrowNew returns 0 if it's any help, and if I call 'ExceptionCheck'
    afterwards, it returns 'true', before that it returns 'false' meaning
    that the exception pending is the one that I have just thrown.

    Any ideas would be appreciated,


    yarona, Sep 6, 2005
    1. Advertisements

  2. There's nothing wrong with the code you've posted, but there might be
    something wrong in the code you didn't post.

    For example, what is "ExceptionCheck()"? Do you mean

    Have you tried calling ExceptionDescribe() after ThrowNew() to see
    whether it really is your exception that's been thrown?

    How are you handling this in the caller?

    Gordon Beaton, Sep 6, 2005
    1. Advertisements

  3. yarona

    Roedy Green Guest

    Is there a debugger that lets you debug Java when in Java and C++ or
    MASM when in C++?
    Roedy Green, Sep 6, 2005
  4. I think your problem might be that after a ThrowNew, the native method
    does not abruptly terminate automatically. That is, flow of control
    returns to your native method, and the new exception is pending at this
    point. You need to "abort" your method manually if ExceptionOccurred()
    returns true (or handle the exception in native code, which is something
    i'd call "severe pain").
    Stefan Schulz, Sep 6, 2005
  5. yarona

    Roedy Green Guest

    Insert this after the Throw:

    pEnv->DeleteLocalRef( clsException );

    Your problem basically is that C++ knows nothing about Java
    exceptions. Exceptions are just control blocks lying about. It is up
    to you in some C++ish way, after you set up the exception, return
    quickly and gracefully up the call stack to your caller back in Java
    who can then handle the exception. On your way back, C++ can handle or
    notice the exception by explicitly testing for it with ExceptionCheck.

    In Abundance this is known as a "graceful bailout".
    Roedy Green, Sep 7, 2005
  6. yarona

    Roedy Green Guest

    Roedy Green, Sep 7, 2005
  7. No, don't. There is seldom any need for DeleteLocalRef(), and
    certainly not in this case.

    This is akin to telling him to null method local references before
    returning from a Java method.

    Gordon Beaton, Sep 7, 2005
  8. yarona

    yarona Guest

    Hello all, and many thanks for your replies,

    "ExceptionCheck()" is a method which is much like "ExceptionOccured"
    only it returns jboolean rather than a jthrowable.

    I am returning from the native method immidiatly after "ThrowNew" (
    actually I'm calling "ExceptionDescribe" first, and it is my exception
    that is thrown).
    I also put a break point in the exception object's c'tor on the Java
    side, and sure enough it's getting called, meaning that it's being

    The Java side looks something like this:

    MyThrower thrower = new MyThrower();
    thrower.ExceptionThrowingMethod(); // a native method
    catch(MyExceptionClass e)
    //handle exception

    MyExceptionClass is derived from java.lang.Exception

    But I never reach the catch clause - even though as I've mentioned, the
    "MyExceptionClass" object was constructed.


    yarona, Sep 7, 2005
  9. Hmm, I wasn't even aware that that method existed, but I see it now in
    the docs...
    This could very well be the problem: In my experience,
    ExceptionDescribe() seems to clear the exception, at least sometimes.

    Apparently others have also seen this behaviour:

    Try removing these checks from your native code. Just throw the
    exception, then return.

    Gordon Beaton, Sep 7, 2005
  10. Additionally, the JNI docs state clearly which JNI functions are safe
    to call when there is a pending exception (as is the case here), and
    DeleteLocalRef() isn't among them:


    Gordon Beaton, Sep 7, 2005
  11. yarona

    yarona Guest

    Also there's no need to call DeleteLocalRef() since I'm running from a
    native method, and not a utility method - the JVM releases all local
    refs for me.
    yarona, Sep 7, 2005
  12. yarona

    Chris Uppal Guest

    It's not relevant to this case, but for the record, there is one important
    category of application where DeleteLocalRef() is not optional.

    That is when your application uses JNI to call into Java, rather than the other
    way around. I.e. your main program is written in something like C, and it
    creates a JVM in order to make use of some Java library or other. In such
    cases, the C code that creates the reference has not been called /from/ Java
    so the automatic clean-up of local references does not occur (since that
    happens when the C code returns /to/ Java).

    There are other occasions when you might want to DeleteLocalRef(), but -- as
    Gordon says -- they are atypical. And anyway they are discussed in the JNI
    tutorial and documentation (which is, however, vague on the above point -- the
    writers preferring to pretend that the only reason for using JNI is to call
    "legacy" code from Java, an attitude I find insufferably arrogant).

    I have to make heavy use of the above technique, since I'm using JNI to call
    legacy Java code from Smalltalk...

    -- chris
    Chris Uppal, Sep 7, 2005
  13. I'll assume that "utiltity method" here refers to other methods in
    your native library, i.e. not your native methods themselves, but
    other functions in the native library that might be called by your
    native methods.

    If that's what you mean (and please explain if it isn't), then
    contrary to what you've implied, you wouldn't have needed to use
    DeleteLocalRef() in that case either.

    When a native method is invoked from Java, a local context is created
    to hold all object references created at (or below) that point. When
    you return back to the JVM (and thereby pass that point as you move up
    the stack), the local context is freed and any objects referred to
    (potentially) become eligible for garbage collection.

    So it doesn't matter if you pass the JNIEnv* to a helper function and
    create your objects there instead, as far as the JVM is concerned
    there is no difference.

    Have you solved the original problem?

    Gordon Beaton, Sep 7, 2005
  14. yarona

    yarona Guest

    Hi Gordon, thanks for your replies.

    This is going to be long so bare with me, trust me it's interesting :)

    You are correct, When I said "utility functions" I meant helper
    functions in my native code that are called from my native methods.

    You are also correct when you are saying that when returning to the JVM
    all local refs are released, but what happens if I allocate a local ref
    within a helper function, and then return from it to my native method,
    and after that go on doing some more native work? the local refs
    allocated inside the helper would not be released until I return from
    the native method to the JVM, taking up some precious space!!!

    As for the original problem - yes I have solved it, the problem was a
    wierd and suttle one:

    As I've gathered from all the posts here,and the JNI documentation,
    calling JNI functions after a call to ThrowNew, and before returning to
    the JVM is not safe (putting functions like ExceptionOccured and
    ExceptionCheck aside...)

    This means that posting an exception should preferably look like this:

    //no JNI calls here!!!

    otherwise the exception might never be thrown on the Java side.

    The interesting thing is that my code looks just like the above code(I
    took out the DecribeExceptionCall) - and still no exception - so there
    must have been something between the call to ThreadNew and the return
    that has been implicily put there by the compiler.

    I opened my disassembler, and sure enough I saw what happened:
    I wanted to make my native method thread synchronized, yet release the
    monitor upon an excetpion or returning from the method, in order to
    prevent a deadlock - I didnt want to return from the method and forget
    to call ExitMonitor, so I've written a little guard C++ class:

    class MonitorGuard
    MonitorGuard(JNIEnv* pEnv, jobject monitor)
    :m_pEnv(pEnv), m_monitor(monitor)
    if(m_pEnv && m_monitor)

    if(m_pEnv && m_monitor)

    JNIEnv* m_pEnv;
    jobject m_monitor;

    As you can see this class takes the monitor upon construction, and
    releases it upon destruction, this way, when I return from the native
    method, ExitMonitor is automatically called, and there's no danger for
    a deadlock.

    BUT... I fell in another pittfall, after I do this:


    the guard's destructor was implicitly called, after ThrowNew, and
    before returning to the JVM, thus calling ExitMonitor, which is
    apparently not included in the functions which are safe to be called
    after ThrowNew - so no exception was thrown.

    I solved it by createing a special scope for the synchronized code,
    throwing the exception outside of it like so:
    bool bThrow = false;
    jclass clsException;
    CMonitorGuard(pEnv, objThis); //objThis is the 'this' object passed
    in the JNI interface.
    //do some native work...
    if(clsException = pEnv->FindClass("MyExceptionClass")
    bThrow = true;
    //do some more native work;



    And behold, the exception was thrown on the Java side!!! hip hip

    That sums it up - JNI has many suttle pit falls, and this is one of
    them - so one has to be carful not to fall in it, be careful of
    implicit JNI code called after ThrowNew!

    Thanks once again for the great help,

    yarona, Sep 7, 2005
  15. Granted, but in most non-looping code the number of objects created
    this way is usually rather limited, and I'd usually let the JVM handle
    these things automatically for me.

    Still if you want to avoid keeping unused objects around any longer
    than necessary, one suggestion is to wrap those helper functions in
    calls to PushLocalFrame() and PopLocalFrame(), so you at least don't
    need to manage each reference individually.

    Have you considered simply declaring the native method synchronized? I
    realize that only synchronizes among calls to methods on the same
    object, but perhaps that's the case here.
    It was, and good work finding the solution!

    Gordon Beaton, Sep 7, 2005
  16. yarona

    Roedy Green Guest

    Odd. That came straight from Sun's textbook.
    Roedy Green, Sep 8, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.