Browse Source

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
pull/23217/head
Costin Leau 15 years ago
parent
commit
ee2b1cde82
  1. 36
      org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java
  2. 15
      org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java
  3. 45
      org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java
  4. 6
      org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java

36
org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java

@ -19,6 +19,7 @@ package org.springframework.core.type.classreading; @@ -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; @@ -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; @@ -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 @@ -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 @@ -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 @@ -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;
}
}
}

15
org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java

@ -25,6 +25,7 @@ import org.springframework.asm.Opcodes; @@ -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; @@ -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 @@ -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 @@ -91,5 +95,4 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method
public String getDeclaringClassName() {
return this.declaringClassName;
}
}
}

45
org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java

@ -32,55 +32,42 @@ import org.springframework.core.type.ClassMetadata; @@ -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;
}
}
}

6
org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java

@ -48,7 +48,8 @@ public class CachingMetadataReaderLeakTest { @@ -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 { @@ -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…
Cancel
Save