Moving recursive lookup for defineClass0 just in the native method itself; messing...
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_ClassLoader.java
index 98a8dd4fc124376f5723da41f72b4910f1d59890..25a1dcf1afb58efe08e48687189ce4d9a1f55317 100644 (file)
@@ -128,17 +128,19 @@ public class JPF_java_lang_ClassLoader extends NativePeer {
     return ci.getClassObjectRef();
   }
 
+  // TODO: Fix for Groovy's model-checking
+  // TODO: Load the SystemClassLoader if this ClassLoader fails, but just get it if it is already defined!
+  // TODO: This is needed for sun.reflect.GroovyMagic and some other classes
   @MJI
   public int defineClass0__Ljava_lang_String_2_3BII__Ljava_lang_Class_2 
                                       (MJIEnv env, int objRef, int nameRef, int bufferRef, int offset, int length) {
     String cname = env.getStringObject(nameRef);
     ClassLoaderInfo cl = env.getClassLoaderInfo(objRef);
 
-    // determine whether that the corresponding class is already defined by this 
-    // classloader, if so, this attempt is invalid, and loading throws a LinkageError
+    // determine whether that the corresponding class is already defined by this
+    // classloader, if so, just return the already defined class!
     if (cl.getDefinedClassInfo(cname) != null) {  // attempt to define twice
-      env.throwException("java.lang.LinkageError"); 
-      return MJIEnv.NULL;
+      return cl.getDefinedClassInfo(cname).getClassObjectRef();
     }
         
     byte[] buffer = env.getByteArrayObject(bufferRef);
@@ -154,13 +156,32 @@ public class JPF_java_lang_ClassLoader extends NativePeer {
       ci.registerClass(ti);
 
       return ci.getClassObjectRef();
-      
+
+    } catch (LoadOnJPFRequired rre) {
+      return searchThroughSystemClassLoader(env, objRef, nameRef, bufferRef, offset, length);
+
     } catch (ClassInfoException cix){
+      if (cix.getExceptionClass().equals("java.lang.ClassNotFoundException")) {
+        return searchThroughSystemClassLoader(env, objRef, nameRef, bufferRef, offset, length);
+      }
       env.throwException("java.lang.ClassFormatError");
       return MJIEnv.NULL;
+
     }
   }
 
+  private int searchThroughSystemClassLoader
+          (MJIEnv env, int objRef, int nameRef, int bufferRef, int offset, int length) {
+
+    int sysObjRef = env.getSystemClassLoaderInfo().getClassLoaderObjectRef();
+    if (objRef != sysObjRef) {
+      return defineClass0__Ljava_lang_String_2_3BII__Ljava_lang_Class_2
+              (env, sysObjRef, nameRef, bufferRef, offset, length);
+    }
+    env.throwException("java.lang.ClassNotFoundException");
+    return MJIEnv.NULL;
+  }
+
 
   protected static boolean check(MJIEnv env, String cname, byte[] buffer, int offset, int length) {
     // throw SecurityExcpetion if the package prefix is java