diff -uNr japhar-0.09.orig/include/runtime.h japhar-0.09/include/runtime.h
--- japhar-0.09.orig/include/runtime.h	Sat Sep 16 00:49:58 2000
+++ japhar-0.09/include/runtime.h	Wed Dec  6 00:09:15 2000
@@ -425,7 +425,9 @@
 HVM_ExceptionCleanup(HungryEnv *henv, japhar_object* exception);
 
 PR_EXTERN( void )
-HVM_ExceptionPrintBacktrace(HungryEnv *henv, japhar_object* throwable_ref);
+HVM_ExceptionPrintStackTrace(HungryEnv *henv,
+                             japhar_object* throwable_ref,
+                             japhar_object* stream);
 
 PR_EXTERN( void )
 HVM_ExceptionFillInBacktraceFromStack(HungryEnv *henv,
diff -uNr japhar-0.09.orig/lib/libnative/java.lang/throwable.c japhar-0.09/lib/libnative/java.lang/throwable.c
--- japhar-0.09.orig/lib/libnative/java.lang/throwable.c	Sun Oct 31 19:43:00 1999
+++ japhar-0.09/lib/libnative/java.lang/throwable.c	Wed Dec  6 00:08:50 2000
@@ -35,7 +35,7 @@
 					  jobject printwriter_stream)
 {
   HungryEnv *henv = HVM_ThreadGetEnv();
-  HVM_ExceptionPrintBacktrace(henv, throwable);
+  HVM_ExceptionPrintStackTrace(henv, throwable, printwriter_stream);
 }
 
 JNIEXPORT jobject JNICALL
diff -uNr japhar-0.09.orig/lib/libruntime/exceptions.c japhar-0.09/lib/libruntime/exceptions.c
--- japhar-0.09.orig/lib/libruntime/exceptions.c	Thu Jan  6 20:33:47 2000
+++ japhar-0.09/lib/libruntime/exceptions.c	Wed Dec  6 09:16:37 2000
@@ -46,7 +46,7 @@
   int i = 0;
   PR_ASSERT(NULL != henv);
   PR_ASSERT(NULL != method);
-  
+
   if (method->line_numbers)
     {
       for (i = 0; i < method->num_line_number_blocks; i++)
@@ -61,10 +61,12 @@
 }
 
 PR_IMPLEMENT(void)
-HVM_ExceptionPrintBacktrace(HungryEnv *henv, japhar_object* throwable_ref)
+HVM_ExceptionPrintStackTrace(HungryEnv *henv,
+                             japhar_object* throwable_ref,
+                             japhar_object* stream_ref)
 {
-  ClazzFile *throwable_class;
-  MethodStruct *getMessage;
+  ClazzFile *throwable_class, *stream_class;
+  MethodStruct *getMessage, *println = NULL;
   japhar_object* msg = NULL;
   ClazzFile *exception_cf = throwable_ref->clazz;
   char *exceptionname = getClassName(env, exception_cf);
@@ -72,63 +74,83 @@
   ExceptionInfo *exc_info = HVM_ObjectGetNativeState(throwable_ref);
   BackTraceLevel *level;
   InterpValue msg_value;
+  char *msg_to_print;
+  japhar_object *msg_obj;
 
-  throwable_class = HVM_ClassFind(henv, java_lang_Throwable);
-
-  getMessage = HVM_MethodFind(henv, throwable_class,
-                              "getMessage",
-                              "()Ljava/lang/String;");
-
-  /*
-   * Cache exception and make sure the runtime don't think the call to
-   * getMessage failed
-   */
-  exception_cache = henv->_exception;
-  henv->_exception = NULL;
-
-  msg_value = HVM_MethodCallA(henv, getMessage, throwable_ref, NULL);
-  msg = msg_value.l;
-
-  /* Don't know what to do if the call fails.  Die a horrible death? */
-  PR_ASSERT(NULL == henv->_exception);
-  henv->_exception = exception_cache;
-
-  if (msg)
+  if (stream_ref != NULL)
     {
-      const char *msg_bytes = HVM_StringToCString(henv, msg);
+      ClazzFile *stream_clazz = HVM_ClassFind(henv, "java/io/PrintWriter");
+      PRBool pwriter = HVM_ObjectIsInstanceOf(henv, stream_ref, stream_clazz);
+      if (pwriter)
+        stream_class = HVM_ClassFind(henv, "java/io/PrintWriter");
+      else
+        stream_class = HVM_ClassFind(henv, "java/io/PrintStream");
 
-      fprintf (stderr, "%s (%s)\n", exceptionname, msg_bytes);
+      if (stream_class == NULL)
+        {
+          if (pwriter)
+            abort_with_message("ExceptionPrintStackTrace could not "
+                               "find java/io/PrintWriter");
+          else
+            abort_with_message("ExceptionPrintStackTrace could not "
+                               "find java/io/PrintStream");
+        }
+
+      println = HVM_MethodFind(henv, stream_class, "println",
+                               "(Ljava/lang/String;)V");
+      if (println == NULL)
+        abort_with_message("ExceptionPrintStacktrace could not "
+                           "find method println");
     }
-  else
-    fprintf (stderr, "%s\n", exceptionname);
 
   level = exc_info->head;
   while (level)
     {
       int line_number = method_pc_to_line_number(henv, level->method,
                                                  level->pc);
-      
+
+      PR_ASSERT(NULL != level->method);
       if (level->method->access_flags & ACC_NATIVE)
-        fprintf (stderr, "        in %s.%s(%s%snative method)\n",
-                 level->classname,
-                 level->method->name,
-                 level->filename ? level->filename : "",
-                 level->filename ? ", " : "");
+        {
+          msg_to_print = PR_smprintf("        in %s.%s(%s%snative method)",
+                                     level->classname,
+                                     level->method->name,
+                                     level->filename ? level->filename : "",
+                                     level->filename ? ", " : "");
+        }
       else if (line_number == -1)
-        fprintf (stderr, "        in %s.%s(%s%spc = %d)\n",
-                 level->classname,
-                 level->method->name,
-                 level->filename ? level->filename : "",
-                 level->filename ? ", " : "",
-                 level->pc);
+        {
+          msg_to_print = PR_smprintf("        in %s.%s(%s%spc = %d)",
+                                     level->classname,
+                                     level->method->name,
+                                     level->filename ? level->filename : "",
+                                     level->filename ? ", " : "",
+                                     level->pc);
+        }
       else
-        fprintf (stderr, "        at %s.%s(%s%s%d, pc = %d)\n",
-                 level->classname,
-                 level->method->name,
-                 level->filename ? level->filename : "",
-                 level->filename ? ":" : "line ",
-                 line_number,
-                 level->pc);
+        {
+          msg_to_print = PR_smprintf("        at %s.%s(%s%s%d, pc = %d)",
+                                     level->classname,
+                                     level->method->name,
+                                     level->filename ? level->filename : "",
+                                     level->filename ? ":" : "line ",
+                                     line_number,
+                                     level->pc);
+        }
+
+      msg_obj = HVM_StringFromCString(henv, msg_to_print);
+      if (msg_obj == NULL)
+        abort_with_message("ExceptionPrintStackTrace unable to "
+                           "allocate message");
+
+      if (println != NULL)
+        {
+          HVM_MethodCall(henv, println, stream_ref, msg_obj);
+        }
+      else
+        fprintf (stderr, "%s\n", msg_to_print);
+
+      PR_smprintf_free(msg_to_print);
 
       level = level->next;
     }
@@ -141,7 +163,7 @@
   /* XXX remove the gc root */
   henv->_exception = NULL;
 
-  HVM_ExceptionPrintBacktrace(henv, throwable_ref);
+  HVM_ExceptionPrintStackTrace(henv, throwable_ref, (japhar_object*)NULL);
 }
 
 PR_IMPLEMENT(void)
@@ -173,14 +195,14 @@
 {
   ExceptionInfo *exc_info = HVM_ObjectGetNativeState(throwable_ref);
   BackTraceLevel *new_level = (BackTraceLevel*)PR_MALLOC(sizeof(BackTraceLevel));
-  
+
   new_level->classname = PL_strdup(getClassName(henv, throw_frame->method->clazz));
   new_level->filename = throw_frame->method->clazz->source_filename;
   new_level->method = throw_frame->method;
   new_level->pc = throw_frame->pc;
   new_level->next = NULL;
   new_level->prev = NULL;
-  
+
   /* link the new level into the list of levels */
   if (exc_info->tail)
     {
@@ -284,7 +306,7 @@
 
   throw_frame = f;
 
-  PR_LOG(exceptionLm, PR_LOG_DEBUG, 
+  PR_LOG(exceptionLm, PR_LOG_DEBUG,
          ("Exception %s thrown from %s.%s - at pc %d\n",
           getClassName(ENV(throw_frame), throwable_cf),
           getClassName(ENV(throw_frame), throw_frame->method->clazz),
@@ -303,7 +325,7 @@
           /* if we hit a native frame, we just return.
              the interpreter loop will return to it's caller
              if the exception hasn't been handled here. */
-          
+
           return;
         }
       else
@@ -328,7 +350,7 @@
               catch_class = ExceptionBlock_getHandlerClazz(henv,
                                                            throw_frame->method->clazz,
                                                            exc_block);
-              
+
               if (!HVM_ObjectIsInstanceOf(henv, throwable_ref, catch_class))
                 continue;
 
@@ -337,7 +359,7 @@
                  the exception was thrown from. */
 
               throw_frame->pc = exc_block->handler_pc;
-              
+
               henv->op_stack->stack_top = throw_frame->opstack_top;
 
               op_stack_push_object(henv->op_stack, throwable_ref);
@@ -345,17 +367,17 @@
               /* XXX remove the gc root */
               henv->_exception = NULL;
 
-              PR_LOG(exceptionLm, PR_LOG_DEBUG, 
+              PR_LOG(exceptionLm, PR_LOG_DEBUG,
                      ("Exception %s caught by %s.%s - at pc %d\n",
                       getClassName(henv, catch_class),
                       getClassName(henv, throw_frame->method->clazz),
                       throw_frame->method->name,
                       throw_frame->pc));
-              
+
               return;
             }
 
-          /* if we didn't find a match, pop the stack 
+          /* if we didn't find a match, pop the stack
              frame and do it again. */
           new_throw_frame = throw_frame->parent;
           pop_frame(henv);
@@ -381,7 +403,7 @@
   char *msg = NULL;
 
   exception_cls = HVM_ClassFind(henv, exception_name);
-  
+
   if (!exception_cls)
     abort_with_message("Unable to raise exception.");
 
@@ -417,16 +439,13 @@
       constructor = HVM_MethodFind(henv, cf,
                                    "<init>", "(Ljava/lang/String;)V");
 
-      HVM_MethodCall(henv, constructor, 
-                     new_exception, string);
+      HVM_MethodCall(henv, constructor, new_exception, string);
     }
   else
     {
       constructor = HVM_MethodFind(henv, cf, "<init>", "()V");
 
-      HVM_MethodCallA(henv, constructor,
-                      new_exception, NULL);
-
+      HVM_MethodCallA(henv, constructor, new_exception, NULL);
     }
 
   return new_exception;
diff -uNr japhar-0.09.orig/lib/libruntime/init.c japhar-0.09/lib/libruntime/init.c
--- japhar-0.09.orig/lib/libruntime/init.c	Sat Sep 16 00:51:08 2000
+++ japhar-0.09/lib/libruntime/init.c	Wed Dec  6 09:25:34 2000
@@ -454,7 +454,7 @@
 
   if (new_env->_exception)
     {
-      HVM_ExceptionPrintBacktrace(new_env, new_env->_exception);
+      HVM_ExceptionPrintStackTrace(new_env, new_env->_exception, (japhar_object*)NULL);
       return PR_FALSE;
     }
 
