+ remove class definitions for sticking around (by forcing eager metadata initialization)
+ improve cache size by eliminating the numbers of method metadata objects created
+ improve lookup access on method metadata
This commit is contained in:
Costin Leau 2010-01-29 14:27:49 +00:00
parent 39f81760f8
commit ee2b1cde82
4 changed files with 46 additions and 56 deletions

View File

@ -19,6 +19,7 @@ package org.springframework.core.type.classreading;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -27,6 +28,9 @@ import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Type; import org.springframework.asm.Type;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/** /**
* ASM class visitor which looks for the class name and implemented types as * ASM class visitor which looks for the class name and implemented types as
@ -35,6 +39,7 @@ import org.springframework.core.type.MethodMetadata;
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Mark Fisher * @author Mark Fisher
* @author Costin Leau
* @since 2.5 * @since 2.5
*/ */
final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata {
@ -43,12 +48,11 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
private final Set<String> annotationSet = new LinkedHashSet<String>(); private final Set<String> annotationSet = new LinkedHashSet<String>();
private final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(); private final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(4);
private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>(); private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>(4);
private final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>();
private final MultiValueMap<String, MethodMetadata> methodMetadataMap = new LinkedMultiValueMap<String, MethodMetadata>();
public AnnotationMetadataReadingVisitor(ClassLoader classLoader) { public AnnotationMetadataReadingVisitor(ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
@ -57,9 +61,7 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
@Override @Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodMetadataReadingVisitor mm = new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader); return new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader, methodMetadataMap);
this.methodMetadataSet.add(mm);
return mm;
} }
@Override @Override
@ -132,22 +134,16 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
} }
public boolean hasAnnotatedMethods(String annotationType) { public boolean hasAnnotatedMethods(String annotationType) {
for (MethodMetadata method : this.methodMetadataSet) { return methodMetadataMap.containsKey(annotationType);
if (method.isAnnotated(annotationType)) {
return true;
}
}
return false;
} }
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) { public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(); List<MethodMetadata> list = methodMetadataMap.get(annotationType);
for (MethodMetadata method : this.methodMetadataSet) { if (CollectionUtils.isEmpty(list)) {
if (method.isAnnotated(annotationType)) { return new LinkedHashSet<MethodMetadata>(0);
annotatedMethods.add(method);
}
} }
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(list.size());
annotatedMethods.addAll(list);
return annotatedMethods; return annotatedMethods;
} }
}
}

View File

@ -25,6 +25,7 @@ import org.springframework.asm.Opcodes;
import org.springframework.asm.Type; import org.springframework.asm.Type;
import org.springframework.asm.commons.EmptyVisitor; import org.springframework.asm.commons.EmptyVisitor;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
import org.springframework.util.MultiValueMap;
/** /**
* ASM method visitor which looks for the annotations defined on the method, * ASM method visitor which looks for the annotations defined on the method,
@ -33,6 +34,7 @@ import org.springframework.core.type.MethodMetadata;
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Mark Pollack * @author Mark Pollack
* @author Costin Leau
* @since 3.0 * @since 3.0
*/ */
final class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata { final class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata {
@ -45,25 +47,27 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method
private final ClassLoader classLoader; private final ClassLoader classLoader;
private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>(); private final MultiValueMap<String, MethodMetadata> methodMetadataMap;
private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>(2);
public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader) { public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader,
MultiValueMap<String, MethodMetadata> methodMetadataMap) {
super(new EmptyVisitor()); super(new EmptyVisitor());
this.name = name; this.name = name;
this.access = access; this.access = access;
this.declaringClassName = declaringClassName; this.declaringClassName = declaringClassName;
this.classLoader = classLoader; this.classLoader = classLoader;
this.methodMetadataMap = methodMetadataMap;
} }
@Override @Override
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
String className = Type.getType(desc).getClassName(); String className = Type.getType(desc).getClassName();
methodMetadataMap.add(className, this);
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader); return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader);
} }
public String getMethodName() { public String getMethodName() {
return this.name; return this.name;
} }
@ -91,5 +95,4 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method
public String getDeclaringClassName() { public String getDeclaringClassName() {
return this.declaringClassName; return this.declaringClassName;
} }
}
}

View File

@ -32,55 +32,42 @@ import org.springframework.core.type.ClassMetadata;
* without effect on users of the <code>core.type</code> package. * without effect on users of the <code>core.type</code> package.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Costin Leau
* @since 2.5 * @since 2.5
*/ */
final class SimpleMetadataReader implements MetadataReader { final class SimpleMetadataReader implements MetadataReader {
private final Resource resource; private final Resource resource;
private final ClassMetadata classMetadata;
private final ClassReader classReader; private final AnnotationMetadata annotationMetadata;
private final ClassLoader classLoader;
private ClassMetadata classMetadata;
private AnnotationMetadata annotationMetadata;
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
this.resource = resource; InputStream is = resource.getInputStream();
InputStream is = this.resource.getInputStream(); ClassReader classReader = null;
try { try {
this.classReader = new ClassReader(is); classReader = new ClassReader(is);
} } finally {
finally {
is.close(); is.close();
} }
this.classLoader = classLoader;
}
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, true);
this.annotationMetadata = visitor;
// (since AnnotationMetadataReader extends ClassMetadataReadingVisitor)
this.classMetadata = visitor;
this.resource = resource;
}
public Resource getResource() { public Resource getResource() {
return this.resource; return this.resource;
} }
public ClassMetadata getClassMetadata() { public ClassMetadata getClassMetadata() {
if (this.classMetadata == null) {
ClassMetadataReadingVisitor visitor = new ClassMetadataReadingVisitor();
this.classReader.accept(visitor, true);
this.classMetadata = visitor;
}
return this.classMetadata; return this.classMetadata;
} }
public AnnotationMetadata getAnnotationMetadata() { public AnnotationMetadata getAnnotationMetadata() {
if (this.annotationMetadata == null) {
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(this.classLoader);
this.classReader.accept(visitor, true);
this.annotationMetadata = visitor;
this.classMetadata = visitor;
}
return this.annotationMetadata; return this.annotationMetadata;
} }
}
}

View File

@ -48,7 +48,8 @@ public class CachingMetadataReaderLeakTest {
@Test @Test
public void testSignificantLoad() throws Exception { public void testSignificantLoad() throws Exception {
URL url = getClass().getResource("/org/springframework/beans/TestBean.class"); // the biggest public class in the JDK (>60k)
URL url = getClass().getResource("/java/awt/Component.class");
assertThat(url, notNullValue()); assertThat(url, notNullValue());
// look at a LOT of items // look at a LOT of items
@ -71,5 +72,8 @@ public class CachingMetadataReaderLeakTest {
MetadataReader reader = mrf.getMetadataReader(resource); MetadataReader reader = mrf.getMetadataReader(resource);
assertThat(reader, notNullValue()); assertThat(reader, notNullValue());
} }
// useful for profiling to take snapshots
//System.in.read();
} }
} }