Moving recursive lookup for defineClass0 just in the native method itself; messing...
authorrtrimana <rtrimana@uci.edu>
Fri, 5 Jul 2019 19:01:56 +0000 (12:01 -0700)
committerrtrimana <rtrimana@uci.edu>
Fri, 5 Jul 2019 19:01:56 +0000 (12:01 -0700)
src/main/gov/nasa/jpf/vm/ClassLoaderInfo.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_ClassLoader.java
src/tests/gov/nasa/jpf/test/java/lang/ClassLoaderTest.java

index 63c3c88..b328587 100644 (file)
@@ -360,13 +360,7 @@ public class ClassLoaderInfo
           }
 
         } else { // no match found
-          // TODO: Fix for Groovy's model-checking
-          // TODO: May need to do a recursive lookup
-          if (parent != null) {
-            return parent.getResolvedClassInfo(typeName);
-          } else {
-            throw new ClassInfoException("class not found: " + typeName, this, "java.lang.ClassNotFoundException", typeName);
-          }
+          throw new ClassInfoException("class not found: " + typeName, this, "java.lang.ClassNotFoundException", typeName);
         }
       }
       
@@ -591,11 +585,6 @@ public class ClassLoaderInfo
           }          
         }
       }
-      // TODO: Fix for Groovy's model-checking
-      // TODO: May need to do a recursive lookup
-      if (parent != null) {
-        return parent.loadClass(typeName);
-      }
 
       // initiate the roundtrip & bail out
       pushloadClassFrame(typeName);
index 98a8dd4..25a1dcf 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
index 5e164fc..5899d2b 100644 (file)
@@ -6,13 +6,13 @@
  * The Java Pathfinder core (jpf-core) platform is licensed under the
  * Apache License, Version 2.0 (the "License"); you may not use this file except
  * in compliance with the License. You may obtain a copy of the License at
- * 
- *        http://www.apache.org/licenses/LICENSE-2.0. 
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0.
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and 
+ * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package gov.nasa.jpf.test.java.lang;
@@ -30,7 +30,7 @@ import org.junit.Test;
  * test of java.lang.ClassLoader API
  */
 public class ClassLoaderTest extends TestJPF {
-  
+
   @Test
   public void testGetResource() {
     if(verifyNoPropertyViolation()) {
@@ -128,7 +128,7 @@ public class ClassLoaderTest extends TestJPF {
   public void testFoundResources() throws IOException {
     if(verifyNoPropertyViolation()) {
       TestClassLoader classLoader = new TestClassLoader();
-      Enumeration<URL> enm = classLoader.findResources("not_existing_resource"); 
+      Enumeration<URL> enm = classLoader.findResources("not_existing_resource");
       assertNotNull(enm);
       assertFalse(enm.hasMoreElements());
     }
@@ -168,7 +168,7 @@ public class ClassLoaderTest extends TestJPF {
   }
 
   class TestClassLoader extends ClassLoader {
-      
+
     public TestClassLoader() {
       super();
     }
@@ -178,8 +178,8 @@ public class ClassLoaderTest extends TestJPF {
     }
 
     @Override
-       protected Enumeration<URL> findResources(String name) throws IOException {
+    protected Enumeration<URL> findResources(String name) throws IOException {
       return super.findResources(name);
     }
   }
-}
+}
\ No newline at end of file