-
Notifications
You must be signed in to change notification settings - Fork 380
Description
Tests executes through JPF fails with ClassInfoException when running under Java 9/10.
Example: Running gov.nasa.jpf.test.basic.HarnessTest
[junit] gov.nasa.jpf.vm.ClassInfoException: class not found: java.io.Serializable
[junit] at gov.nasa.jpf.vm.ClassLoaderInfo.getResolvedClassInfo(ClassLoaderInfo.java:363)
[junit] at gov.nasa.jpf.vm.SystemClassLoaderInfo.getResolvedClassInfo(SystemClassLoaderInfo.java:147)
[junit] at gov.nasa.jpf.vm.SystemClassLoaderInfo.loadClass(SystemClassLoaderInfo.java:182)
[junit] at gov.nasa.jpf.vm.ClassInfo.resolveReferencedClass(ClassInfo.java:2414)
[junit] at gov.nasa.jpf.vm.ClassInfo.loadInterfaces(ClassInfo.java:2366)
[junit] at gov.nasa.jpf.vm.ClassInfo.resolveClass(ClassInfo.java:2383)
[junit] at gov.nasa.jpf.vm.ClassInfo.resolveAndLink(ClassInfo.java:548)
[junit] at gov.nasa.jpf.jvm.JVMClassInfo.<init>(JVMClassInfo.java:624)
[junit] at gov.nasa.jpf.jvm.JVMClassFileContainer$JVMClassFileMatch.createClassInfo(JVMClassFileContainer.java:58)
[junit] at gov.nasa.jpf.jvm.JVMClassFileContainer$JVMClassFileMatch.createClassInfo(JVMClassFileContainer.java:33)
[junit] at gov.nasa.jpf.vm.ClassLoaderInfo.getResolvedClassInfo(ClassLoaderInfo.java:353)
[junit] at gov.nasa.jpf.vm.SystemClassLoaderInfo.getResolvedClassInfo(SystemClassLoaderInfo.java:147)
[junit] at gov.nasa.jpf.vm.VM.getStartupSystemClassInfos(VM.java:445)
[junit] at gov.nasa.jpf.vm.VM.initializeMainThread(VM.java:564)
[junit] at gov.nasa.jpf.vm.SingleProcessVM.initialize(SingleProcessVM.java:130)
[junit] at gov.nasa.jpf.JPF.run(JPF.java:611)
[junit] at gov.nasa.jpf.util.test.TestJPF.createAndRunJPF(TestJPF.java:675)
[junit] at gov.nasa.jpf.util.test.TestJPF.unhandledException(TestJPF.java:849)
[junit] at gov.nasa.jpf.util.test.TestJPF.verifyUnhandledException(TestJPF.java:903)
[junit] at gov.nasa.jpf.test.basic.HarnessTest.verifyNullPointerException(HarnessTest.java:54)
ClassInfoException is thrown in here:
jpf-core/src/main/gov/nasa/jpf/vm/ClassLoaderInfo.java
Lines 316 to 372 in 18a0c42
| /** | |
| * obtain ClassInfo object for given class name | |
| * | |
| * if the requested class or any of its superclasses and interfaces | |
| * is not found this method will throw a ClassInfoException. Loading | |
| * of respective superclasses and interfaces happens recursively from here. | |
| * | |
| * Returned ClassInfo objects are not registered yet, i.e. still have to | |
| * be added to the ClassLoaderInfo's statics, and don't have associated java.lang.Class | |
| * objects until registerClass(ti) is called. | |
| * | |
| * Before any field or method access, the class also has to be initialized, | |
| * which can include overlayed execution of <clinit> declaredMethods, which is done | |
| * by calling initializeClass(ti,insn) | |
| * | |
| * this is for loading classes from the file system | |
| */ | |
| public ClassInfo getResolvedClassInfo (String className) throws ClassInfoException { | |
| String typeName = Types.getClassNameFromTypeName( className); | |
| ClassInfo ci = resolvedClasses.get( typeName); | |
| if (ci == null) { | |
| if (ClassInfo.isBuiltinClass( typeName)){ | |
| ci = loadSystemClass( typeName); | |
| } else { | |
| ClassFileMatch match = getMatch( typeName); | |
| if (match != null){ | |
| String url = match.getClassURL(); | |
| ci = loadedClasses.get( url); // have we loaded the class from this source before | |
| if (ci != null){ | |
| if (ci.getClassLoaderInfo() != this){ // might have been loaded by another classloader | |
| ci = ci.cloneFor(this); | |
| } | |
| } else { | |
| try { | |
| log.info("loading class ", typeName, " from ", url); | |
| ci = match.createClassInfo(this); | |
| } catch (ClassParseException cpx){ | |
| throw new ClassInfoException( "error parsing class", this, "java.lang.NoClassDefFoundError", typeName, cpx); | |
| } | |
| loadedClasses.put( url, ci); | |
| } | |
| } else { // no match found | |
| throw new ClassInfoException("class not found: " + typeName, this, "java.lang.ClassNotFoundException", typeName); | |
| } | |
| } | |
| setAttributes(ci); | |
| resolvedClasses.put(typeName, ci); | |
| } | |
| return ci; | |
| } |
Possible causes
As stated in the JDK 9 Release Notes the system property sun.boot.class.path has been removed. This makes JPF to fail resolve standard Java classes.
jpf-core/src/main/gov/nasa/jpf/vm/ClassInfo.java
Lines 1676 to 1680 in 18a0c42
| // finally, we load from the standard Java libraries | |
| v = System.getProperty("sun.boot.class.path"); | |
| if (v != null) { | |
| buf.append(v); | |
| } |
References
http://www.oracle.com/technetwork/java/javase/9-relnote-issues-3704069.html
https://stackoverflow.com/q/50451536/3647002
Implementation for the class URL generation would also need to be updated.
jpf-core/src/main/gov/nasa/jpf/jvm/JVMClassFileContainer.java
Lines 74 to 77 in a9bc908
| @Override | |
| public String getClassURL (String typeName){ | |
| return getURL() + typeName.replace('.', '/') + ".class"; | |
| } |
In the earlier versions path to standard class would be like:
jar:file:/path/to/jjre/lib/rt.jar!/java/lang/Object.class
With the module system:
jrt:/java.base/java/lang/Object.class