Tim Ellison wrote:
Still, it seems strange that you should have to call DetachCurrentThread
explicitly to get this behavior. I would have expected that
DestroyJavaVM alone would cause the uncaught exception handler to fire.
Not all apps that embed the VM will know to make this work-around.
Yes, that surprised me too. The bug suggests that the launcher is at
fault for calling
ExceptionDescribe() instead of DetachCurrentThread(). However I would have
thought that this was not necessary in the case where an exception
handler has
been registered, and that the handler would be called during
DestroyJavaVM()'s
execution.
Perhaps this is something that could be "fixed" in DRLVM? So if
DetachCurrentThread() is called, it runs any registered exception
handlers for that
thread as usual. However, if DestroyJavaVM is called, it makes sure that all
exception handlers are run for every thread.
Regards,
Oliver
Regards,
Tim
Oliver Deakin wrote:
Evgueni Brevnov wrote:
Oliver,
Yes, I got the same result on RI when starting VM by your simple
launcher. Assume it is OK not to print an error message and stacke
trace of an unhandled exception in JavaDestroyVM(). How about calling
uncaught exception handler? According to the spec it must be called if
terminating thread has an exception. The test shows that the handler
is not called when VM is created by our launcher. But if VM is
created by RI's launcher then everything works fine and the handler is
executed. This means that RI's launcher somehow deals with it (not VM
itself). It seems for me as a bug in RI. Do you think so?
Hi Evgueni,
I see the same thing - if I run your second Test class (the
UncaughtExceptionHandler
test) with my simple launcher on the RI and J9 I do not see any output.
i.e. the MyHandler.uncaughtException() method is never called.
Having a Google around I found a link to a Sun bug registered for this [1].
All our launcher needs to do is call DetachCurrentThread() on the main
thread before DestroyJavaVM(), and the UncaughtExceptionHandler will
be called as expected. (This bug only occurs with exception handlers
registered to the main thread - I verified this with [2] which has its
non-main
thread's exception handler called correctly)
So if you add the line:
(*jvm)->DetachCurrentThread(jvm);
to my simple launcher just before the DestroyJavaVM() call, you will see
that the MyHandler.uncaughtException() is called for the main thread, and
the test works as expected.
This looks like it needs to be added to our launcher - do you agree?
What is even more interesting is that if I run your more simple Test class
(the one that just does 'throw new Error("my");'), with the
DetachCurrentThread()
call added to the simple launcher I get a stack trace printed on both RI
and J9!
Again it appears that this is only a problem with the main thread (if
you alter
[2] before so that the handler is not registered, you get the expected
stack trace).
So it seems that adding DetachCurrentThread to the launcher fixes both
problems!
Regards,
Oliver
[1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4992454
[2]
public class Test {
static class MyHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("My Handler Called!!!");
}
}
static class MyRunnable implements Runnable {
public void run() {
Thread.currentThread().setUncaughtExceptionHandler(new
MyHandler());
throw new Error("my");
}
}
public static void main(String [] args) {
Thread t = new Thread(new MyRunnable());
t.start();
try {
t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted!");
}
}
}
Evgueni
On 9/21/06, Oliver Deakin <[EMAIL PROTECTED]> wrote:
Hi Evgueni,
I wrote a simple launcher [1] that does the following:
1) Calls CreateJavaVM
2) Runs the main method of your Test class below
3) Calls DestroyJavaVM
Note that it does *not* call env->ExceptionDescribe() before destroying
the VM.
I tested this launcher against the RI and J9 and found that no stack
trace or
error details are printed.
So I would say that it is standard behaviour for the VM not to output
any
information about uncaught exceptions when shutting down, and that the
launcher
is expected to call ExceptionDescribe() if it wants any details to be
printed.
So from what you have said below, IMHO we need to:
- Change DRLVM to not print stack trace if there is an uncaught
exception at
shutdown.
- If necessary, change the launcher to make sure ExceptionDescribe() is
called
before DestroyJavaVM().
Does that sound right?
Regards,
Oliver
[1]
#include <jni.h>
main() {
JNIEnv *env;
JavaVM *jvm;
jint result;
jclass cls;
jmethodID mid;
JavaVMInitArgs vmargs;
vmargs.version = 0x00010002;
vmargs.nOptions = 0;
vmargs.ignoreUnrecognized = JNI_TRUE;
result=JNI_CreateJavaVM(&jvm, (void**)&env, &vmargs);
if (result<0) {
fprintf(stderr, "Cannot create JavaVM\n");
exit(1);
}
cls = (*env)->FindClass(env, "TestClass");
if(cls == NULL)
{
printf("ERROR: FindClass failed.\n");
goto destroy;
}
mid = (*env)->GetStaticMethodID(env, cls, "main",
"([Ljava/lang/String;)V");
if(mid==NULL)
{
printf("ERROR: GetStaticMethodID call failed.\n");
goto destroy;
}
(*env)->CallStaticVoidMethod(env, cls, mid, NULL);
destroy:
(*jvm)->DestroyJavaVM(jvm);
}
Evgueni Brevnov wrote:
Hi All,
I'm almost done with the implementation of Invocation API for DRLVM.
While testing it I ran into a problem when an exception is printed
twice. I created a simple application which just throws an error and
it is not handled by any exception handler:
public class Test {
public static void main(String [] args) {
throw new Error("my");
}
}
In this case the launcher calls env->ExceptionDescribe() before
destroying VM. Then it calls DestroyJavaVM() which identifies
unhanded exception and calls an uncaught exception handler (see
java.lang.Thread.getUncaughtExceptionHandler()) for the current
thread. By default the handler prints the exception one more time.
That's definitely differs from RI where the exception is printed out
only once.
To identify where the problem is I created another simple test and
runs it on RI and DRLVM:
public class Test {
static class MyHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("My Handler Called!!!");
}
}
public static void main(String [] args) {
Thread.currentThread().setUncaughtExceptionHandler(new
MyHandler());
throw new Error("my");
}
}
Here is the output:
RI: java.exe Test
My Handler Called!!!
DRLVM: java.exe Test
java/lang/Error : my
at Test.main (Test.java: 12)
My Handler Called!!!
As you can see RI doesn't print exception stack trace at all. But
DRLVM does. To be precise the launcher does. So we need to fix the
launcher.....
Note: The behaviour of DRLVM you have may differ from listed above
since all experiments were done on my local workspace with Invocation
API implemented.
---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
--
Oliver Deakin
IBM United Kingdom Limited
---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
--
Oliver Deakin
IBM United Kingdom Limited
---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]