SPR-6775
+ 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:
parent
39f81760f8
commit
ee2b1cde82
|
|
@ -19,6 +19,7 @@ package org.springframework.core.type.classreading;
|
|||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -27,6 +28,9 @@ import org.springframework.asm.MethodVisitor;
|
|||
import org.springframework.asm.Type;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
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
|
||||
|
|
@ -35,6 +39,7 @@ import org.springframework.core.type.MethodMetadata;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Costin Leau
|
||||
* @since 2.5
|
||||
*/
|
||||
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 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 Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>();
|
||||
private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>(4);
|
||||
|
||||
private final MultiValueMap<String, MethodMetadata> methodMetadataMap = new LinkedMultiValueMap<String, MethodMetadata>();
|
||||
|
||||
public AnnotationMetadataReadingVisitor(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
|
|
@ -57,9 +61,7 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
|||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
MethodMetadataReadingVisitor mm = new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader);
|
||||
this.methodMetadataSet.add(mm);
|
||||
return mm;
|
||||
return new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader, methodMetadataMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -132,22 +134,16 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
|||
}
|
||||
|
||||
public boolean hasAnnotatedMethods(String annotationType) {
|
||||
for (MethodMetadata method : this.methodMetadataSet) {
|
||||
if (method.isAnnotated(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return methodMetadataMap.containsKey(annotationType);
|
||||
}
|
||||
|
||||
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
|
||||
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>();
|
||||
for (MethodMetadata method : this.methodMetadataSet) {
|
||||
if (method.isAnnotated(annotationType)) {
|
||||
annotatedMethods.add(method);
|
||||
}
|
||||
List<MethodMetadata> list = methodMetadataMap.get(annotationType);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return new LinkedHashSet<MethodMetadata>(0);
|
||||
}
|
||||
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(list.size());
|
||||
annotatedMethods.addAll(list);
|
||||
return annotatedMethods;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import org.springframework.asm.Opcodes;
|
|||
import org.springframework.asm.Type;
|
||||
import org.springframework.asm.commons.EmptyVisitor;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* 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 Mark Pollack
|
||||
* @author Costin Leau
|
||||
* @since 3.0
|
||||
*/
|
||||
final class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata {
|
||||
|
|
@ -45,25 +47,27 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method
|
|||
|
||||
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());
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.declaringClassName = declaringClassName;
|
||||
this.classLoader = classLoader;
|
||||
this.methodMetadataMap = methodMetadataMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
String className = Type.getType(desc).getClassName();
|
||||
methodMetadataMap.add(className, this);
|
||||
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader);
|
||||
}
|
||||
|
||||
|
||||
public String getMethodName() {
|
||||
return this.name;
|
||||
}
|
||||
|
|
@ -91,5 +95,4 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method
|
|||
public String getDeclaringClassName() {
|
||||
return this.declaringClassName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -32,55 +32,42 @@ import org.springframework.core.type.ClassMetadata;
|
|||
* without effect on users of the <code>core.type</code> package.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Costin Leau
|
||||
* @since 2.5
|
||||
*/
|
||||
final class SimpleMetadataReader implements MetadataReader {
|
||||
|
||||
private final Resource resource;
|
||||
|
||||
private final ClassReader classReader;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private ClassMetadata classMetadata;
|
||||
|
||||
private AnnotationMetadata annotationMetadata;
|
||||
|
||||
private final ClassMetadata classMetadata;
|
||||
private final AnnotationMetadata annotationMetadata;
|
||||
|
||||
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
|
||||
this.resource = resource;
|
||||
InputStream is = this.resource.getInputStream();
|
||||
InputStream is = resource.getInputStream();
|
||||
ClassReader classReader = null;
|
||||
try {
|
||||
this.classReader = new ClassReader(is);
|
||||
}
|
||||
finally {
|
||||
classReader = new ClassReader(is);
|
||||
} finally {
|
||||
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() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
public ClassMetadata getClassMetadata() {
|
||||
if (this.classMetadata == null) {
|
||||
ClassMetadataReadingVisitor visitor = new ClassMetadataReadingVisitor();
|
||||
this.classReader.accept(visitor, true);
|
||||
this.classMetadata = visitor;
|
||||
}
|
||||
return this.classMetadata;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -48,7 +48,8 @@ public class CachingMetadataReaderLeakTest {
|
|||
|
||||
@Test
|
||||
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());
|
||||
|
||||
// look at a LOT of items
|
||||
|
|
@ -71,5 +72,8 @@ public class CachingMetadataReaderLeakTest {
|
|||
MetadataReader reader = mrf.getMetadataReader(resource);
|
||||
assertThat(reader, notNullValue());
|
||||
}
|
||||
|
||||
// useful for profiling to take snapshots
|
||||
//System.in.read();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue