01 /**
02 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03 */
04 package net.sourceforge.pmd.lang.java.typeresolution;
05
06 import java.io.IOException;
07 import java.util.ArrayList;
08 import java.util.HashSet;
09 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import net.sourceforge.pmd.lang.java.typeresolution.visitors.PMDASMVisitor;
14
15 import org.objectweb.asm.ClassReader;
16
17 /*
18 * I've refactored this class to not cache the results any more. This is a
19 * tradeoff in testing I've found the CPU tradeoff is negligeable. With the
20 * cache, large codebases consumed a lot of memory and slowed down greatly when
21 * approaching 3,000 classes. I'm adding this comment in case someone is looking
22 * at this code and thinks a cache may help.
23 */
24 public class PMDASMClassLoader extends ClassLoader {
25
26 public PMDASMClassLoader(ClassLoader parent) {
27 super(parent);
28 }
29
30 private Set<String> dontBother = new HashSet<String>();
31
32 public synchronized Map<String, String> getImportedClasses(String name) throws ClassNotFoundException {
33
34 if (dontBother.contains(name)) {
35 throw new ClassNotFoundException(name);
36 }
37 try {
38 ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
39 PMDASMVisitor asmVisitor = new PMDASMVisitor();
40 reader.accept(asmVisitor, 0);
41
42 List<String> inner = asmVisitor.getInnerClasses();
43 if (inner != null && !inner.isEmpty()) {
44 inner = new ArrayList<String>(inner); // to avoid ConcurrentModificationException
45 for (String str: inner) {
46 reader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
47 reader.accept(asmVisitor, 0);
48 }
49 }
50 return asmVisitor.getPackages();
51 } catch (IOException e) {
52 dontBother.add(name);
53 throw new ClassNotFoundException(name, e);
54 }
55 }
56 }
|