forked from phoedos/pmd
I've refactored this class to not cache the results any more. This is a
tradeoff in testing I've found the CPU tradeoff is negligeable. With the cache, large codebases consumed a lot of memory and slowed down greatly when approaching 3,000 classes. Also fixes some false positives. git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4892 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
@ -6,71 +6,49 @@ package net.sourceforge.pmd.typeresolution;
|
||||
import net.sourceforge.pmd.typeresolution.visitors.PMDASMVisitor;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
* I've refactored this class to not cache the results any more. This is a
|
||||
* tradeoff in testing I've found the CPU tradeoff is negligeable. With the
|
||||
* cache, large codebases consumed a lot of memory and slowed down greatly when
|
||||
* approaching 3,000 classes. I'm adding this comment in case someone is looking
|
||||
* at this code and thinks a cache may help.
|
||||
*/
|
||||
public class PMDASMClassLoader extends ClassLoader {
|
||||
|
||||
public PMDASMClassLoader() {
|
||||
}
|
||||
public PMDASMClassLoader() {
|
||||
}
|
||||
|
||||
public synchronized Class loadClass(String name) throws ClassNotFoundException {
|
||||
return defineClass(name);
|
||||
}
|
||||
private Set dontBother = new HashSet();
|
||||
|
||||
private Map importedClasses = new HashMap();
|
||||
public Map getImportedClasses(String name) throws ClassNotFoundException {
|
||||
|
||||
private Set dontBother = new HashSet();
|
||||
if (dontBother.contains(name)) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
try {
|
||||
ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
|
||||
PMDASMVisitor asmVisitor = new PMDASMVisitor();
|
||||
reader.accept(asmVisitor, 0);
|
||||
|
||||
public Map getImportedClasses(String className) {
|
||||
Map ret = (Map) importedClasses.get(className);
|
||||
return ret == null ? new HashMap() : ret;
|
||||
}
|
||||
|
||||
private Class defineClass(String name) throws ClassNotFoundException {
|
||||
|
||||
if (dontBother.contains(name)) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
try {
|
||||
if (name.startsWith("java.")) {
|
||||
return Class.forName(name);
|
||||
}
|
||||
if (importedClasses.containsKey(name)) {
|
||||
if (super.findLoadedClass(name) != null) {
|
||||
return super.findLoadedClass(name);
|
||||
}
|
||||
}
|
||||
ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
|
||||
PMDASMVisitor asmVisitor = new PMDASMVisitor();
|
||||
reader.accept(asmVisitor, 0);
|
||||
|
||||
List inner = asmVisitor.getInnerClasses();
|
||||
if (inner != null && !inner.isEmpty()) {
|
||||
for (int ix = 0; ix < inner.size(); ix++) {
|
||||
String str = (String) inner.get(ix);
|
||||
ClassReader innerReader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
|
||||
innerReader.accept(asmVisitor, 0);
|
||||
}
|
||||
}
|
||||
importedClasses.put(name, asmVisitor.getPackages());
|
||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
reader.accept(writer, 0);
|
||||
|
||||
byte[] byteCode = writer.toByteArray();
|
||||
return defineClass(name, byteCode, 0, byteCode.length);
|
||||
} catch (ClassNotFoundException e) {
|
||||
dontBother.add(name);
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
dontBother.add(name);
|
||||
throw new ClassNotFoundException(name, e);
|
||||
}
|
||||
}
|
||||
List inner = asmVisitor.getInnerClasses();
|
||||
if (inner != null && !inner.isEmpty()) {
|
||||
for (int ix = 0; ix < inner.size(); ix++) {
|
||||
String str = (String) inner.get(ix);
|
||||
reader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
|
||||
reader.accept(asmVisitor, 0);
|
||||
}
|
||||
}
|
||||
return asmVisitor.getPackages();
|
||||
} catch (IOException e) {
|
||||
dontBother.add(name);
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user