I have a quick question about dealing with exceptions being thrown by libraries under JNA...
When I throw an exception in the underlying native code, JNA gets a invalid memory access error. I'm assuming this is because C libraries cannot throw an exception up through it's stack (it's actually C++/CLR but has C exports)? So is there no real way to report the exception to Java? Or "should it work" and I'm just doing something incredibly wrong?
DllExport void Initialize(char* dir)
{
throw gcnew System::Exception("Testing");
}
It would be nice for Java to be able to detect these thrown exceptions, and I guess I could actually look into passing a memory pointer into all my C exports and check to see if those are null or not, but seems like a roundabout way.
C++ exceptions can only be handled in C++ code. They should never be allowed to escape the C++ world (i.e., a C interface of C++ code should never let exceptions propagate). It is not even safe to let a C++ exception propagate through a layer of C code between two C++ modules (e.g., when a C++ function calls a C function which in turn calls a C++ function).
One of the reasons for this is that there is no standard on how C++ exceptions should be implemented, so C++ modules are only binary-compatible if compiled by the same compiler (in the same version). So code in any other language can't be set up to handle C++ exceptions.
In this case (C++ library, C interface, called from Java) you would have to catch the C++ exception, propagate the information through the C interface (e.g., by using error return codes), check for it in Java and throw an exception there.
You need to handle the c++ exception yourself and instead build a java exception which can be passed to the java side of the code.
Related
Suppose I'm embedding Sun's JVM in a C++ application. Through JNI I call a Java method (my own), which in turns calls a native method I implemented in a shared library.
What happens if this native method throws a C++ exception?
edit: compiler is gcc 3.4.x, jvm is sun's 1.6.20.
The Java compiler doesn't understand C++ exceptions, so you'll have to work with both Java and C++ exceptions. Luckily, that's not overly complicated. First we have a C++ exception that tells us if a Java exception has occurred.
#include <stdexcept>
//This is how we represent a Java exception already in progress
struct ThrownJavaException : std::runtime_error {
ThrownJavaException() :std::runtime_error("") {}
ThrownJavaException(const std::string& msg ) :std::runtime_error(msg) {}
};
and a function to throw an C++ exception if a Java exception is already in place:
inline void assert_no_exception(JNIEnv * env) {
if (env->ExceptionCheck()==JNI_TRUE)
throw ThrownJavaException("assert_no_exception");
}
we also have a C++ exception for throwing new Java exceptions:
//used to throw a new Java exception. use full paths like:
//"java/lang/NoSuchFieldException"
//"java/lang/NullPointerException"
//"java/security/InvalidParameterException"
struct NewJavaException : public ThrownJavaException{
NewJavaException(JNIEnv * env, const char* type="", const char* message="")
:ThrownJavaException(type+std::string(" ")+message)
{
jclass newExcCls = env->FindClass(type);
if (newExcCls != NULL)
env->ThrowNew(newExcCls, message);
//if it is null, a NoClassDefFoundError was already thrown
}
};
We also need a function to swallow C++ exceptions and replace them with Java exceptions
void swallow_cpp_exception_and_throw_java(JNIEnv * env) {
try {
throw;
} catch(const ThrownJavaException&) {
//already reported to Java, ignore
} catch(const std::bad_alloc& rhs) {
//translate OOM C++ exception to a Java exception
NewJavaException(env, "java/lang/OutOfMemoryError", rhs.what());
} catch(const std::ios_base::failure& rhs) { //sample translation
//translate IO C++ exception to a Java exception
NewJavaException(env, "java/io/IOException", rhs.what());
//TRANSLATE ANY OTHER C++ EXCEPTIONS TO JAVA EXCEPTIONS HERE
} catch(const std::exception& e) {
//translate unknown C++ exception to a Java exception
NewJavaException(env, "java/lang/Error", e.what());
} catch(...) {
//translate unknown C++ exception to a Java exception
NewJavaException(env, "java/lang/Error", "Unknown exception type");
}
}
With the above functions, it's easy to use Java/C++ hybrid exceptions in your C++ code, as shown below.
extern "C" JNIEXPORT
void JNICALL Java_MyClass_MyFunc(JNIEnv * env, jclass jc_, jstring param)
{
try { //do not let C++ exceptions outside of this function
//YOUR CODE BELOW THIS LINE. HERES SOME RANDOM CODE
if (param == NULL) //if something is wrong, throw a java exception
throw NewJavaException(env, "java/lang/NullPointerException", "param");
do_stuff(param); //might throw java or C++ exceptions
assert_no_exception(env); //throw a C++ exception if theres a java exception
do_more_stuff(param); //might throw C++ exceptions
//prefer Java exceptions where possible:
if (condition1) throw NewJavaException(env, "java/lang/NullPointerException", "condition1");
//but C++ exceptions should be fine too
if (condition0) throw std::bad_alloc("BAD_ALLOC");
//YOUR CODE ABOVE THIS LINE. HERES SOME RANDOM CODE
} catch(...) { //do not let C++ exceptions outside of this function
swallow_cpp_exception_and_throw_java(env);
}
}
If you're really ambitious, it's possible to keep track of a StackTraceElement[] of your bigger functions, and get a partial stacktrace. The basic method is to give each function a StackTraceElement, and as they're called, push a pointer to them onto a thread-local "callstack" and when they return, pop the pointer off. Then, alter the constructor of NewJavaException to make a copy of that stack, and pass it to setStackTrace.
Within the JNI literature, the word exception appears to be used exclusively to refer to Java exceptions. Unexpected events in native code are referred to as programming errors. JNI explicitly does not require JVMs to check for programming errors. If a programming error occurs, behavior is undefined. Different JVMs may behave differently.
It's the native code's responsibility to translate all programming errors into either return codes or Java exceptions. Java exceptions don't get thrown immediately from native code. They can be pending, only thrown once the native code returns to the Java caller. The native code can check for pending exceptions with ExceptionOccurred and clear them with ExceptionClear.
I would label that as undefined behavior. Propagation of exceptions back to C code (that's what is running the JVM) is undefined behavior.
On Windows, compilers have to use Microsoft's Structured Exception Handling to implement exceptions, so C++ exceptions will be "safely" caried through C code. However, that C code is not written with exceptions in mind, so you will get a crash if you're lucky, and inconsistent state and resource leaks if you aren't.
On other platforms, well, I don't know, but it can't be any prettier. When I write JNI code, I wrap every C++ function in a try block: even if I don't throw, I still might get some of the standard exceptions (std::bad_alloc comes to mind, but others are possible too).
JNI uses c functions to interface with native code. C cannot handle exceptions correctly since it is not aware of their existence. So you have to catch the exceptions in your Native code and convert them to java exceptions or your jvm will crash. (This works since the java exception is only thrown once the native code returns to java)
I am guessing your JVM will crash. Native C++ exceptions do not propagate into Java through JNI. One reason for that is that JNI is a C interface, and C knows nothing of C++ exceptions.
What you have to do is catch the C++ exceptions before you get into the C layer of your JNI code, and make the JNI C function return an error code. Then you can check for the error code inside Java and throw a Java exception if necessary.
As we know, many methods in JNI may cause exception and cannot be called after exception caused that may crash the JVM. We can not only use ExceptionOccurred() or ExceptionCheck() to determine whether exception occurred or not, but also can simply check something not equal to NULL or 0. Which way is the best practice?
As you are only asking for "best practice", the answer is very straightforward:
always call ExceptionCheck or ExceptionOccurred when calling JNI functions which may raise exceptions.
always check return values from JNI functions
Calling ExceptionOccurred after each JNI call, preferably in a dedicated function, allows you to get some information on the exception, for logging, and also allows you to call ExceptionClear.
Make the dedicated function return void, and use the return values from the JNI functions to distinguish between normal and error paths.
I'm learning to use java, I think I already know the basics of C++. But, as I just started learning java, the first bits of 'hello world' program I noticed uses 'throws exception' when initiating the main function in the main class. Why is it used? Do we do something similar in c++? Is returning 0 in int type main function in c++ a similar thing?
In Java, specifying that a methodthrows SomeException means that any method calling that method will have to either catch or itself throw that exception. In the case of the main function, it just means that you don't have to catch any exceptions that may occur directly in the main method, they will instead be passed on to the underlying runtime, resulting in a stack trace print and program exit.
It isn't, or at least, I've never seen a main in Java which
did it. I'm not even sure that it's legal. (Given the way Java
uses exceptions, it shouldn't be. Only RuntimeException and
Error should propagate out of main.)
Java tends to overuse exceptions; especially, it uses exceptions
in cases where return values would be more appropriate (e.g.
things like not being able to open a file). In a correct
program, these exceptions must be handled (just as in a correct
program, C++ returned error codes, or in the case of input and
output, the stream state, must be handled). Java uses the
exception specifier to declare these exceptions (and only
theseāit isn't necessary to declare things that would be
an exception in C++).
How is exception handling implemented in higher-level programming languages (like Java)? By this, I don't mean how to use exceptions within a language; I mean how the compiler generates code (assembly, or some intermediate, like Java byte code) that we recognize as exception-handling, because in the end, the computer can execute only instructions; Everything of a higher-level must be comprised of those instructions.
In C, before exceptions existed, you would return an error code, but if a function already returns something, then what? Perhaps return a structure of both the error code and the real result?
The compiler outputs an athrow instruction (JVM Specification) at the throw site, and an Exceptions attribute (#4.7.5) in the code of the method that shows where all the various catch clauses are, what range of instructions they cover, and what exception types they catch.
As the title suggests, how can I tell a JVM thrown exception from a Programmatically(does this mean, thrown by a programmer or the program) thrown exception ?
JVM Exceptions
1) ArrayIndexOutOfBoundsException
2) ClassCastException
3) NullPointerException
Programmatically thrown
1) NumberFormatException
2) AssertionError
Many Thanks
How to differentiate between Programmer and JVM Exceptions
You cannot do this statically because no such distinction exists.
Any exception defined in the standard Java class libraries may be thrown by application or third-party library code. This includes exceptions (including those that you listed) that are normally thrown by the JVM itself.
In some cases, it is a bad (or even terrible) idea to throw a standard exception. For example, it would be a really bad idea for an application to throw something like VerifyError because that has a very specific meaning that an application has no business throwing.
In other cases, there are no issues. For example, there is no problem1 with an application throwing NullPointerException explicitly; e.g.
public void setName(String name) {
if (name == null) {
throw new NullPointerException("name must not be null");
}
this.name = name;
}
The only possible way to distinguish between an exception that has been thrown by the JVM and by application code is to examine the stack frames from the thrown exception to figure out what class instantiated the exception. (Strictly speaking that doesn't tell you where the exception was thrown ... but it is close enough given that exceptions are nearly always instantiated and thrown in the same statement.)
But even this is not a useful distinction to make. There is no semantically useful difference between an exception thrown by application code, the standard class library or the JVM itself. The source of the exception certainly doesn't say anything about the root cause of the problem; e.g. whether it is due to an application bug, a library bug or something else.
The only useful distinctions are:
Error exceptions which you should not attempt to recover from, because they are usually not recoverable.
Other unchecked exceptions which may be recoverable, but are typically caused by bugs.
Checked exceptions which are often caused by "environmental" problems (such as incorrect file names) that may well need to be reported to the user.
There are a couple of alternative readings of the question:
If you wanted to distinguish the exceptions that could be thrown by the JVM from those that can only be thrown by Java code, you could do this by searching the OpenJDK source code for places where exceptions are thrown from native code.
If you wanted to distinguish the exceptions that could be thrown by the JVM OR by the standard Java libraries, broaden the search to include Java source code.
However, in both cases the "answer" is not useful (as above), and will depend on the particular Java release you examine.
1 - 1) There are no technical problems with throwing NPE, CCE, AIOOBE and so on. 2) I have never come across a style guide that says you shouldn't do it. 3) I have never seen a coherent explanation of why it should be "frowned on". (If you know of one, please provide a link to it.)
I'm not sure what you mean by JVM exceptions. These are all runtime exceptions that may be thrown by the programmer at any point (exception AssertionError), though it is considered poor style to throw certain exceptions like NullPointerException. The point is, there's no one quality separating the two categories you mention other than their typical usage. All the runtime exceptions extend, either directly or indirectly, RuntimeException.
From the JavaDocs for Throwable:
Only objects that are instances of
this class (or one of its subclasses)
are thrown by the Java Virtual Machine
or can be thrown by the Java throw
statement.
Because this same superclass defines all exceptions thrown by either the JVM or a programmer, you can't easily distinguish the two.
I don't think you will find a complete list, since there is no clear distinction between jvm and programmer initiated exceptions, apart from a few special cases:
most Error classes are thrown by the VM, due to internal or external causes. The one exception ThreadDeath, is thrown in a thread when that thread is stopped, and is kind of a "hack" to get the thread to unwind it's stack and exit.
most checked exceptions relate to environmental problems that lead to failure of some operation, but may be resolvable and are non-fatal to the JVM (IOException, SQLException, RemoteException) come to mind.
the remainder, unchecked exceptions, are a combination of both jvm and programmer initiated exception. For example, the JDK throws IllegalArgumentException when method parameters are not to spec. Is that a JVM exception or a programmatic exception? It unclear if your definition of JVM exceptions includes the JDK or not. ArrayIndexOutOfBounds is generated for illegal array accesses, generated by the JVM, but it's also thrown in some apis, e.g. Track.get from java.midi. (Although this can be argued as poor form, and the superclass IndexOutOfBounds should have been used instead.)
The most used exceptions thrown by JVM and by API are:
Exceptions thrown by JVM
ArrayIndexOutOfBoundsException
ClassCastException
NullPointerException
ArithmeticException
AssertionError
ExceptionInInitializerError
StackOverflowError
NoClassDefFoundError
Programmatically by API thrown
llegalArgumentException
NumberFormatException
IllegalStateException
SecurityException
Where exceptions come from
It's important that you understand what causes exceptions and errors and where they come from. Java defines two broad categories of exceptions and errors:
JVM exceptions: those exceptions or errors that are either exclusively or
most logically thrown by the JVM
Programmatic exceptions: those exceptions that are thrown explicitly by
application and/or API programmers
A very common exception, the NullPointerException occurs when you attempt to access an object using a reference variable with a current value of null. There's no way that the compiler can hope to find those problems before runtime. Take a look at the following:
class NPE {
static String s;
public static void main(String [] args) {
System.out.println(s.length());
}
}