`ClassHierarchyFactory.makeWithRoot` fails when analyzing source code without dependencies
Calling code (Kotlin) that runs on the WALA-start repository:
fun main(args: Array<String>) {
val sourceDir = File("/path/to/WALA-start/src/main/java")
val scope = JavaSourceAnalysisScope()
scope.addToScope(JavaSourceAnalysisScope.SOURCE, SourceDirectoryTreeModule(sourceDir))
val jreDir = File("/usr/lib/jvm/java-17-openjdk/jmods")
jreDir.list()?.forEach {
if (it.endsWith(".jmod")) {
scope.addToScope(ClassLoaderReference.Primordial, JarFile(File(jreDir, it)))
}
}
val cha = ClassHierarchyFactory.makeWithRoot(scope, ECJClassLoaderFactory(scope.exclusions))
}
Exception in thread "main" com.ibm.wala.ipa.cha.ClassHierarchyException: factory.getLoader failed
at com.ibm.wala.ipa.cha.ClassHierarchy.<init>(ClassHierarchy.java:291)
at com.ibm.wala.ipa.cha.ClassHierarchy.<init>(ClassHierarchy.java:203)
at com.ibm.wala.ipa.cha.ClassHierarchyFactory.make(ClassHierarchyFactory.java:85)
at com.ibm.wala.ipa.cha.ClassHierarchyFactory.makeWithRoot(ClassHierarchyFactory.java:95)
at MainKt.main(Main.kt:25)
Caused by: java.lang.NullPointerException: Cannot invoke "org.eclipse.jdt.core.dom.ITypeBinding.getDeclaredMethods()" because "superClass" is null
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.findDefaultCtor(JDTJava2CAstTranslator.java:707)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.createConstructorBody(JDTJava2CAstTranslator.java:767)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visit(JDTJava2CAstTranslator.java:899)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.createClassDeclaration(JDTJava2CAstTranslator.java:527)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visitTypeDecl(JDTJava2CAstTranslator.java:434)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visit(JDTJava2CAstTranslator.java:3777)
at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.translateToCAst(JDTJava2CAstTranslator.java:273)
at com.ibm.wala.cast.java.translator.jdt.ecj.ECJSourceModuleTranslator$ECJAstToIR.acceptAST(ECJSourceModuleTranslator.java:158)
at org.eclipse.jdt.core.dom.CompilationUnitResolver.resolve(CompilationUnitResolver.java:1065)
at org.eclipse.jdt.core.dom.CompilationUnitResolver.resolve(CompilationUnitResolver.java:661)
at org.eclipse.jdt.core.dom.ASTParser.createASTs(ASTParser.java:1049)
at com.ibm.wala.cast.java.translator.jdt.ecj.ECJSourceModuleTranslator.loadAllSources(ECJSourceModuleTranslator.java:258)
at com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.loadAllSources(JavaSourceLoaderImpl.java:599)
at com.ibm.wala.classLoader.ClassLoaderImpl.init(ClassLoaderImpl.java:506)
at com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.init(JavaSourceLoaderImpl.java:608)
at com.ibm.wala.cast.java.translator.jdt.ecj.ECJClassLoaderFactory.makeNewClassLoader(ECJClassLoaderFactory.java:31)
at com.ibm.wala.classLoader.ClassLoaderFactoryImpl.getLoader(ClassLoaderFactoryImpl.java:61)
at com.ibm.wala.ipa.cha.ClassHierarchy.<init>(ClassHierarchy.java:270)
... 4 more
The failure seems to be related to classes in WALA-start that extends types found in the WALA project, which are not included in the scope (for now), but makeWithRoot should be able to handle this according to #591 (makeWithPhantom is actually a better fit for my project, but it seems to be incomplete?).
Is this NPE a bug, or is it actually impossible to work with the source frontend without dependencies?
Hey, I think this is probably related to https://github.com/wala/WALA/issues/99. Unfortunately, JDT, and hence the WALA source frontend, is not robust to missing classes, even if the WALA ClassHierarchy is. I don't know of a workaround (though maybe @juliandolby or @linghuiluo does). Alternately, if you can analyze bytecodes rather than source code, things should be more robust.