* src/cacaoh/dummy.c (resolve_handle_pending_exception): New function.
authorChristian Thalinger <twisti@complang.tuwien.ac.at>
Wed, 26 Mar 2008 16:14:46 +0000 (17:14 +0100)
committerChristian Thalinger <twisti@complang.tuwien.ac.at>
Wed, 26 Mar 2008 16:14:46 +0000 (17:14 +0100)
* src/native/vm/sun/jvm.c (JVM_FindClassFromClassLoader): Added assert
on throwError.
(JVM_DoPrivileged): Throw PrivilegedActionException only if the
exception is an instance of java.lang.Exception but not of
java.lang.RuntimeException.

* src/vm/exceptions.c (exceptions_new_class_utf): New function.
(exceptions_throw_class_utf): Likewise.
(exceptions_throw_classnotfoundexception): Use
exceptions_throw_class_utf.
(exceptions_classnotfoundexception_to_noclassdeffounderror): Removed.
* src/vm/exceptions.h: Likewise.

* src/vm/resolve.c (resolve_handle_pending_exception): New function.
(resolve_class_from_name): Don't convert exception.
* src/vm/resolve.h (resolve_handle_pending_exception): Added.

* src/vmcore/class.c (class_java_lang_Exception): New global variable.
(class_java_lang_ClassNotFoundException): Likewise.
(class_java_lang_RuntimeException): Likewise.
* src/vmcore/class.h: Likewise.

* src/vmcore/linker.c (linker_init): Link new global classes.
* src/vmcore/loader.c (loader_init): Load new global classes.

* src/vmcore/utf8.c (utf_java_lang_RuntimeException): New global
variable.
(utf8_init): Initialize new global variable.
* src/vmcore/utf8.h (utf_java_lang_RuntimeException): Export.

* tests/regression/bugzilla/All.java: Added PR58.
* tests/regression/bugzilla/PR58.java: New file.

14 files changed:
src/cacaoh/dummy.c
src/native/vm/sun/jvm.c
src/vm/exceptions.c
src/vm/exceptions.h
src/vm/resolve.c
src/vm/resolve.h
src/vmcore/class.c
src/vmcore/class.h
src/vmcore/linker.c
src/vmcore/loader.c
src/vmcore/utf8.c
src/vmcore/utf8.h
tests/regression/bugzilla/All.java
tests/regression/bugzilla/PR58.java [new file with mode: 0644]

index f7fe97c5f8c8a11634f6cfd6621d5251486fe7e8..3177b4143406fd710ae912e9f339a41c97ea61ed 100644 (file)
@@ -608,6 +608,11 @@ char *properties_get(char *key)
 
 /* resolve ********************************************************************/
 
+void resolve_handle_pending_exception(bool throwError)
+{
+       vm_abort("resolve_handle_pending_exception: Not implemented.");
+}
+
 bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
 {
        abort();
index 5c8d361d5975446e6ddca1e700334c94217a0210..91545dd36438e3eccd93682d200207f831d84776 100644 (file)
@@ -776,6 +776,11 @@ jclass JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init
 
        TRACEJVMCALLS(("JVM_FindClassFromClassLoader(name=%s, init=%d, loader=%p, throwError=%d)", name, init, loader, throwError));
 
+       /* As of now, OpenJDK does not call this function with throwError
+          is true. */
+
+       assert(throwError == false);
+
        u  = utf_new_char(name);
        cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
@@ -985,7 +990,7 @@ void JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)
 
 jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)
 {
-       java_handle_t *o;
+       java_handle_t *h;
        classinfo     *c;
        methodinfo    *m;
        java_handle_t *result;
@@ -993,8 +998,8 @@ jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject contex
 
        TRACEJVMCALLS(("JVM_DoPrivileged(env=%p, cls=%p, action=%p, context=%p, wrapException=%d)", env, cls, action, context, wrapException));
 
-       o = (java_handle_t *) action;
-       c = o->vftbl->class;
+       h = (java_handle_t *) action;
+       LLNI_class_get(h, c);
 
        if (action == NULL) {
                exceptions_throw_nullpointerexception();
@@ -1014,12 +1019,17 @@ jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject contex
        /* XXX It seems something with a privileged stack needs to be done
           here. */
 
-       result = vm_call_method(m, o);
+       result = vm_call_method(m, h);
 
-       e = exceptions_get_and_clear_exception();
+       e = exceptions_get_exception();
 
        if (e != NULL) {
-               exceptions_throw_privilegedactionexception(e);
+               if ( builtin_instanceof(e, class_java_lang_Exception) &&
+                       !builtin_instanceof(e, class_java_lang_RuntimeException)) {
+                       exceptions_clear_exception();
+                       exceptions_throw_privilegedactionexception(e);
+               }
+
                return NULL;
        }
 
index 26ca1fda3e3264fccb999c52eb5c737288617292..707328ec7769487b7f28601453c8412ddf006461 100644 (file)
@@ -276,6 +276,44 @@ static void exceptions_abort(utf *classname, utf *message)
 }
 
 
+/* exceptions_new_class_utf ****************************************************
+
+   Creates an exception object with the given class and initalizes it
+   with the given utf message.
+
+   IN:
+      c ......... exception class
+         message ... the message as an 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).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
+{
+       java_handle_t *s;
+       java_handle_t *o;
+
+       if (vm_initializing)
+               exceptions_abort(c->name, message);
+
+       s = javastring_new(message);
+
+       if (s == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, s);
+
+       if (o == NULL)
+               return exceptions_get_exception();
+
+       return o;
+}
+
+
 /* exceptions_new_utf **********************************************************
 
    Creates an exception object with the given name and initalizes it.
@@ -307,6 +345,99 @@ static java_handle_t *exceptions_new_utf(utf *classname)
 }
 
 
+/* exceptions_new_utf_javastring ***********************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/String 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).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+                                                                                                       java_handle_t *message)
+{
+       java_handle_t *o;
+       classinfo     *c;
+   
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, message);
+
+       if (o == NULL)
+               return exceptions_get_exception();
+
+       return o;
+}
+
+
+/* exceptions_new_utf_utf ******************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given utf message.
+
+   IN:
+      classname....class name in UTF-8
+         message......the message as an 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).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
+{
+       classinfo     *c;
+       java_handle_t *o;
+
+       if (vm_initializing)
+               exceptions_abort(classname, message);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return exceptions_get_exception();
+
+       o = exceptions_new_class_utf(c, message);
+
+       return o;
+}
+
+
+/* exceptions_throw_class_utf **************************************************
+
+   Creates an exception object with the given class, initalizes and
+   throws it with the given utf message.
+
+   IN:
+      c ......... exception class
+         message ... the message as an utf *
+
+*******************************************************************************/
+
+static void exceptions_throw_class_utf(classinfo *c, utf *message)
+{
+       java_handle_t *o;
+
+       o = exceptions_new_class_utf(c, message);
+
+       exceptions_set_exception(o);
+}
+
+
 /* exceptions_throw_utf ********************************************************
 
    Creates an exception object with the given name, initalizes and
@@ -501,87 +632,6 @@ static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
 }
 
 
-/* exceptions_new_utf_javastring ***********************************************
-
-   Creates an exception object with the given name and initalizes it
-   with the given java/lang/String 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).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_javastring(utf *classname,
-                                                                                                       java_handle_t *message)
-{
-       java_handle_t *o;
-       classinfo     *c;
-   
-       if (vm_initializing)
-               exceptions_abort(classname, NULL);
-
-       c = load_class_bootstrap(classname);
-
-       if (c == NULL)
-               return exceptions_get_exception();
-
-       o = native_new_and_init_string(c, message);
-
-       if (o == NULL)
-               return exceptions_get_exception();
-
-       return o;
-}
-
-
-/* exceptions_new_utf_utf ******************************************************
-
-   Creates an exception object with the given name and initalizes it
-   with the given utf message.
-
-   IN:
-      classname....class name in UTF-8
-         message......the message as an 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).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
-{
-       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 == NULL)
-               return exceptions_get_exception();
-
-       o = native_new_and_init_string(c, s);
-
-       if (o == NULL)
-               return exceptions_get_exception();
-
-       return o;
-}
-
-
 /* exceptions_throw_utf_utf ****************************************************
 
    Creates an exception object with the given name, initalizes and
@@ -794,7 +844,7 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 
 void exceptions_throw_classnotfoundexception(utf *name)
 {      
-       exceptions_throw_utf_utf(utf_java_lang_ClassNotFoundException, name);
+       exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
 }
 
 
@@ -1589,60 +1639,6 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 }
 
 
-/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
-
-   Check the exception for a ClassNotFoundException. If it is one,
-   convert it to a NoClassDefFoundError.
-
-*******************************************************************************/
-
-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
index 93958851a4027ed9e82badfad239ad296cfb4503..933eb2c33b99989bcde574052f2d63bc1cd9105b 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/exceptions.h - exception related functions prototypes
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -131,8 +129,6 @@ void exceptions_throw_nullpointerexception(void);
 void exceptions_throw_privilegedactionexception(java_handle_t *cause);
 void exceptions_throw_stringindexoutofboundsexception(void);
 
-void exceptions_classnotfoundexception_to_noclassdeffounderror(void);
-
 java_handle_t *exceptions_fillinstacktrace(void);
 
 void exceptions_print_exception(java_handle_t *xptr);
index 3f60dbc57be8dff3fd12ff98584f0e51842cd7f3..fddbc29b647eae8677fcb165caf2e190b37555d3 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
 /*#define RESOLVE_VERBOSE*/
 
+/* resolve_handle_pending_exception ********************************************
+
+   Convert a pending ClassNotFoundException into a
+   NoClassDefFoundError if requested.
+
+   See: hotspot/src/share/vm/classfile/systemDictionary.cpp
+   (handle_resolution_exception)
+
+   ARGUMENTS:
+       classname .... name of the class currently resolved
+       throwError ... if true throw a NoClassDefFoundError instead of
+                      a ClassNotFoundException
+
+*******************************************************************************/
+
+void resolve_handle_pending_exception(bool throwError)
+{
+       java_handle_t *e;
+
+       /* Get the current exception. */
+
+       e = exceptions_get_exception();
+
+       if (e != NULL) {
+               if (throwError == true) {
+                       /* Convert ClassNotFoundException to
+                          NoClassDefFoundError. */
+
+                       if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
+                               /* Clear exception, because we are calling Java code
+                                  again. */
+
+                               exceptions_clear_exception();
+
+                               /* create new error */
+
+                               exceptions_throw_noclassdeffounderror_cause(e);
+                       }
+                       else {
+                               return;
+                       }
+               }
+               else {
+                       /* An exception conversion was not requested.  Simply
+                          return. */
+
+                       return;
+               }
+       }
+}
+
+
 /******************************************************************************/
 /* CLASS RESOLUTION                                                           */
 /******************************************************************************/
@@ -177,14 +227,8 @@ bool resolve_class_from_name(classinfo *referer,
                if (cls == NULL) {
                        cls = load_class_from_classloader(classname, referer->classloader);
 
-                       if (cls == NULL) {
-                               /* If the exception is a ClassNotFoundException,
-                                  convert it to a NoClassDefFoundError. */
-
-                               exceptions_classnotfoundexception_to_noclassdeffounderror();
-
+                       if (cls == NULL)
                                return false;
-                       }
                }
        }
 
index b38b80b7606a3a35117920be3c0f02c3caab607d..1082175763207ae8c03cf827b52eae434c6eaba5 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/resolve.h - resolving classes/interfaces/fields/methods
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -114,8 +112,11 @@ struct unresolved_method {
 #define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \
        do { (stset).subtyperefs = NULL; } while(0)
 
+
 /* function prototypes ********************************************************/
 
+void resolve_handle_pending_exception(bool throwError);
+
 bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
                                                utf *classname,
                                                resolve_mode_t mode,
index fe5f70a6e576b0f035227bd2d04f52b39167e537..da2ccb28400f0e626612329f2fb0aa28bbd6be79 100644 (file)
@@ -68,7 +68,7 @@
 
 /* frequently used classes ****************************************************/
 
-/* important system classes */
+/* Important system classes. */
 
 classinfo *class_java_lang_Object;
 classinfo *class_java_lang_Class;
@@ -88,6 +88,12 @@ classinfo *class_java_lang_VMThread;
 classinfo *class_java_lang_VMThrowable;
 #endif
 
+/* Important system exceptions. */
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
 #if defined(WITH_CLASSPATH_SUN)
 classinfo *class_sun_reflect_MagicAccessorImpl;
 #endif
index 7f25b8f31e59686249d58b91f40c751fe582dbd3..4cb801dfd61fea3fb7c8472d54fdd05302eab5b9 100644 (file)
@@ -203,7 +203,7 @@ struct castinfo {
 
 /* frequently used classes ****************************************************/
 
-/* important system classes */
+/* Important system classes. */
 
 extern classinfo *class_java_lang_Object;
 extern classinfo *class_java_lang_Class;
@@ -217,6 +217,12 @@ extern classinfo *class_java_lang_ThreadGroup;
 extern classinfo *class_java_lang_Throwable;
 extern classinfo *class_java_io_Serializable;
 
+/* Important system exceptions. */
+
+extern classinfo *class_java_lang_Exception;
+extern classinfo *class_java_lang_ClassNotFoundException;
+extern classinfo *class_java_lang_RuntimeException;
+
 #if defined(WITH_CLASSPATH_GNU)
 extern classinfo *class_java_lang_VMSystem;
 extern classinfo *class_java_lang_VMThread;
index d1c9c4531b0e603b651392fe756248498147adce..edeee699a117236a986c69a9daeafa4fcea36c35 100644 (file)
@@ -279,6 +279,16 @@ void linker_init(void)
                vm_abort("linker_init: linking failed");
 #endif
 
+       /* Important system exceptions. */
+
+       if (!link_class(class_java_lang_Exception))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_ClassNotFoundException))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_RuntimeException))
+               vm_abort("linker_init: linking failed");
 
        /* some classes which may be used more often */
 
index 6ab5036d36a2e3be509fc05fe9474f9dba0ac73f..a2b754e7b7209aa7cd7c76ccdfbe1f7a6d33fd1b 100644 (file)
@@ -197,6 +197,16 @@ void loader_init(void)
                load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
 #endif
 
+       /* Important system exceptions. */
+
+       class_java_lang_Exception  = load_class_bootstrap(utf_java_lang_Exception);
+
+       class_java_lang_ClassNotFoundException =
+               load_class_bootstrap(utf_java_lang_ClassNotFoundException);
+
+       class_java_lang_RuntimeException =
+               load_class_bootstrap(utf_java_lang_RuntimeException);
+
        /* Some classes which may be used often. */
 
 #if defined(ENABLE_JAVASE)
@@ -1643,8 +1653,10 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
                /* XXX This should be done better. */
                tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
 
-               if (tc == NULL)
+               if (tc == NULL) {
+                       resolve_handle_pending_exception(true);
                        return false;
+               }
 
                /* Interfaces are not allowed as super classes. */
 
index 364526129029923ea64ed7197031ef7bd95aac7e..fe2da62dbe3817e667f0a7315044cb56fe8c8345 100644 (file)
@@ -106,6 +106,7 @@ utf *utf_java_lang_InstantiationException;
 utf *utf_java_lang_InterruptedException;
 utf *utf_java_lang_NegativeArraySizeException;
 utf *utf_java_lang_NullPointerException;
+utf *utf_java_lang_RuntimeException;
 utf *utf_java_lang_StringIndexOutOfBoundsException;
 
 utf *utf_java_lang_reflect_InvocationTargetException;
@@ -350,6 +351,9 @@ void utf8_init(void)
        utf_java_lang_NullPointerException =
                utf_new_char("java/lang/NullPointerException");
 
+       utf_java_lang_RuntimeException =
+               utf_new_char("java/lang/RuntimeException");
+
        utf_java_lang_StringIndexOutOfBoundsException =
                utf_new_char("java/lang/StringIndexOutOfBoundsException");
 
index c3e2ae53851966b67361ce8c1618f2bfd2459a86..1c6caf69f02ad49d02221d48989b4d84153fbe40 100644 (file)
@@ -102,6 +102,7 @@ extern utf *utf_java_lang_InstantiationException;
 extern utf *utf_java_lang_InterruptedException;
 extern utf *utf_java_lang_NegativeArraySizeException;
 extern utf *utf_java_lang_NullPointerException;
+extern utf *utf_java_lang_RuntimeException;
 extern utf *utf_java_lang_StringIndexOutOfBoundsException;
 
 extern utf *utf_java_lang_reflect_InvocationTargetException;
index d0183567a73d9850efb8b5d22509f5186314535a..8e144ea2e645dc5ba6347b584262081e53728938 100644 (file)
@@ -46,6 +46,7 @@ public class All extends TestCase {
 
         suite.addTest(new TestSuite(PR52.class));
         suite.addTest(new TestSuite(PR57.class));
+        suite.addTest(new TestSuite(PR58.class));
 
         return suite;
     }
diff --git a/tests/regression/bugzilla/PR58.java b/tests/regression/bugzilla/PR58.java
new file mode 100644 (file)
index 0000000..1451226
--- /dev/null
@@ -0,0 +1,59 @@
+/* tests/regression/bugzilla/PR58.java
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+import java.io.*;
+
+public class PR58 extends TestCase {
+    public static void main(String[] args) {
+        TestRunner.run(suite());
+    }
+
+    public static Test suite() {
+        return new TestSuite(PR58.class);
+    }
+
+    class x extends y {}
+    class y {}
+
+    public void test() {
+        // Delete the class file which is extended.
+        new File("PR58$y.class").delete();
+
+        try {
+            Class.forName("PR58$x");
+            fail("Should throw NoClassDefFoundError");
+        }
+        catch (ClassNotFoundException error) {
+            fail("Unexpected exception: " + error);
+        }
+        catch (NoClassDefFoundError success) {
+            // Check if the cause is correct.
+            assertTrue(success.getCause() instanceof ClassNotFoundException);
+        }
+    }
+}