Allow for classes with missing superclasses in class hierarchy (#329)
Fixes #322 We add an option `createPhantomSuperclasses` to `ClassHierarchy`. When set, if a superclass is missing, we create a new `PhantomClass` in its place and allow the subclass to be added. To use, you can create the `ClassHierarchy` with the new `ClassHierarchyFactory.makeWithPhantom` methods.
This commit is contained in:
parent
5edf49254c
commit
aeb17dfca4
|
@ -0,0 +1 @@
|
|||
!/*.class
|
Binary file not shown.
|
@ -0,0 +1,65 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.core.tests.cha;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.core.tests.util.WalaTestCase;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCacheImpl;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.IAnalysisCacheView;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyFactory;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
import com.ibm.wala.util.io.FileProvider;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class MissingSuperTest extends WalaTestCase {
|
||||
|
||||
/**
|
||||
* Test handling of an invalid class where a non-abstract method has no code.
|
||||
* We want to throw an exception rather than crash.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
@Test
|
||||
public void testMissingSuper() throws IOException, ClassHierarchyException {
|
||||
AnalysisScope scope = AnalysisScopeReader.readJavaScope(TestConstants.WALA_TESTDATA,
|
||||
(new FileProvider()).getFile("J2SEClassHierarchyExclusions.txt"), DupFieldsTest.class.getClassLoader());
|
||||
TypeReference ref = TypeReference.findOrCreate(ClassLoaderReference.Application,
|
||||
"Lmissingsuper/MissingSuper");
|
||||
// without phantom classes, won't be able to resolve
|
||||
ClassHierarchy cha = ClassHierarchyFactory.make(scope);
|
||||
Assert.assertNull("lookup should not work", cha.lookupClass(ref));
|
||||
// with phantom classes, lookup and IR construction should work
|
||||
cha = ClassHierarchyFactory.makeWithPhantom(scope);
|
||||
IClass klass = cha.lookupClass(ref);
|
||||
Assert.assertNotNull("expected class MissingSuper to load", klass);
|
||||
IAnalysisCacheView cache = new AnalysisCacheImpl();
|
||||
Collection<? extends IMethod> declaredMethods = klass.getDeclaredMethods();
|
||||
Assert.assertEquals(declaredMethods.toString(), 2, declaredMethods.size());
|
||||
for (IMethod m : declaredMethods) {
|
||||
// should succeed
|
||||
cache.getIR(m);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -296,11 +296,16 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
|||
computeSuperclass();
|
||||
}
|
||||
if (superClass == null && !getReference().equals(TypeReference.JavaLangObject)) {
|
||||
throw new IllegalStateException("No superclass found for " + this + " Superclass name " + superName);
|
||||
throw new NoSuperclassFoundException("No superclass found for " + this + " Superclass name " + superName);
|
||||
}
|
||||
return superClass;
|
||||
}
|
||||
|
||||
public TypeName getSuperName() {
|
||||
return TypeName.findOrCreate(superName);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllFields()
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.ibm.wala.classLoader;
|
||||
|
||||
/**
|
||||
* Indicates the superclass for a class was not found in the
|
||||
* {@link com.ibm.wala.ipa.callgraph.AnalysisScope}
|
||||
*/
|
||||
public class NoSuperclassFoundException extends RuntimeException {
|
||||
|
||||
static final long serialVersionUID = 333L;
|
||||
|
||||
public NoSuperclassFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* dummy class representing a missing superclass
|
||||
*/
|
||||
public class PhantomClass extends SyntheticClass {
|
||||
|
||||
/**
|
||||
* @param T type reference describing this class
|
||||
* @param cha
|
||||
*/
|
||||
public PhantomClass(TypeReference T, IClassHierarchy cha) {
|
||||
super(T, cha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrivate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModifiers() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClass getSuperclass() {
|
||||
return getClassHierarchy().getRootClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends IClass> getDirectInterfaces() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IClass> getAllImplementedInterfaces() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMethod getMethod(Selector selector) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IField getField(Atom name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMethod getClassInitializer() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends IMethod> getDeclaredMethods() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllInstanceFields() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllStaticFields() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllFields() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends IMethod> getAllMethods() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReferenceType() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -10,31 +10,23 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.cha;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.ibm.wala.classLoader.ArrayClass;
|
||||
import com.ibm.wala.classLoader.BytecodeClass;
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.classLoader.NoSuperclassFoundException;
|
||||
import com.ibm.wala.classLoader.PhantomClass;
|
||||
import com.ibm.wala.classLoader.ShrikeClass;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
@ -51,6 +43,18 @@ import com.ibm.wala.util.strings.Atom;
|
|||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.Warnings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Simple implementation of a class hierarchy.
|
||||
*
|
||||
|
@ -132,6 +136,13 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
*/
|
||||
private Collection<TypeReference> runtimeExceptionTypeRefs;
|
||||
|
||||
/**
|
||||
* when a superclass is missing, should we create a phantom superclass and add the subclass to
|
||||
* the hierarchy? Note that we can only create phantom superclass when the class is a
|
||||
* {@link com.ibm.wala.classLoader.BytecodeClass}
|
||||
*/
|
||||
private final boolean createPhantomSuperclasses;
|
||||
|
||||
/**
|
||||
* Return a set of {@link IClass} that holds all superclasses of klass
|
||||
*
|
||||
|
@ -145,44 +156,60 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
|
||||
Set<IClass> result = HashSetFactory.make(3);
|
||||
|
||||
klass = klass.getSuperclass();
|
||||
|
||||
while (klass != null) {
|
||||
if (DEBUG) {
|
||||
System.err.println("got superclass " + klass);
|
||||
}
|
||||
boolean added = result.add(klass);
|
||||
if (!added) {
|
||||
// oops. we have A is a sub-class of B and B is a sub-class of A. blow up.
|
||||
throw new IllegalStateException("cycle in the extends relation for class " + klass);
|
||||
}
|
||||
try {
|
||||
klass = klass.getSuperclass();
|
||||
if (klass != null && klass.getReference().getName().equals(rootTypeRef.getName())) {
|
||||
if (!klass.getReference().getClassLoader().equals(rootTypeRef.getClassLoader())) {
|
||||
throw new IllegalStateException("class " + klass + " is invalid, unexpected classloader");
|
||||
|
||||
while (klass != null) {
|
||||
if (DEBUG) {
|
||||
System.err.println("got superclass " + klass);
|
||||
}
|
||||
boolean added = result.add(klass);
|
||||
if (!added) {
|
||||
// oops. we have A is a sub-class of B and B is a sub-class of A. blow up.
|
||||
throw new IllegalStateException("cycle in the extends relation for class " + klass);
|
||||
}
|
||||
klass = klass.getSuperclass();
|
||||
if (klass != null && klass.getReference().getName().equals(rootTypeRef.getName())) {
|
||||
if (!klass.getReference().getClassLoader().equals(rootTypeRef.getClassLoader())) {
|
||||
throw new IllegalStateException("class " + klass + " is invalid, unexpected classloader");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NoSuperclassFoundException e) {
|
||||
if (createPhantomSuperclasses && klass instanceof BytecodeClass) {
|
||||
// create a phantom superclass. add it and the root class to the result
|
||||
IClass phantom = getPhantomSuperclass((BytecodeClass) klass);
|
||||
result.add(phantom);
|
||||
result.add(getRootClass());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, Language language, IProgressMonitor progressMonitor, Map<TypeReference, Node> map)
|
||||
ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, Language language,
|
||||
IProgressMonitor progressMonitor, Map<TypeReference, Node> map, boolean createPhantomSuperclasses)
|
||||
throws ClassHierarchyException, IllegalArgumentException {
|
||||
this(scope, factory, Collections.singleton(language), progressMonitor, map);
|
||||
this(scope, factory, Collections.singleton(language), progressMonitor, map,
|
||||
createPhantomSuperclasses);
|
||||
}
|
||||
|
||||
ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor progressMonitor, Map<TypeReference, Node> map)
|
||||
ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor
|
||||
progressMonitor, Map<TypeReference, Node> map, boolean createPhantomSuperclasses)
|
||||
throws ClassHierarchyException, IllegalArgumentException {
|
||||
this(scope, factory, scope.getLanguages(), progressMonitor, map);
|
||||
this(scope, factory, scope.getLanguages(), progressMonitor, map, createPhantomSuperclasses);
|
||||
}
|
||||
|
||||
ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, Collection<Language> languages,
|
||||
IProgressMonitor progressMonitor, Map<TypeReference, Node> map) throws ClassHierarchyException, IllegalArgumentException {
|
||||
IProgressMonitor progressMonitor, Map<TypeReference, Node> map, boolean createPhantomSuperclasses) throws
|
||||
ClassHierarchyException, IllegalArgumentException {
|
||||
// now is a good time to clear the warnings globally.
|
||||
// TODO: think of a better way to guard against warning leaks.
|
||||
Warnings.clear();
|
||||
|
||||
this.map = map;
|
||||
this.createPhantomSuperclasses = createPhantomSuperclasses;
|
||||
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException();
|
||||
|
@ -307,20 +334,26 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
if (DEBUG) {
|
||||
System.err.println(("Attempt to add class " + klass));
|
||||
}
|
||||
Set<IClass> loadedSuperclasses;
|
||||
Set<IClass> loadedSuperclasses = null;
|
||||
Collection<IClass> loadedSuperInterfaces;
|
||||
try {
|
||||
loadedSuperclasses = computeSuperclasses(klass);
|
||||
loadedSuperInterfaces = klass.getAllImplementedInterfaces();
|
||||
} catch (Exception e) {
|
||||
// a little cleanup
|
||||
if (klass instanceof ShrikeClass) {
|
||||
if (DEBUG) {
|
||||
System.err.println(("Exception. Clearing " + klass));
|
||||
if (createPhantomSuperclasses && e instanceof NoSuperclassFoundException) {
|
||||
// this must have been thrown by the getAllImplementedInterfaces() call.
|
||||
// for now, just pretend it implements no interfaces
|
||||
loadedSuperInterfaces = Collections.emptySet();
|
||||
} else {
|
||||
// a little cleanup
|
||||
if (klass instanceof ShrikeClass) {
|
||||
if (DEBUG) {
|
||||
System.err.println(("Exception. Clearing " + klass));
|
||||
}
|
||||
}
|
||||
Warnings.add(ClassExclusion.create(klass.getReference(), e.getMessage()));
|
||||
return false;
|
||||
}
|
||||
Warnings.add(ClassExclusion.create(klass.getReference(), e.getMessage()));
|
||||
return false;
|
||||
}
|
||||
Node node = findOrCreateNode(klass);
|
||||
|
||||
|
@ -333,8 +366,13 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
Set workingSuperclasses = HashSetFactory.make(loadedSuperclasses);
|
||||
while (node != null) {
|
||||
IClass c = node.getJavaClass();
|
||||
IClass superclass = null;
|
||||
superclass = c.getSuperclass();
|
||||
IClass superclass;
|
||||
try {
|
||||
superclass = c.getSuperclass();
|
||||
} catch (NoSuperclassFoundException e) {
|
||||
assert createPhantomSuperclasses;
|
||||
superclass = getPhantomSuperclass((BytecodeClass) c);
|
||||
}
|
||||
if (superclass != null) {
|
||||
workingSuperclasses.remove(superclass);
|
||||
Node supernode = findOrCreateNode(superclass);
|
||||
|
@ -381,6 +419,18 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
return true;
|
||||
}
|
||||
|
||||
private IClass getPhantomSuperclass(BytecodeClass klass) {
|
||||
ClassLoaderReference loader = klass.getReference().getClassLoader();
|
||||
TypeName superName = klass.getSuperName();
|
||||
TypeReference superRef = TypeReference.findOrCreate(loader, superName);
|
||||
IClass superClass = lookupClass(superRef);
|
||||
if (superClass == null) {
|
||||
superClass = new PhantomClass(superRef, this);
|
||||
addClass(superClass);
|
||||
}
|
||||
return superClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that a klass implements a particular interface
|
||||
*/
|
||||
|
|
|
@ -10,17 +10,15 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.cha;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactoryImpl;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy.Node;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ClassHierarchyFactory {
|
||||
|
||||
/**
|
||||
|
@ -34,6 +32,19 @@ public class ClassHierarchyFactory {
|
|||
return make(scope, new ClassLoaderFactoryImpl(scope.getExclusions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a ClassHierarchy object representing the analysis scope, where phantom classes are
|
||||
* created when superclasses are missing
|
||||
*
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
public static ClassHierarchy makeWithPhantom(AnalysisScope scope) throws ClassHierarchyException {
|
||||
if (scope == null) {
|
||||
throw new IllegalArgumentException("null scope");
|
||||
}
|
||||
return makeWithPhantom(scope, new ClassLoaderFactoryImpl(scope.getExclusions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* temporarily marking this internal to avoid infinite sleep with randomly chosen IProgressMonitor.
|
||||
*/
|
||||
|
@ -45,31 +56,41 @@ public class ClassHierarchyFactory {
|
|||
}
|
||||
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory) throws ClassHierarchyException {
|
||||
return make(scope, factory, false);
|
||||
}
|
||||
|
||||
private static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, boolean
|
||||
createPhantomSuperclasses) throws ClassHierarchyException {
|
||||
if (scope == null) {
|
||||
throw new IllegalArgumentException("null scope");
|
||||
}
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("null factory");
|
||||
}
|
||||
return new ClassHierarchy(scope, factory, null, new ConcurrentHashMap<TypeReference, Node>());
|
||||
return new ClassHierarchy(scope, factory, null, new ConcurrentHashMap<>(),
|
||||
createPhantomSuperclasses);
|
||||
}
|
||||
|
||||
public static ClassHierarchy makeWithPhantom(AnalysisScope scope, ClassLoaderFactory factory)
|
||||
throws ClassHierarchyException {
|
||||
return make(scope, factory, true);
|
||||
}
|
||||
/**
|
||||
* temporarily marking this internal to avoid infinite sleep with randomly chosen IProgressMonitor.
|
||||
*/
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor monitor)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, monitor, new ConcurrentHashMap<TypeReference, Node>());
|
||||
return new ClassHierarchy(scope, factory, monitor, new ConcurrentHashMap<>(), false);
|
||||
}
|
||||
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Set<Language> languages)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, languages, null, new ConcurrentHashMap<TypeReference, Node>());
|
||||
return new ClassHierarchy(scope, factory, languages, null, new ConcurrentHashMap<>(), false);
|
||||
}
|
||||
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Language language)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, language, null, new ConcurrentHashMap<TypeReference, Node>());
|
||||
return new ClassHierarchy(scope, factory, language, null, new ConcurrentHashMap<>(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,7 +101,7 @@ public class ClassHierarchyFactory {
|
|||
if (factory == null) {
|
||||
throw new IllegalArgumentException("null factory");
|
||||
}
|
||||
return new ClassHierarchy(scope, factory, language, monitor, new ConcurrentHashMap<TypeReference, Node>());
|
||||
return new ClassHierarchy(scope, factory, language, monitor, new ConcurrentHashMap<>(), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,17 +10,15 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.cha;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactoryImpl;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy.Node;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SeqClassHierarchyFactory {
|
||||
|
||||
/**
|
||||
|
@ -51,7 +49,8 @@ public class SeqClassHierarchyFactory {
|
|||
if (factory == null) {
|
||||
throw new IllegalArgumentException("null factory");
|
||||
}
|
||||
return new ClassHierarchy(scope, factory, null, HashMapFactory.<TypeReference, Node>make());
|
||||
return new ClassHierarchy(scope, factory, null, HashMapFactory.make(),
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,17 +58,17 @@ public class SeqClassHierarchyFactory {
|
|||
*/
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor monitor)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, monitor, HashMapFactory.<TypeReference, Node>make());
|
||||
return new ClassHierarchy(scope, factory, monitor, HashMapFactory.make(), false);
|
||||
}
|
||||
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Set<Language> languages)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, languages, null, HashMapFactory.<TypeReference, Node>make());
|
||||
return new ClassHierarchy(scope, factory, languages, null, HashMapFactory.make(), false);
|
||||
}
|
||||
|
||||
public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Language language)
|
||||
throws ClassHierarchyException {
|
||||
return new ClassHierarchy(scope, factory, language, null, HashMapFactory.<TypeReference, Node>make());
|
||||
return new ClassHierarchy(scope, factory, language, null, HashMapFactory.make(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,7 +79,7 @@ public class SeqClassHierarchyFactory {
|
|||
if (factory == null) {
|
||||
throw new IllegalArgumentException("null factory");
|
||||
}
|
||||
return new ClassHierarchy(scope, factory, language, monitor, HashMapFactory.<TypeReference, Node>make());
|
||||
return new ClassHierarchy(scope, factory, language, monitor, HashMapFactory.make(), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue