* src/vm/exceptions.c (exceptions_handle_exception) [__ARM__]: Added
[cacao.git] / src / vm / exceptions.c
index ef026cc7f5b60b3bbc02c29302772bcff5f318ee..bab903ce08366a49115c1e3bd5739a906f6578a9 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/exceptions.c - exception related functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes: Edwin Steiner
-
-   $Id: exceptions.c 5053 2006-06-28 19:11:20Z twisti $
-
 */
 
 
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
 
 #include "vm/types.h"
 
+#include "md-abi.h"
+
 #include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
 #include "native/native.h"
+
 #include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
-#include "toolbox/logging.h"
+
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
+
 #include "toolbox/util.h"
-#include "vm/class.h"
+
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/show.h"
+#include "vm/jit/stacktrace.h"
+#include "vm/jit/trace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
 
 
 /* for raising exceptions from native methods *********************************/
 
 #if !defined(ENABLE_THREADS)
-java_objectheader *_no_threads_exceptionptr = NULL;
+java_object_t *_no_threads_exceptionptr = NULL;
 #endif
 
 
-/* init_system_exceptions ******************************************************
+/* exceptions_init *************************************************************
 
-   Load and link exceptions used in the system.
+   Initialize the exceptions subsystem.
 
 *******************************************************************************/
 
-bool exceptions_init(void)
+void exceptions_init(void)
 {
-       /* java/lang/Throwable */
+#if !(defined(__ARM__) && defined(__LINUX__))
+       /* On arm-linux the first memory page can't be mmap'ed, as it
+          contains the exception vectors. */
 
-       if (!(class_java_lang_Throwable =
-                 load_class_bootstrap(utf_java_lang_Throwable)) ||
-               !link_class(class_java_lang_Throwable))
-               return false;
+       int pagesize;
 
+       /* mmap a memory page at address 0x0, so our hardware-exceptions
+          work. */
 
-       /* java/lang/VMThrowable */
+       pagesize = getpagesize();
 
-       if (!(class_java_lang_VMThrowable =
-                 load_class_bootstrap(utf_java_lang_VMThrowable)) ||
-               !link_class(class_java_lang_VMThrowable))
-               return false;
+       (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+#endif
 
+       /* check if we get into trouble with our hardware-exceptions */
 
-       /* java/lang/Error */
+       if (OFFSET(java_bytearray_t, data) <= EXCEPTION_HARDWARE_LARGEST)
+               vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray_t, data), EXCEPTION_HARDWARE_LARGEST);
+}
 
-       if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
-               !link_class(class_java_lang_Error))
-               return false;
 
-       /* java/lang/AbstractMethodError */
+/* exceptions_get_exception ****************************************************
 
-       if (!(class_java_lang_AbstractMethodError =
-                 load_class_bootstrap(utf_java_lang_AbstractMethodError)) ||
-               !link_class(class_java_lang_AbstractMethodError))
-               return false;
+   Returns the current exception pointer of the current thread.
+
+*******************************************************************************/
 
-       /* java/lang/LinkageError */
+java_handle_t *exceptions_get_exception(void)
+{
+       java_object_t *o;
+       java_handle_t *e;
+#if defined(ENABLE_THREADS)
+       threadobject  *t;
 
-       if (!(class_java_lang_LinkageError =
-                 load_class_bootstrap(utf_java_lang_LinkageError)) ||
-               !link_class(class_java_lang_LinkageError))
-               return false;
+       t = THREADOBJECT;
+#endif
 
-       /* java/lang/NoClassDefFoundError */
+       /* Get the exception. */
 
-       if (!(class_java_lang_NoClassDefFoundError =
-                 load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
-               !link_class(class_java_lang_NoClassDefFoundError))
-               return false;
+       LLNI_CRITICAL_START;
 
-       /* java/lang/NoSuchMethodError */
+#if defined(ENABLE_THREADS)
+       o = t->_exceptionptr;
+#else
+       o = _no_threads_exceptionptr;
+#endif
 
-       if (!(class_java_lang_NoSuchMethodError =
-                 load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
-               !link_class(class_java_lang_NoSuchMethodError))
-               return false;
+       e = LLNI_WRAP(o);
 
-       /* java/lang/OutOfMemoryError */
+       LLNI_CRITICAL_END;
 
-       if (!(class_java_lang_OutOfMemoryError =
-                 load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
-               !link_class(class_java_lang_OutOfMemoryError))
-               return false;
+       /* Return the exception. */
 
+       return e;
+}
 
-       /* java/lang/Exception */
 
-       if (!(class_java_lang_Exception =
-                 load_class_bootstrap(utf_java_lang_Exception)) ||
-               !link_class(class_java_lang_Exception))
-               return false;
+/* exceptions_set_exception ****************************************************
 
-       /* java/lang/ClassNotFoundException */
+   Sets the exception pointer of the current thread.
 
-       if (!(class_java_lang_ClassNotFoundException =
-                 load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
-               !link_class(class_java_lang_ClassNotFoundException))
-               return false;
+*******************************************************************************/
 
-       /* java/lang/IllegalArgumentException */
+void exceptions_set_exception(java_handle_t *e)
+{
+       threadobject  *t;
+       java_object_t *o;
 
-       if (!(class_java_lang_IllegalArgumentException =
-                 load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
-               !link_class(class_java_lang_IllegalArgumentException))
-               return false;
+#if defined(ENABLE_THREADS)
+       t = THREADOBJECT;
+#else
+       t = NULL;
+#endif
 
-       /* java/lang/IllegalMonitorStateException */
+       /* Set the exception. */
 
-       if (!(class_java_lang_IllegalMonitorStateException =
-                 load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
-               !link_class(class_java_lang_IllegalMonitorStateException))
-               return false;
+       LLNI_CRITICAL_START;
 
-       /* java/lang/NullPointerException */
+       o = LLNI_UNWRAP(e);
 
-       if (!(class_java_lang_NullPointerException =
-                 load_class_bootstrap(utf_java_lang_NullPointerException)) ||
-               !link_class(class_java_lang_NullPointerException))
-               return false;
+#if !defined(NDEBUG)
+       if (opt_DebugExceptions) {
+               printf("[exceptions_set_exception  : t=%p, o=%p, class=",
+                          (void *) t, (void *) o);
+               class_print(o->vftbl->class);
+               printf("]\n");
+       }
+#endif
 
+#if defined(ENABLE_THREADS)
+       t->_exceptionptr = o;
+#else
+       _no_threads_exceptionptr = o;
+#endif
 
-       return true;
+       LLNI_CRITICAL_END;
 }
 
 
-static void throw_exception_exit_intern(bool doexit)
-{
-       java_objectheader *xptr;
-       classinfo *c;
-       methodinfo *pss;
+/* exceptions_clear_exception **************************************************
 
-       xptr = *exceptionptr;
+   Clears the current exception pointer of the current thread.
 
-       if (xptr) {
-               /* clear exception, because we are calling jit code again */
-               *exceptionptr = NULL;
+*******************************************************************************/
+
+void exceptions_clear_exception(void)
+{
+       threadobject *t;
 
-               c = xptr->vftbl->class;
+#if defined(ENABLE_THREADS)
+       t = THREADOBJECT;
+#else
+       t = NULL;
+#endif
+
+       /* Set the exception. */
 
-               pss = class_resolveclassmethod(c,
-                                                                          utf_printStackTrace,
-                                                                          utf_void__void,
-                                                                          class_java_lang_Object,
-                                                                          false);
+#if !defined(NDEBUG)
+       if (opt_DebugExceptions) {
+               printf("[exceptions_clear_exception: t=%p]\n", (void *) t);
+       }
+#endif
 
-               /* print the stacktrace */
+#if defined(ENABLE_THREADS)
+       t->_exceptionptr = NULL;
+#else
+       _no_threads_exceptionptr = NULL;
+#endif
+}
 
-               if (pss) {
-                       (void) vm_call_method(pss, xptr);
 
-                       /* This normally means, we are EXTREMLY out of memory or have a   */
-                       /* serious problem while printStackTrace. But may be another      */
-                       /* exception, so print it.                                        */
+/* exceptions_get_and_clear_exception ******************************************
 
-                       if (*exceptionptr) {
-                               java_lang_Throwable *t;
+   Gets the exception pointer of the current thread and clears it.
+   This function may return NULL.
 
-                               t = (java_lang_Throwable *) *exceptionptr;
+*******************************************************************************/
 
-                               fprintf(stderr, "Exception while printStackTrace(): ");
-                               utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
+java_handle_t *exceptions_get_and_clear_exception(void)
+{
+       java_handle_t *o;
 
-                               if (t->detailMessage) {
-                                       char *buf;
+       /* Get the exception... */
 
-                                       buf = javastring_tochar((java_objectheader *) t->detailMessage);
-                                       fprintf(stderr, ": %s", buf);
-                                       MFREE(buf, char, strlen(buf));
-                               }
-                                       
-                               fprintf(stderr, "\n");
-                       }
+       o = exceptions_get_exception();
 
-               } else {
-                       utf_fprint_printable_ascii_classname(stderr, c->name);
-                       fprintf(stderr, ": printStackTrace()V not found!\n");
-               }
+       /* ...and clear the exception if it is set. */
 
-               fflush(stderr);
+       if (o != NULL)
+               exceptions_clear_exception();
 
-               /* good bye! */
+       /* return the exception */
 
-               if (doexit)
-                       exit(1);
-       }
+       return o;
 }
 
 
-void throw_exception(void)
-{
-       throw_exception_exit_intern(false);
-}
+/* exceptions_abort ************************************************************
 
+   Prints exception to be thrown and aborts.
 
-void throw_exception_exit(void)
-{
-       throw_exception_exit_intern(true);
-}
+   IN:
+      classname....class name
+      message......exception message
 
+*******************************************************************************/
 
-void throw_main_exception(void)
+static void exceptions_abort(utf *classname, utf *message)
 {
-       fprintf(stderr, "Exception in thread \"main\" ");
-       fflush(stderr);
+       log_println("exception thrown while VM is initializing: ");
 
-       throw_exception_exit_intern(false);
-}
+       log_start();
+       utf_display_printable_ascii_classname(classname);
 
+       if (message != NULL) {
+               log_print(": ");
+               utf_display_printable_ascii_classname(message);
+       }
 
-void throw_main_exception_exit(void)
-{
-       fprintf(stderr, "Exception in thread \"main\" ");
-       fflush(stderr);
+       log_finish();
 
-       throw_exception_exit_intern(true);
+       vm_abort("Aborting...");
 }
 
 
-void throw_cacao_exception_exit(const char *exception, const char *message, ...)
-{
-       s4 i;
-       char *tmp;
-       s4 len;
-       va_list ap;
+/* exceptions_new_utf **********************************************************
 
-       len = strlen(exception);
-       tmp = MNEW(char, len + 1);
-       strncpy(tmp, exception, len);
-       tmp[len] = '\0';
+   Creates an exception object with the given name and initalizes it.
 
-       /* convert to classname */
+   IN:
+      classname....class name in UTF-8
 
-       for (i = len - 1; i >= 0; i--)
-               if (tmp[i] == '/') tmp[i] = '.';
+*******************************************************************************/
 
-       fprintf(stderr, "Exception in thread \"main\" %s", tmp);
+static java_handle_t *exceptions_new_utf(utf *classname)
+{
+       classinfo     *c;
+       java_handle_t *o;
 
-       MFREE(tmp, char, len);
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
 
-       if (strlen(message) > 0) {
-               fprintf(stderr, ": ");
+       c = load_class_bootstrap(classname);
 
-               va_start(ap, message);
-               vfprintf(stderr, message, ap);
-               va_end(ap);
-       }
+       if (c == NULL)
+               return exceptions_get_exception();
 
-       fprintf(stderr, "\n");
-       fflush(stderr);
+       o = native_new_and_init(c);
 
-       /* good bye! */
+       if (o == NULL)
+               return exceptions_get_exception();
 
-       exit(1);
+       return o;
 }
 
 
-/* exceptions_throw_outofmemory_exit *******************************************
+/* exceptions_throw_utf ********************************************************
+
+   Creates an exception object with the given name, initalizes and
+   throws it.
 
-   Just print an: java.lang.InternalError: Out of memory
+   IN:
+      classname....class name in UTF-8
 
 *******************************************************************************/
 
-void exceptions_throw_outofmemory_exit(void)
+static void exceptions_throw_utf(utf *classname)
 {
-       throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                          "Out of memory");
+       java_handle_t *o;
+
+       o = exceptions_new_utf(classname);
+
+       if (o == NULL)
+               return;
+
+       exceptions_set_exception(o);
 }
 
 
-/* new_exception ***************************************************************
+/* exceptions_throw_utf_throwable **********************************************
 
-   Creates an exception object with the given name and initalizes it.
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/Throwable exception.
 
    IN:
       classname....class name in UTF-8
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+         cause........the given Throwable
 
 *******************************************************************************/
 
-java_objectheader *new_exception(const char *classname)
+static void exceptions_throw_utf_throwable(utf *classname,
+                                                                                  java_handle_t *cause)
 {
-       java_objectheader *o;
-       classinfo         *c;
+       classinfo           *c;
+       java_handle_t       *o;
+       methodinfo          *m;
+       java_lang_Throwable *object;
 
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
 
-       o = native_new_and_init(c);
+       object = (java_lang_Throwable *) cause;
 
-       if (!o)
-               return *exceptionptr;
+       c = load_class_bootstrap(classname);
 
-       return o;
+       if (c == NULL)
+               return;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return;
+
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_Throwable__void,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, cause);
+
+       exceptions_set_exception(o);
 }
 
 
-/* new_exception_message *******************************************************
+/* exceptions_throw_utf_exception **********************************************
 
    Creates an exception object with the given name and initalizes it
-   with the given char message.
+   with the given java/lang/Exception exception.
 
    IN:
       classname....class name in UTF-8
-         message......message in UTF-8
+         exception....the given Exception
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+*******************************************************************************/
+
+static void exceptions_throw_utf_exception(utf *classname,
+                                                                                  java_handle_t *exception)
+{
+       classinfo     *c;
+       java_handle_t *o;
+       methodinfo    *m;
+
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return;
+
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_Exception__V,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, exception);
+
+       exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf_cause **************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/Throwable exception with initCause.
+
+   IN:
+      classname....class name in UTF-8
+         cause........the given Throwable
 
 *******************************************************************************/
 
-java_objectheader *new_exception_message(const char *classname,
-                                                                                const char *message)
+static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
 {
-       java_lang_String *s;
+       classinfo           *c;
+       java_handle_t       *o;
+       methodinfo          *m;
+       java_lang_String    *s;
+       java_lang_Throwable *object;
+
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
+
+       object = (java_lang_Throwable *) cause;
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return;
+
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_String__void,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       LLNI_field_get_ref(object, detailMessage, s);
+
+       (void) vm_call_method(m, o, s);
+
+       /* call initCause */
 
-       s = javastring_new_from_utf_string(message);
-       if (!s)
-               return *exceptionptr;
+       m = class_resolveclassmethod(c,
+                                                                utf_initCause,
+                                                                utf_java_lang_Throwable__java_lang_Throwable,
+                                                                NULL,
+                                                                true);
+
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, cause);
 
-       return new_exception_javastring(classname, s);
+       exceptions_set_exception(o);
 }
 
 
-/* new_exception_throwable *****************************************************
+/* exceptions_new_utf_javastring ***********************************************
 
    Creates an exception object with the given name and initalizes it
-   with the given java/lang/Throwable exception.
+   with the given java/lang/String message.
 
    IN:
       classname....class name in UTF-8
-         throwable....the given Throwable
+         message......the message as a java.lang.String
 
    RETURN VALUE:
       an exception pointer (in any case -- either it is the newly created
@@ -390,25 +516,30 @@ java_objectheader *new_exception_message(const char *classname,
 
 *******************************************************************************/
 
-java_objectheader *new_exception_throwable(const char *classname,
-                                                                                  java_lang_Throwable *throwable)
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+                                                                                                       java_handle_t *message)
 {
-       java_objectheader *o;
-       classinfo         *c;
+       java_handle_t *o;
+       classinfo     *c;
    
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
+
+       c = load_class_bootstrap(classname);
 
-       o = native_new_and_init_throwable(c, throwable);
+       if (c == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, message);
 
-       if (!o)
-               return *exceptionptr;
+       if (o == NULL)
+               return exceptions_get_exception();
 
        return o;
 }
 
 
-/* new_exception_utfmessage ****************************************************
+/* exceptions_new_utf_utf ******************************************************
 
    Creates an exception object with the given name and initalizes it
    with the given utf message.
@@ -423,147 +554,200 @@ java_objectheader *new_exception_throwable(const char *classname,
 
 *******************************************************************************/
 
-java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
 {
-       java_lang_String *s;
+       classinfo     *c;
+       java_handle_t *s;
+       java_handle_t *o;
+
+       if (vm_initializing)
+               exceptions_abort(classname, message);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return exceptions_get_exception();
 
        s = javastring_new(message);
-       if (!s)
-               return *exceptionptr;
 
-       return new_exception_javastring(classname, s);
+       if (s == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, s);
+
+       if (o == NULL)
+               return exceptions_get_exception();
+
+       return o;
 }
 
 
-/* new_exception_javastring ****************************************************
+/* exceptions_throw_utf_utf ****************************************************
 
-   Creates an exception object with the given name and initalizes it
-   with the given java/lang/String message.
+   Creates an exception object with the given name, initalizes and
+   throws it with the given utf message.
 
    IN:
       classname....class name in UTF-8
-         message......the message as a java.lang.String
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+         message......the message as an utf *
 
 *******************************************************************************/
 
-java_objectheader *new_exception_javastring(const char *classname,
-                                                                                       java_lang_String *message)
+static void exceptions_throw_utf_utf(utf *classname, utf *message)
 {
-       java_objectheader *o;
-       classinfo         *c;
-   
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
+       java_handle_t *o;
+
+       o = exceptions_new_utf_utf(classname, message);
+
+       exceptions_set_exception(o);
+}
 
-       o = native_new_and_init_string(c, message);
 
-       if (!o)
-               return *exceptionptr;
+/* exceptions_new_abstractmethoderror ****************************************
+
+   Generates a java.lang.AbstractMethodError for the VM.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_abstractmethoderror(void)
+{
+       java_handle_t *o;
+
+       o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
 
        return o;
 }
 
 
-/* new_exception_int ***********************************************************
+/* exceptions_new_error ********************************************************
 
-   Creates an exception object with the given name and initalizes it
-   with the given int value.
+   Generates a java.lang.Error for the VM.
 
-   IN:
-      classname....class name in UTF-8
-         i............the integer
+*******************************************************************************/
+
+#if defined(ENABLE_JAVAME_CLDC1_1)
+static java_handle_t *exceptions_new_error(utf *message)
+{
+       java_handle_t *o;
+
+       o = exceptions_new_utf_utf(utf_java_lang_Error, message);
+
+       return o;
+}
+#endif
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+
+/* exceptions_asm_new_abstractmethoderror **************************************
+
+   Generates a java.lang.AbstractMethodError for
+   asm_abstractmethoderror.
 
 *******************************************************************************/
 
-java_objectheader *new_exception_int(const char *classname, s4 i)
+java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
 {
-       java_objectheader *o;
-       classinfo         *c;
-   
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
+       stackframeinfo_t  sfi;
+       java_handle_t    *e;
+       java_object_t    *o;
+
+       /* Fill and add a stackframeinfo (XPC is equal to RA). */
+
+       stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
+
+       /* create the exception */
+
+#if defined(ENABLE_JAVASE)
+       e = exceptions_new_abstractmethoderror();
+#else
+       e = exceptions_new_error(utf_java_lang_AbstractMethodError);
+#endif
+
+       /* Remove the stackframeinfo. */
+
+       stacktrace_stackframeinfo_remove(&sfi);
 
-       o = native_new_and_init_int(c, i);
+       /* unwrap the exception */
+       /* ATTENTION: do the this _after_ the stackframeinfo was removed */
 
-       if (!o)
-               return *exceptionptr;
+       o = LLNI_UNWRAP(e);
 
        return o;
 }
 
 
-/* exceptions_new_abstractmethoderror ******************************************
+/* exceptions_new_arraystoreexception ******************************************
 
-   Generates a java.lang.AbstractMethodError for the VM.
+   Generates a java.lang.ArrayStoreException for the VM.
 
 *******************************************************************************/
 
-java_objectheader *exceptions_new_abstractmethoderror(void)
+java_handle_t *exceptions_new_arraystoreexception(void)
 {
-       java_objectheader *e;
-
-       e = native_new_and_init(class_java_lang_AbstractMethodError);
+       java_handle_t *o;
 
-       if (e == NULL)
-               return *exceptionptr;
+       o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
 
-       return e;
+       return o;
 }
 
 
 /* exceptions_throw_abstractmethoderror ****************************************
 
-   Generates a java.lang.AbstractMethodError for the VM and throws it.
+   Generates and throws a java.lang.AbstractMethodError for the VM.
 
 *******************************************************************************/
 
 void exceptions_throw_abstractmethoderror(void)
 {
-       *exceptionptr = exceptions_new_abstractmethoderror();
+       exceptions_throw_utf(utf_java_lang_AbstractMethodError);
 }
 
 
-/* new_classformaterror ********************************************************
+/* exceptions_throw_classcircularityerror **************************************
 
-   generates a java.lang.ClassFormatError for the classloader
+   Generates and throws a java.lang.ClassCircularityError for the
+   classloader.
+
+   IN:
+      c....the class in which the error was found
+
+*******************************************************************************/
+
+void exceptions_throw_classcircularityerror(classinfo *c)
+{
+       exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
+}
+
+
+/* exceptions_throw_classformaterror *******************************************
+
+   Generates and throws a java.lang.ClassFormatError for the VM.
 
    IN:
       c............the class in which the error was found
          message......UTF-8 format string
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
 *******************************************************************************/
 
-java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
+void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
-       va_list            ap;
+       char    *msg;
+       s4       msglen;
+       va_list  ap;
+       utf     *u;
 
        /* calculate message length */
 
        msglen = 0;
 
-       if (c)
+       if (c != NULL)
                msglen += utf_bytes(c->name) + strlen(" (");
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
        va_end(ap);
 
-       if (c)
+       if (c != NULL)
                msglen += strlen(")");
 
        msglen += strlen("0");
@@ -574,7 +758,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 
        /* print message into allocated buffer */
 
-       if (c) {
+       if (c != NULL) {
                utf_copy_classname(msg, c->name);
                strcat(msg, " (");
        }
@@ -583,267 +767,314 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
        vsprintf(msg + strlen(msg), message, ap);
        va_end(ap);
 
-       if (c)
+       if (c != NULL)
                strcat(msg, ")");
 
-       o = new_exception_message(string_java_lang_ClassFormatError, msg);
+       u = utf_new_char(msg);
+
+       /* free memory */
 
        MFREE(msg, char, msglen);
 
-       return o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
 }
 
 
-/* exceptions_throw_classformaterror *******************************************
+/* exceptions_throw_classnotfoundexception *************************************
 
-   Generate a java.lang.ClassFormatError for the VM system and throw it.
+   Generates and throws a java.lang.ClassNotFoundException for the
+   VM.
 
    IN:
-      c............the class in which the error was found
-         message......UTF-8 format string
+      name.........name of the class not found as a utf *
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+*******************************************************************************/
+
+void exceptions_throw_classnotfoundexception(utf *name)
+{      
+       exceptions_throw_utf_utf(utf_java_lang_ClassNotFoundException, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror ***************************************
+
+   Generates and throws a java.lang.NoClassDefFoundError.
+
+   IN:
+      name.........name of the class not found as a utf *
 
 *******************************************************************************/
 
-void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
+void exceptions_throw_noclassdeffounderror(utf *name)
 {
-       va_list ap;
+       exceptions_throw_utf_utf(utf_java_lang_NoClassDefFoundError, name);
+}
 
-       va_start(ap, message);
-       *exceptionptr = new_classformaterror(c, message, ap);
-       va_end(ap);
+
+/* exceptions_throw_noclassdeffounderror_cause *********************************
+
+   Generates and throws a java.lang.NoClassDefFoundError with the
+   given cause.
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
+{
+       exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
 }
 
 
-/* new_classnotfoundexception **************************************************
+/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
 
-   Generates a java.lang.ClassNotFoundException for the classloader.
+   Generates and throws a java.lang.NoClassDefFoundError with a
+   specific message:
 
    IN:
       name.........name of the class not found as a utf *
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
 *******************************************************************************/
 
-java_objectheader *new_classnotfoundexception(utf *name)
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
 {
-       java_objectheader *o;
-       java_lang_String  *s;
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
-       s = javastring_new(name);
-       if (!s)
-               return *exceptionptr;
+       msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+               utf_bytes(name) + strlen(")") + strlen("0");
 
-       o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
+       msg = MNEW(char, msglen);
 
-       if (!o)
-               return *exceptionptr;
+       utf_copy_classname(msg, c->name);
+       strcat(msg, " (wrong name: ");
+       utf_cat_classname(msg, name);
+       strcat(msg, ")");
 
-       return o;
+       u = utf_new_char(msg);
+
+       MFREE(msg, char, msglen);
+
+       exceptions_throw_noclassdeffounderror(u);
 }
 
 
-/* new_noclassdeffounderror ****************************************************
+/* exceptions_throw_exceptionininitializererror ********************************
 
-   Generates a java.lang.NoClassDefFoundError
+   Generates and throws a java.lang.ExceptionInInitializerError for
+   the VM.
 
    IN:
-      name.........name of the class not found as a utf *
+      cause......cause exception object
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+*******************************************************************************/
+
+void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
+{
+       exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
+                                                                  cause);
+}
+
+
+/* exceptions_throw_incompatibleclasschangeerror *******************************
+
+   Generates and throws a java.lang.IncompatibleClassChangeError for
+   the VM.
+
+   IN:
+      message......UTF-8 message format string
 
 *******************************************************************************/
 
-java_objectheader *new_noclassdeffounderror(utf *name)
+void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
 {
-       java_objectheader *o;
-       java_lang_String  *s;
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
-       s = javastring_new(name);
-       if (!s)
-               return *exceptionptr;
+       /* calculate exception message length */
 
-       o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
+       msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
 
-       if (!o)
-               return *exceptionptr;
+       /* allocate memory */
 
-       return o;
+       msg = MNEW(char, msglen);
+
+       utf_copy_classname(msg, c->name);
+       strcat(msg, message);
+
+       u = utf_new_char(msg);
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
 }
 
 
-/* classnotfoundexception_to_noclassdeffounderror ******************************
+/* exceptions_throw_instantiationerror *****************************************
 
-   Check the *exceptionptr for a ClassNotFoundException. If it is one,
-   convert it to a NoClassDefFoundError.
+   Generates and throws a java.lang.InstantiationError for the VM.
 
 *******************************************************************************/
 
-void classnotfoundexception_to_noclassdeffounderror(void)
+void exceptions_throw_instantiationerror(classinfo *c)
 {
-       java_objectheader *xptr;
-       java_objectheader *cause;
+       exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
+}
 
-       /* get the cause */
 
-       cause = *exceptionptr;
+/* exceptions_throw_internalerror **********************************************
 
-       /* convert ClassNotFoundException's to NoClassDefFoundError's */
+   Generates and throws a java.lang.InternalError for the VM.
 
-       if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
-               /* clear exception, because we are calling jit code again */
+   IN:
+      message......UTF-8 message format string
 
-               *exceptionptr = NULL;
+*******************************************************************************/
 
-               /* create new error */
+void exceptions_throw_internalerror(const char *message, ...)
+{
+       va_list  ap;
+       char    *msg;
+       s4       msglen;
+       utf     *u;
 
-               xptr =
-                       new_exception_javastring(string_java_lang_NoClassDefFoundError,
-                                       ((java_lang_Throwable *) cause)->detailMessage);
+       /* calculate exception message length */
 
-               /* we had an exception while creating the error */
+       va_start(ap, message);
+       msglen = get_variable_message_length(message, ap);
+       va_end(ap);
 
-               if (*exceptionptr)
-                       return;
+       /* allocate memory */
 
-               /* set new exception */
+       msg = MNEW(char, msglen);
 
-               *exceptionptr = xptr;
-       }
+       /* generate message */
+
+       va_start(ap, message);
+       vsprintf(msg, message, ap);
+       va_end(ap);
+
+       u = utf_new_char(msg);
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
 }
 
 
-/* new_internalerror ***********************************************************
+/* exceptions_throw_linkageerror ***********************************************
 
-   Generates a java.lang.InternalError for the VM.
+   Generates and throws java.lang.LinkageError with an error message.
 
    IN:
-      message......UTF-8 message format string
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+      message......UTF-8 message
+         c............class related to the error. If this is != NULL
+                      the name of c is appended to the error message.
 
 *******************************************************************************/
 
-java_objectheader *new_internalerror(const char *message, ...)
+void exceptions_throw_linkageerror(const char *message, classinfo *c)
 {
-       java_objectheader *o;
-       va_list            ap;
-       char              *msg;
-       s4                 msglen;
+       utf  *u;
+       char *msg;
+       int   len;
 
        /* calculate exception message length */
 
-       va_start(ap, message);
-       msglen = get_variable_message_length(message, ap);
-       va_end(ap);
+       len = strlen(message) + 1;
 
+       if (c != NULL)
+               len += utf_bytes(c->name);
+               
        /* allocate memory */
 
-       msg = MNEW(char, msglen);
+       msg = MNEW(char, len);
 
        /* generate message */
 
-       va_start(ap, message);
-       vsprintf(msg, message, ap);
-       va_end(ap);
+       strcpy(msg, message);
 
-       /* create exception object */
+       if (c != NULL)
+               utf_cat_classname(msg, c->name);
 
-       o = new_exception_message(string_java_lang_InternalError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
-       MFREE(msg, char, msglen);
+       MFREE(msg, char, len);
 
-       return o;
+       exceptions_throw_utf_utf(utf_java_lang_LinkageError, u);
 }
 
 
-/* exceptions_new_linkageerror *************************************************
+/* exceptions_throw_nosuchfielderror *******************************************
 
-   Generates a java.lang.LinkageError with an error message.
+   Generates and throws a java.lang.NoSuchFieldError with an error
+   message.
 
    IN:
-      message......UTF-8 message
-         c............class related to the error. If this is != NULL
-                      the name of c is appended to the error message.
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+      c............class in which the field was not found
+         name.........name of the field
 
 *******************************************************************************/
 
-java_objectheader *exceptions_new_linkageerror(const char *message,
-                                                                                          classinfo *c)
+void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
        /* calculate exception message length */
 
-       msglen = strlen(message) + 1;
-       if (c) {
-               msglen += utf_bytes(c->name);
-       }
-               
+       msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
+
        /* allocate memory */
 
        msg = MNEW(char, msglen);
 
        /* generate message */
 
-       strcpy(msg,message);
-       if (c) {
-               utf_cat_classname(msg, c->name);
-       }
+       utf_copy_classname(msg, c->name);
+       strcat(msg, ".");
+       utf_cat(msg, name);
 
-       o = native_new_and_init_string(class_java_lang_LinkageError,
-                                                                  javastring_new_from_utf_string(msg));
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       if (!o)
-               return *exceptionptr;
-
-       return o;
+       exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
 }
 
 
-/* exceptions_new_nosuchmethoderror ********************************************
+/* exceptions_throw_nosuchmethoderror ******************************************
 
-   Generates a java.lang.NoSuchMethodError with an error message.
+   Generates and throws a java.lang.NoSuchMethodError with an error
+   message.
 
    IN:
       c............class in which the method was not found
          name.........name of the method
          desc.........descriptor of the method
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
 *******************************************************************************/
 
-java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
-                                                                                                       utf *name, utf *desc)
+void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
        /* calculate exception message length */
 
@@ -861,65 +1092,75 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
        utf_cat(msg, name);
        utf_cat(msg, desc);
 
-       o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
-                                                                  javastring_new_from_utf_string(msg));
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       if (!o)
-               return *exceptionptr;
+#if defined(ENABLE_JAVASE)
+       exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
+#else
+       exceptions_throw_utf_utf(utf_java_lang_Error, u);
+#endif
+}
+
 
-       return o;
+/* exceptions_throw_outofmemoryerror *******************************************
+
+   Generates and throws an java.lang.OutOfMemoryError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_outofmemoryerror(void)
+{
+       exceptions_throw_utf(utf_java_lang_OutOfMemoryError);
 }
 
 
-/* exceptions_throw_nosuchmethoderror ******************************************
+/* exceptions_throw_unsatisfiedlinkerror ***************************************
 
-   Generates a java.lang.NoSuchMethodError with an error message.
+   Generates and throws a java.lang.UnsatisfiedLinkError for the
+   classloader.
 
    IN:
-      c............class in which the method was not found
-         name.........name of the method
-         desc.........descriptor of the method
+         name......UTF-8 name string
 
 *******************************************************************************/
 
-void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
+void exceptions_throw_unsatisfiedlinkerror(utf *name)
 {
-       *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
+#if defined(ENABLE_JAVASE)
+       exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
+#else
+       exceptions_throw_utf_utf(utf_java_lang_Error, name);
+#endif
 }
 
 
-/* new_unsupportedclassversionerror ********************************************
+/* exceptions_throw_unsupportedclassversionerror *******************************
 
-   Generate a java.lang.UnsupportedClassVersionError for the classloader
+   Generates and throws a java.lang.UnsupportedClassVersionError for
+   the classloader.
 
    IN:
       c............class in which the method was not found
          message......UTF-8 format string
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
 *******************************************************************************/
 
-java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
+void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
 {
-       java_objectheader *o;
-       va_list            ap;
-       char              *msg;
-    s4                 msglen;
+       char *msg;
+    s4    msglen;
+       utf  *u;
 
        /* calculate exception message length */
 
-       msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
-
-       va_start(ap, message);
-       msglen += get_variable_message_length(message, ap);
-       va_end(ap);
+       msglen =
+               utf_bytes(c->name) +
+               strlen(" (Unsupported major.minor version 00.0)") +
+               strlen("0");
 
        /* allocate memory */
 
@@ -928,56 +1169,45 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
        /* generate message */
 
        utf_copy_classname(msg, c->name);
-       strcat(msg, " (");
-
-       va_start(ap, message);
-       vsprintf(msg + strlen(msg), message, ap);
-       va_end(ap);
-
-       strcat(msg, ")");
-
-       /* create exception object */
+       sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
+                       ma, mi);
 
-       o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
-                                                         msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       return o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
 }
 
 
-/* new_verifyerror *************************************************************
+/* exceptions_throw_verifyerror ************************************************
 
-   Generates a java.lang.VerifyError for the JIT compiler.
+   Generates and throws a java.lang.VerifyError for the JIT compiler.
 
    IN:
       m............method in which the error was found
          message......UTF-8 format string
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
 *******************************************************************************/
 
-java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
 {
-       java_objectheader *o;
-       va_list            ap;
-       char              *msg;
-       s4                 msglen;
-
-       useinlining = false; /* at least until sure inlining works with exceptions*/
+       va_list  ap;
+       char    *msg;
+       s4       msglen;
+       utf     *u;
 
        /* calculate exception message length */
 
        msglen = 0;
 
-       if (m)
-               msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+       if (m != NULL)
+               msglen =
+                       strlen("(class: ") + utf_bytes(m->class->name) +
                        strlen(", method: ") + utf_bytes(m->name) +
                        strlen(" signature: ") + utf_bytes(m->descriptor) +
                        strlen(") ") + strlen("0");
@@ -992,7 +1222,7 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
        /* generate message */
 
-       if (m) {
+       if (m != NULL) {
                strcpy(msg, "(class: ");
                utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
@@ -1006,15 +1236,15 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
        vsprintf(msg + strlen(msg), message, ap);
        va_end(ap);
 
-       /* create exception object */
-
-       o = new_exception_message(string_java_lang_VerifyError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       return o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
 }
 
 
@@ -1032,18 +1262,18 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
 *******************************************************************************/
 
-void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
+void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
-       char              *typename;
+       char *msg;
+       s4    msglen;
+       char *typename;
+       utf  *u;
 
        /* calculate exception message length */
 
        msglen = 0;
 
-       if (m)
+       if (m != NULL)
                msglen = strlen("(class: ") + utf_bytes(m->class->name) +
                        strlen(", method: ") + utf_bytes(m->name) +
                        strlen(" signature: ") + utf_bytes(m->descriptor) +
@@ -1056,7 +1286,7 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
 
        /* generate message */
 
-       if (m) {
+       if (m != NULL) {
                strcpy(msg, "(class: ");
                utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
@@ -1069,47 +1299,47 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
                msg[0] = 0;
        }
 
-       strcat(msg,"Expecting to find ");
+       strcat(msg, "Expecting to find ");
+
        switch (type) {
                case TYPE_INT: typename = "integer"; break;
                case TYPE_LNG: typename = "long"; break;
                case TYPE_FLT: typename = "float"; break;
                case TYPE_DBL: typename = "double"; break;
                case TYPE_ADR: typename = "object/array"; break;
+               case TYPE_RET: typename = "returnAddress"; break;
                default:       typename = "<INVALID>"; assert(0); break;
        }
+
        strcat(msg, typename);
        strcat(msg, " on stack");
 
-       /* create exception object */
-
-       o = new_exception_message(string_java_lang_VerifyError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       *exceptionptr = o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
 }
 
 
-/* new_arithmeticexception *****************************************************
+/* exceptions_new_arithmeticexception ******************************************
 
-   Generates a java.lang.ArithmeticException for the jit compiler.
+   Generates a java.lang.ArithmeticException for the JIT compiler.
 
 *******************************************************************************/
 
-java_objectheader *new_arithmeticexception(void)
+java_handle_t *exceptions_new_arithmeticexception(void)
 {
-       java_objectheader *e;
-
-       e = new_exception_message(string_java_lang_ArithmeticException,
-                                                         string_java_lang_ArithmeticException_message);
+       java_handle_t *o;
 
-       if (!e)
-               return *exceptionptr;
+       o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
+                                                          utf_division_by_zero);
 
-       return e;
+       return o;
 }
 
 
@@ -1120,12 +1350,11 @@ java_objectheader *new_arithmeticexception(void)
 
 *******************************************************************************/
 
-java_objectheader *new_arrayindexoutofboundsexception(s4 index)
+java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
 {
-       java_objectheader *e;
-       methodinfo        *m;
-       java_objectheader *o;
-       java_lang_String  *s;
+       java_handle_t *o;
+       methodinfo    *m;
+       java_handle_t *s;
 
        /* convert the index into a String, like Sun does */
 
@@ -1136,183 +1365,188 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index)
                                                                 true);
 
        if (m == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
-       o = vm_call_method(m, NULL, index);
-
-       s = (java_lang_String *) o;
+       s = vm_call_method(m, NULL, index);
 
        if (s == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
-       e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
-                                                                s);
+       o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
+                                                                         s);
 
-       if (e == NULL)
-               return *exceptionptr;
+       if (o == NULL)
+               return exceptions_get_exception();
 
-       return e;
+       return o;
 }
 
 
 /* exceptions_throw_arrayindexoutofboundsexception *****************************
 
-   Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
-   system.
+   Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
+   the VM.
 
 *******************************************************************************/
 
 void exceptions_throw_arrayindexoutofboundsexception(void)
 {
-       java_objectheader *e;
-
-       e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
-
-       if (!e)
-               return;
-
-       *exceptionptr = e;
+       exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
 }
 
 
-/* new_arraystoreexception *****************************************************
+/* exceptions_throw_arraystoreexception ****************************************
 
-   generates a java.lang.ArrayStoreException for the jit compiler
+   Generates and throws a java.lang.ArrayStoreException for the VM.
 
 *******************************************************************************/
 
-java_objectheader *new_arraystoreexception(void)
+void exceptions_throw_arraystoreexception(void)
 {
-       java_objectheader *e;
-
-       e = new_exception(string_java_lang_ArrayStoreException);
-/*     e = native_new_and_init(class_java_lang_ArrayStoreException); */
-
-       if (!e)
-               return *exceptionptr;
-
-       return e;
+       exceptions_throw_utf(utf_java_lang_ArrayStoreException);
 }
 
 
-/* new_classcastexception ******************************************************
+/* exceptions_new_classcastexception *******************************************
 
-   generates a java.lang.ClassCastException for the jit compiler
+   Generates a java.lang.ClassCastException for the JIT compiler.
 
 *******************************************************************************/
 
-java_objectheader *new_classcastexception(void)
+java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
 {
-       java_objectheader *e;
+       java_handle_t *e;
+       classinfo     *c;
+       utf           *classname;
+
+       LLNI_class_get(o, c);
 
-       e = new_exception(string_java_lang_ClassCastException);
+       classname = c->name;
 
-       if (!e)
-               return *exceptionptr;
+       e = exceptions_new_utf_utf(utf_java_lang_ClassCastException, classname);
 
        return e;
 }
 
 
-/* exceptions_new_illegalargumentexception *************************************
+/* exceptions_throw_clonenotsupportedexception *********************************
 
-   Generates a java.lang.IllegalArgumentException for the VM system.
+   Generates and throws a java.lang.CloneNotSupportedException for the
+   VM.
 
 *******************************************************************************/
 
-java_objectheader *new_illegalargumentexception(void)
+void exceptions_throw_clonenotsupportedexception(void)
 {
-       java_objectheader *e;
+       exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
+}
 
-       e = native_new_and_init(class_java_lang_IllegalArgumentException);
 
-       if (!e)
-               return *exceptionptr;
+/* exceptions_throw_illegalaccessexception *************************************
 
-       return e;
+   Generates and throws a java.lang.IllegalAccessException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_illegalaccessexception(utf *message)
+{
+       exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
 }
 
 
 /* exceptions_throw_illegalargumentexception ***********************************
 
-   Generates a java.lang.IllegalArgumentException for the VM system
-   and throw it in the VM system.
+   Generates and throws a java.lang.IllegalArgumentException for the
+   VM.
 
 *******************************************************************************/
 
 void exceptions_throw_illegalargumentexception(void)
 {
-       *exceptionptr = new_illegalargumentexception();
+       exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
 }
 
 
-/* new_illegalmonitorstateexception ********************************************
+/* exceptions_throw_illegalmonitorstateexception *******************************
 
-   Generates a java.lang.IllegalMonitorStateException for the VM
-   thread system.
+   Generates and throws a java.lang.IllegalMonitorStateException for
+   the VM.
 
 *******************************************************************************/
 
-java_objectheader *new_illegalmonitorstateexception(void)
+void exceptions_throw_illegalmonitorstateexception(void)
 {
-       java_objectheader *e;
+       exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
+}
 
-       e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
 
-       if (!e)
-               return *exceptionptr;
+/* exceptions_throw_instantiationexception *************************************
 
-       return e;
+   Generates and throws a java.lang.InstantiationException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_instantiationexception(classinfo *c)
+{
+       exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
 }
 
 
-/* exceptions_new_negativearraysizeexception ***********************************
+/* exceptions_throw_interruptedexception ***************************************
 
-   Generates a java.lang.NegativeArraySizeException for the VM system.
+   Generates and throws a java.lang.InterruptedException for the VM.
 
 *******************************************************************************/
 
-java_objectheader *new_negativearraysizeexception(void)
+void exceptions_throw_interruptedexception(void)
 {
-       java_objectheader *e;
+       exceptions_throw_utf(utf_java_lang_InterruptedException);
+}
 
-       e = new_exception(string_java_lang_NegativeArraySizeException);
 
-       if (!e)
-               return *exceptionptr;
+/* exceptions_throw_invocationtargetexception **********************************
 
-       return e;
+   Generates and throws a java.lang.reflect.InvocationTargetException
+   for the VM.
+
+   IN:
+      cause......cause exception object
+
+*******************************************************************************/
+
+void exceptions_throw_invocationtargetexception(java_handle_t *cause)
+{
+       exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
+                                                                  cause);
 }
 
 
 /* exceptions_throw_negativearraysizeexception *********************************
 
-   Generates a java.lang.NegativeArraySizeException for the VM system.
+   Generates and throws a java.lang.NegativeArraySizeException for the
+   VM.
 
 *******************************************************************************/
 
 void exceptions_throw_negativearraysizeexception(void)
 {
-       *exceptionptr = new_negativearraysizeexception();
+       exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
 }
 
 
-/* new_nullpointerexception ****************************************************
+/* exceptions_new_nullpointerexception *****************************************
 
-   generates a java.lang.NullPointerException for the jit compiler
+   Generates a java.lang.NullPointerException for the VM system.
 
 *******************************************************************************/
 
-java_objectheader *new_nullpointerexception(void)
+java_handle_t *exceptions_new_nullpointerexception(void)
 {
-       java_objectheader *e;
+       java_handle_t *o;
 
-       e = native_new_and_init(class_java_lang_NullPointerException);
+       o = exceptions_new_utf(utf_java_lang_NullPointerException);
 
-       if (!e)
-               return *exceptionptr;
-
-       return e;
+       return o;
 }
 
 
@@ -1325,40 +1559,132 @@ java_objectheader *new_nullpointerexception(void)
 
 void exceptions_throw_nullpointerexception(void)
 {
-       *exceptionptr = new_nullpointerexception();
+       exceptions_throw_utf(utf_java_lang_NullPointerException);
 }
 
 
-/* exceptions_new_stringindexoutofboundsexception ******************************
+/* exceptions_throw_privilegedactionexception **********************************
 
-   Generates a java.lang.StringIndexOutOfBoundsException for the VM
-   system.
+   Generates and throws a java.security.PrivilegedActionException.
 
 *******************************************************************************/
 
-java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
+void exceptions_throw_privilegedactionexception(java_handle_t *exception)
 {
-       java_objectheader *e;
+       exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
+                                                                  exception);
+}
+
 
-       e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
+/* exceptions_throw_stringindexoutofboundsexception ****************************
 
-       if (e == NULL)
-               return *exceptionptr;
+   Generates and throws a java.lang.StringIndexOutOfBoundsException
+   for the VM.
 
-       return e;
+*******************************************************************************/
+
+void exceptions_throw_stringindexoutofboundsexception(void)
+{
+       exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
 }
 
 
-/* exceptions_throw_stringindexoutofboundsexception ****************************
+/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
 
-   Throws a java.lang.StringIndexOutOfBoundsException for the VM
-   system.
+   Check the exception for a ClassNotFoundException. If it is one,
+   convert it to a NoClassDefFoundError.
 
 *******************************************************************************/
 
-void exceptions_throw_stringindexoutofboundsexception(void)
+void exceptions_classnotfoundexception_to_noclassdeffounderror(void)
+{
+       classinfo           *c;
+       java_handle_t       *o;
+       java_handle_t       *cause;
+       java_lang_Throwable *object;
+       java_lang_String    *s;
+
+       /* Load java/lang/ClassNotFoundException for the instanceof
+          check. */
+
+       c = load_class_bootstrap(utf_java_lang_ClassNotFoundException);
+
+       if (c == NULL)
+               return;
+
+       /* Get the cause. */
+
+       cause = exceptions_get_exception();
+
+       /* Convert ClassNotFoundException's to NoClassDefFoundError's. */
+
+       if (builtin_instanceof(cause, c)) {
+               /* clear exception, because we are calling jit code again */
+
+               exceptions_clear_exception();
+
+               /* create new error */
+
+               object = (java_lang_Throwable *) cause;
+               LLNI_field_get_ref(object, detailMessage, s);
+
+               o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
+                                                                                 (java_handle_t *) s);
+
+               /* we had an exception while creating the error */
+
+               if (exceptions_get_exception())
+                       return;
+
+               /* set new exception */
+
+               exceptions_set_exception(o);
+       }
+}
+
+
+/* exceptions_fillinstacktrace *************************************************
+
+   Calls the fillInStackTrace-method of the currently thrown
+   exception.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_fillinstacktrace(void)
 {
-       *exceptionptr = exceptions_new_stringindexoutofboundsexception();
+       java_handle_t *o;
+       classinfo     *c;
+       methodinfo    *m;
+
+       /* get exception */
+
+       o = exceptions_get_and_clear_exception();
+
+       assert(o);
+
+       /* resolve methodinfo pointer from exception object */
+
+       LLNI_class_get(o, c);
+
+#if defined(ENABLE_JAVASE)
+       m = class_resolvemethod(c,
+                                                       utf_fillInStackTrace,
+                                                       utf_void__java_lang_Throwable);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+       m = class_resolvemethod(c,
+                                                       utf_fillInStackTrace,
+                                                       utf_void__void);
+#else
+#error IMPLEMENT ME!
+#endif
+
+       /* call function */
+
+       (void) vm_call_method(m, o);
+
+       /* return exception object */
+
+       return o;
 }
 
 
@@ -1380,30 +1706,47 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 
 *******************************************************************************/
 
-u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
+#if defined(ENABLE_JIT)
+u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 {
+       stackframeinfo_t       sfi;
+       java_handle_t         *xptr;
        methodinfo            *m;
        codeinfo              *code;
-       s4                     framesize;
-       s4                     issync;
-       exceptionentry        *ex;
+       dseg_exception_entry  *ex;
        s4                     exceptiontablelength;
        s4                     i;
        classref_or_classinfo  cr;
        classinfo             *c;
 #if defined(ENABLE_THREADS)
-       java_objectheader     *o;
+       java_object_t         *o;
+#endif
+       u1                    *result;
+
+#ifdef __S390__
+       /* Addresses are 31 bit integers */
+#      define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
+#else
+#      define ADDR_MASK(x) (x)
 #endif
 
-       /* get info from the method header */
+       xptr = LLNI_WRAP(xptro);
+       xpc  = ADDR_MASK(xpc);
 
-       code                 = *((codeinfo **)      (pv + CodeinfoPointer));
-       framesize            = *((s4 *)             (pv + FrameSize));
-       issync               = *((s4 *)             (pv + IsSync));
-       ex                   =   (exceptionentry *) (pv + ExTableStart);
-       exceptiontablelength = *((s4 *)             (pv + ExTableSize));
+       /* Fill and add a stackframeinfo (XPC is equal to RA). */
 
-       /* Get the methodinfo pointer form the codeinfo pointer. For
+       stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
+
+       result = NULL;
+
+       /* Get the codeinfo for the current method. */
+
+       code = code_get_codeinfo_for_pv(pv);
+
+       ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
+       exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
+
+       /* Get the methodinfo pointer from the codeinfo pointer. For
           asm_vm_call_method the codeinfo pointer is NULL. */
 
        m = (code == NULL) ? NULL : code->m;
@@ -1411,8 +1754,12 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
        /* print exception trace */
 
-       if (opt_verbose || opt_verbosecall || opt_verboseexception)
-               builtin_trace_exception(xptr, m, xpc, 1);
+       if (opt_TraceExceptions)
+               trace_exception(LLNI_DIRECT(xptr), m, xpc);
+
+# if defined(ENABLE_VMLOG)
+       vmlog_cacao_throw(xptr);
+# endif
 #endif
 
        for (i = 0; i < exceptiontablelength; i++) {
@@ -1425,12 +1772,14 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
                   special case of asm_vm_call_method.  So, just return the
                   proper exception handler. */
 
-               if ((ex->startpc == NULL) && (ex->endpc == NULL))
-                       return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
+               if ((ex->startpc == NULL) && (ex->endpc == NULL)) {
+                       result = (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
+                       goto exceptions_handle_exception_return;
+               }
 
                /* is the xpc is the current catch range */
 
-               if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
+               if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
                        cr = ex->catchtype;
 
                        /* NULL catches everything */
@@ -1439,32 +1788,60 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
                                /* Print stacktrace of exception when caught. */
 
-                               if (opt_verboseexception) {
+# if defined(ENABLE_VMLOG)
+                               vmlog_cacao_catch(xptr);
+# endif
+
+                               if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
                                        stacktrace_print_trace(xptr);
                                }
 #endif
 
-                               return ex->handlerpc;
+                               result = ex->handlerpc;
+                               goto exceptions_handle_exception_return;
                        }
 
                        /* resolve or load/link the exception class */
 
                        if (IS_CLASSREF(cr)) {
+                               /* The exception class reference is unresolved. */
+                               /* We have to do _eager_ resolving here. While the class of */
+                               /* the exception object is guaranteed to be loaded, it may  */
+                               /* well have been loaded by a different loader than the     */
+                               /* defining loader of m's class, which is the one we must   */
+                               /* use to resolve the catch class. Thus lazy resolving      */
+                               /* might fail, even if the result of the resolution would   */
+                               /* be an already loaded class.                              */
+
                                c = resolve_classref_eager(cr.ref);
 
+                               if (c == NULL) {
+                                       /* Exception resolving the exception class, argh! */
+                                       goto exceptions_handle_exception_return;
+                               }
+
+                               /* Ok, we resolved it. Enter it in the table, so we don't */
+                               /* have to do this again.                                 */
+                               /* XXX this write should be atomic. Is it?                */
+
+                               ex->catchtype.cls = c;
                        } else {
                                c = cr.cls;
 
+                               /* XXX I don't think this case can ever happen. -Edwin */
                                if (!(c->state & CLASS_LOADED))
                                        /* use the methods' classloader */
                                        if (!load_class_from_classloader(c->name,
                                                                                                         m->class->classloader))
-                                               return NULL;
+                                               goto exceptions_handle_exception_return;
 
+                               /* XXX I think, if it is not linked, we can be sure that     */
+                               /* the exception object is no (indirect) instance of it, no? */
+                               /* -Edwin                                                    */
                                if (!(c->state & CLASS_LINKED))
                                        if (!link_class(c))
-                                               return NULL;
+                                               goto exceptions_handle_exception_return;
                        }
 
                        /* is the thrown exception an instance of the catch class? */
@@ -1473,40 +1850,77 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
                                /* Print stacktrace of exception when caught. */
 
-                               if (opt_verboseexception) {
+# if defined(ENABLE_VMLOG)
+                               vmlog_cacao_catch(xptr);
+# endif
+
+                               if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
                                        stacktrace_print_trace(xptr);
                                }
 #endif
 
-                               return ex->handlerpc;
+                               result = ex->handlerpc;
+                               goto exceptions_handle_exception_return;
                        }
                }
        }
 
 #if defined(ENABLE_THREADS)
-       /* is this method synchronized? */
+       /* Is this method realization synchronized? */
 
-       if (issync) {
-               /* get synchronization object */
+       if (code_is_synchronized(code)) {
+               /* Get synchronization object. */
 
-# if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+# if defined(__ARM__) || (defined(__MIPS__) && (SIZEOF_VOID_P == 4)) || defined(__I386__) || defined(__S390__) || defined(__POWERPC__)
                /* XXX change this if we ever want to use 4-byte stackslots */
-               o = *((java_objectheader **) (sp + issync - 8));
+               o = *((java_object_t **) (sp + code->synchronizedoffset - 8));
 # else
-               o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
-#endif
+               o = *((java_object_t **) (sp + code->synchronizedoffset - SIZEOF_VOID_P));
+# endif
 
                assert(o != NULL);
 
-               builtin_monitorexit(o);
+               lock_monitor_exit(o);
        }
 #endif
 
        /* none of the exceptions catch this one */
 
-       return NULL;
+#if !defined(NDEBUG)
+# if defined(ENABLE_VMLOG)
+       vmlog_cacao_unwnd_method(m);
+# endif
+
+# if defined(ENABLE_DEBUG_FILTER)
+       if (show_filters_test_verbosecall_exit(m)) {
+# endif
+
+       /* outdent the log message */
+
+       if (opt_verbosecall) {
+               if (TRACEJAVACALLINDENT)
+                       TRACEJAVACALLINDENT--;
+               else
+                       log_text("exceptions_handle_exception: WARNING: unmatched unindent");
+       }
+
+# if defined(ENABLE_DEBUG_FILTER)
+       }
+# endif
+#endif /* !defined(NDEBUG) */
+
+       result = NULL;
+
+exceptions_handle_exception_return:
+
+       /* Remove the stackframeinfo. */
+
+       stacktrace_stackframeinfo_remove(&sfi);
+
+       return result;
 }
+#endif /* defined(ENABLE_JIT) */
 
 
 /* exceptions_print_exception **************************************************
@@ -1516,11 +1930,14 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
 *******************************************************************************/
 
-#if !defined(NDEBUG)
-void exceptions_print_exception(java_objectheader *xptr)
+void exceptions_print_exception(java_handle_t *xptr)
 {
        java_lang_Throwable   *t;
+#if defined(ENABLE_JAVASE)
        java_lang_Throwable   *cause;
+#endif
+       java_lang_String      *s;
+       classinfo             *c;
        utf                   *u;
 
        t = (java_lang_Throwable *) xptr;
@@ -1530,14 +1947,19 @@ void exceptions_print_exception(java_objectheader *xptr)
                return;
        }
 
-       cause = t->cause;
+#if defined(ENABLE_JAVASE)
+       LLNI_field_get_ref(t, cause, cause);
+#endif
 
        /* print the root exception */
 
-       utf_display_printable_ascii_classname(t->header.vftbl->class->name);
+       LLNI_class_get(t, c);
+       utf_display_printable_ascii_classname(c->name);
+
+       LLNI_field_get_ref(t, detailMessage, s);
 
-       if (t->detailMessage) {
-               u = javastring_toutf(t->detailMessage, false);
+       if (s != NULL) {
+               u = javastring_toutf((java_handle_t *) s, false);
 
                printf(": ");
                utf_display_printable_ascii(u);
@@ -1545,14 +1967,19 @@ void exceptions_print_exception(java_objectheader *xptr)
 
        putc('\n', stdout);
 
+#if defined(ENABLE_JAVASE)
        /* print the cause if available */
 
-       if (cause && (cause != t)) {
+       if ((cause != NULL) && (cause != t)) {
                printf("Caused by: ");
-               utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
+               
+               LLNI_class_get(cause, c);
+               utf_display_printable_ascii_classname(c->name);
+
+               LLNI_field_get_ref(cause, detailMessage, s);
 
-               if (cause->detailMessage) {
-                       u = javastring_toutf(cause->detailMessage, false);
+               if (s != NULL) {
+                       u = javastring_toutf((java_handle_t *) s, false);
 
                        printf(": ");
                        utf_display_printable_ascii(u);
@@ -1560,8 +1987,97 @@ void exceptions_print_exception(java_objectheader *xptr)
 
                putc('\n', stdout);
        }
+#endif
+}
+
+
+/* exceptions_print_current_exception ******************************************
+
+   Prints the current pending exception, the detail message and the
+   cause, if available, with CACAO internal functions to stdout.
+
+*******************************************************************************/
+
+void exceptions_print_current_exception(void)
+{
+       java_handle_t *o;
+
+       o = exceptions_get_exception();
+
+       exceptions_print_exception(o);
+}
+
+
+/* exceptions_print_stacktrace *************************************************
+
+   Prints a pending exception with Throwable.printStackTrace().  If
+   there happens an exception during printStackTrace(), we print the
+   thrown exception and the original one.
+
+   NOTE: This function calls Java code.
+
+*******************************************************************************/
+
+void exceptions_print_stacktrace(void)
+{
+       java_handle_t *oxptr;
+       java_handle_t *xptr;
+       classinfo     *c;
+       methodinfo    *m;
+
+       /* get original exception */
+
+       oxptr = exceptions_get_and_clear_exception();
+
+       if (oxptr == NULL)
+               vm_abort("exceptions_print_stacktrace: no exception thrown");
+
+       /* clear exception, because we are calling jit code again */
+
+       LLNI_class_get(oxptr, c);
+
+       /* find the printStackTrace() method */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_printStackTrace,
+                                                                utf_void__void,
+                                                                class_java_lang_Object,
+                                                                false);
+
+       if (m == NULL)
+               vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+
+       /* print compatibility message */
+
+       fprintf(stderr, "Exception in thread \"main\" ");
+
+       /* print the stacktrace */
+
+       (void) vm_call_method(m, oxptr);
+
+       /* This normally means, we are EXTREMLY out of memory or
+          have a serious problem while printStackTrace. But may
+          be another exception, so print it. */
+
+       xptr = exceptions_get_exception();
+
+       if (xptr != NULL) {
+               fprintf(stderr, "Exception while printStackTrace(): ");
+
+               /* now print original exception */
+
+               exceptions_print_exception(xptr);
+               stacktrace_print_trace(xptr);
+
+               /* now print original exception */
+
+               fprintf(stderr, "Original exception was: ");
+               exceptions_print_exception(oxptr);
+               stacktrace_print_trace(oxptr);
+       }
+
+       fflush(stderr);
 }
-#endif /* !defined(NDEBUG) */
 
 
 /*