You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/03/13 19:57:46 UTC

[juneau] branch master updated: Collections usage optimizations

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new e3ae95c  Collections usage optimizations
e3ae95c is described below

commit e3ae95cab45f35bc4de4f219e23ae5dc20e02317
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Sun Mar 13 15:57:18 2022 -0400

    Collections usage optimizations
---
 .../java/org/apache/juneau/internal/HttpUtils.java |  19 ++--
 .../java/org/apache/juneau/internal/MultiSet.java  |  29 ++----
 .../org/apache/juneau/internal/ObjectUtils.java    |   2 +-
 .../juneau/jsonschema/JsonSchemaGenerator.java     |   8 +-
 .../jsonschema/JsonSchemaGeneratorSession.java     |   2 +-
 .../main/java/org/apache/juneau/parser/Parser.java |   5 +-
 .../java/org/apache/juneau/parser/ParserSet.java   |  20 ++--
 .../org/apache/juneau/reflect/AnnotationInfo.java  |  28 ++++--
 .../org/apache/juneau/reflect/AnnotationList.java  |   2 +-
 .../java/org/apache/juneau/reflect/ClassInfo.java  | 102 ++++++++++++---------
 .../org/apache/juneau/reflect/ExecutableInfo.java  |  36 ++++----
 .../java/org/apache/juneau/reflect/MethodInfo.java |  30 +++---
 .../java/org/apache/juneau/reflect/ParamInfo.java  |  12 +--
 .../org/apache/juneau/reflect/ClassInfoTest.java   |  22 ++---
 .../apache/juneau/reflect/ExecutableInfoTest.java  |   4 +-
 .../java/org/apache/juneau/utils/MultiSetTest.java |   2 +-
 16 files changed, 174 insertions(+), 149 deletions(-)

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HttpUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HttpUtils.java
index 4c48452..22359ef 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HttpUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HttpUtils.java
@@ -12,7 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.internal;
 
-import static org.apache.juneau.internal.StringUtils.*;
 import java.lang.reflect.*;
 
 /**
@@ -24,6 +23,10 @@ import java.lang.reflect.*;
  */
 public class HttpUtils {
 
+	private static final String[]
+		LC_METHODS = new String[]{"get","put","post","delete","options","head","connect","trace","patch"},
+		UC_METHODS = new String[]{"GET","PUT","POST","DELETE","OPTIONS","HEAD","CONNECT","TRACE","PATCH"};
+
 	/**
 	 * Given a method name, infers the REST method name.
 	 *
@@ -37,10 +40,11 @@ public class HttpUtils {
 		if (detectMethod) {
 			if (n.startsWith("do") && n.length() > 2) {
 				String n2 = n.substring(2).toUpperCase();
-				if (isOneOf(n2, "GET","PUT","POST","DELETE","OPTIONS","HEAD","CONNECT","TRACE","PATCH"))
-					return n2;
+				for (String t : UC_METHODS)
+					if (n2.equals(t))
+						return n2;
 			}
-			for (String t : new String[]{"get","put","post","delete","options","head","connect","trace","patch"})
+			for (String t : LC_METHODS)
 				if (n.startsWith(t) && (n.length() == t.length() || Character.isUpperCase(n.charAt(t.length()))))
 					return t.toUpperCase();
 		}
@@ -59,10 +63,11 @@ public class HttpUtils {
 		if (method == null) {
 			if (n.startsWith("do") && n.length() > 2) {
 				String n2 = n.substring(2).toUpperCase();
-				if (isOneOf(n2, "GET","PUT","POST","DELETE","OPTIONS","HEAD","CONNECT","TRACE","PATCH"))
-					return "/";
+				for (String t : UC_METHODS)
+					if (n2.equals(t))
+						return "/";
 			}
-			for (String t : new String[]{"get","put","post","delete","options","head","connect","trace","patch"}) {
+			for (String t : LC_METHODS) {
 				if (n.startsWith(t) && (n.length() == t.length() || Character.isUpperCase(n.charAt(t.length())))) {
 					return '/' + java.beans.Introspector.decapitalize(n.substring(t.length()));
 				}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
index 6e72561..0a57eb0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MultiSet.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.internal;
 
 import static org.apache.juneau.assertions.Assertions.*;
+
 import java.util.*;
 
 /**
@@ -27,7 +28,7 @@ import java.util.*;
 public class MultiSet<E> extends AbstractSet<E> {
 
 	/** Inner collections. */
-	final List<Collection<E>> l = new ArrayList<>();
+	final Collection<E>[] l;
 
 	/**
 	 * Create a new Set that consists as a coalesced set of the specified collections.
@@ -36,20 +37,10 @@ public class MultiSet<E> extends AbstractSet<E> {
 	 */
 	@SafeVarargs
 	public MultiSet(Collection<E>...c) {
-		for (Collection<E> cc : c)
-			append(cc);
-	}
-
-	/**
-	 * Appends the specified collection to this set of collections.
-	 *
-	 * @param c The collection to append to this set of collections.
-	 * @return This object.
-	 */
-	public MultiSet<E> append(Collection<E> c) {
 		assertArgNotNull("c", c);
-		l.add(c);
-		return this;
+		for (Collection<E> cc : c)
+			assertArgNotNull("c", cc);
+		l = c;
 	}
 
 	/**
@@ -59,7 +50,7 @@ public class MultiSet<E> extends AbstractSet<E> {
 	public Iterator<E> iterator() {
 		return new Iterator<E>() {
 			int i = 0;
-			Iterator<E> i2 = (l.size() > 0 ? l.get(i++).iterator() : null);
+			Iterator<E> i2 = (l.length > 0 ? l[i++].iterator() : null);
 
 			@Override /* Iterator */
 			public boolean hasNext() {
@@ -67,8 +58,8 @@ public class MultiSet<E> extends AbstractSet<E> {
 					return false;
 				if (i2.hasNext())
 					return true;
-				for (int j = i; j < l.size(); j++)
-					if (l.get(j).size() > 0)
+				for (int j = i; j < l.length; j++)
+					if (l[j].size() > 0)
 						return true;
 				return false;
 			}
@@ -78,9 +69,9 @@ public class MultiSet<E> extends AbstractSet<E> {
 				if (i2 == null)
 					throw new NoSuchElementException();
 				while (! i2.hasNext()) {
-					if (i >= l.size())
+					if (i >= l.length)
 						throw new NoSuchElementException();
-					i2 = l.get(i++).iterator();
+					i2 = l[i++].iterator();
 				}
 				return i2.next();
 			}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
index 1014036..966f8ab 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ObjectUtils.java
@@ -285,7 +285,7 @@ public class ObjectUtils {
 				MethodInfo mi = ci.getDeclaredMethod(x -> x.hasName("properties"));
 				if (mi != null)
 					methods2.put(cname, mi.accessible());
-				ci = ci.getParent();
+				ci = ci.getSuperclass();
 			} while (ci != null);
 			methods = methods2;
 			PROPERTIES_METHODS.put(o.getClass(), methods);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
index 6d36ad6..e40f77b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
@@ -854,7 +854,7 @@ public class JsonSchemaGenerator extends BeanTraverseContext implements JsonSche
 	private final BeanDefMapper beanDefMapperBean;
 	final JsonSerializer jsonSerializer;
 	final JsonParser jsonParser;
-	private final Set<Pattern> ignoreTypePatterns;
+	private final Pattern[] ignoreTypePatterns;
 	private final Map<ClassMeta<?>,JsonSchemaClassMeta> jsonSchemaClassMetas = new ConcurrentHashMap<>();
 	private final Map<BeanPropertyMeta,JsonSchemaBeanPropertyMeta> jsonSchemaBeanPropertyMetas = new ConcurrentHashMap<>();
 
@@ -876,7 +876,7 @@ public class JsonSchemaGenerator extends BeanTraverseContext implements JsonSche
 
 		Set<Pattern> ignoreTypePatterns = set();
 		ignoreTypes.forEach(y -> split(y, x -> ignoreTypePatterns.add(Pattern.compile(x.replace(".", "\\.").replace("*", ".*")))));
-		this.ignoreTypePatterns = ignoreTypePatterns;
+		this.ignoreTypePatterns = ignoreTypePatterns.toArray(new Pattern[ignoreTypePatterns.size()]);
 
 		try {
 			beanDefMapperBean = beanDefMapper.newInstance();
@@ -977,8 +977,8 @@ public class JsonSchemaGenerator extends BeanTraverseContext implements JsonSche
 	 * @return
 	 * 	Custom schema information for particular class types.
 	 */
-	public Set<Pattern> getIgnoreTypes() {
-		return ignoreTypePatterns;
+	public List<Pattern> getIgnoreTypes() {
+		return ulist(ignoreTypePatterns);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
index af3e205..0f81c55 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
@@ -539,7 +539,7 @@ public class JsonSchemaGeneratorSession extends BeanTraverseSession {
 	 * @return
 	 * 	Custom schema information for particular class types.
 	 */
-	protected final Set<Pattern> getIgnoreTypes() {
+	protected final List<Pattern> getIgnoreTypes() {
 		return ctx.getIgnoreTypes();
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
index dc5d96d..0138360 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.parser;
 
 import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;
@@ -1362,8 +1363,8 @@ public class Parser extends BeanContextable {
 	 *
 	 * @return The list of media types.  Never <jk>null</jk>.
 	 */
-	public final MediaType[] getMediaTypes() {
-		return consumesArray;
+	public final List<MediaType> getMediaTypes() {
+		return ulist(consumesArray);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSet.java
index 20d3125..3fddf50 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSet.java
@@ -483,8 +483,8 @@ public final class ParserSet {
 	// Maps Content-Type headers to matches.
 	private final ConcurrentHashMap<String,ParserMatch> cache = new ConcurrentHashMap<>();
 
-	private final List<MediaType> mediaTypes;
-	private final List<Parser> mediaTypeParsers;
+	private final MediaType[] mediaTypes;
+	private final Parser[] mediaTypeParsers;
 
 	final Parser[] entries;
 
@@ -500,14 +500,14 @@ public final class ParserSet {
 		List<MediaType> lmt = list();
 		List<Parser> l = list();
 		for (Parser e : entries) {
-			for (MediaType m: e.getMediaTypes()) {
-				lmt.add(m);
+			e.getMediaTypes().forEach(x -> {
+				lmt.add(x);
 				l.add(e);
-			}
+			});
 		}
 
-		this.mediaTypes = unmodifiable(lmt);
-		this.mediaTypeParsers = unmodifiable(l);
+		this.mediaTypes = array(lmt, MediaType.class);
+		this.mediaTypeParsers = array(l, Parser.class);
 	}
 
 	private Parser build(Object o) {
@@ -540,10 +540,10 @@ public final class ParserSet {
 			return pm;
 
 		ContentType ct = contentType(contentTypeHeader);
-		int match = ct.match(mediaTypes);
+		int match = ct.match(ulist(mediaTypes));
 
 		if (match >= 0) {
-			pm = new ParserMatch(mediaTypes.get(match), mediaTypeParsers.get(match));
+			pm = new ParserMatch(mediaTypes[match], mediaTypeParsers[match]);
 			cache.putIfAbsent(contentTypeHeader, pm);
 		}
 
@@ -591,7 +591,7 @@ public final class ParserSet {
 	 * @return An unmodifiable list of media types.
 	 */
 	public List<MediaType> getSupportedMediaTypes() {
-		return mediaTypes;
+		return ulist(mediaTypes);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java
index 5120055..40a2be5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java
@@ -14,6 +14,7 @@ package org.apache.juneau.reflect;
 
 import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.ConsumerUtils.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
 import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.lang.annotation.*;
@@ -38,12 +39,13 @@ import org.apache.juneau.svl.*;
  *
  * @param <T> The annotation type.
  */
-public class AnnotationInfo<T extends Annotation> {
+public final class AnnotationInfo<T extends Annotation> {
 
 	private final ClassInfo c;
 	private final MethodInfo m;
 	private final Package p;
 	private final T a;
+	private volatile Method[] methods;
 	final int rank;
 
 	/**
@@ -158,19 +160,19 @@ public class AnnotationInfo<T extends Annotation> {
 		if (p != null)
 			jm.put("package", p.getName());
 		JsonMap ja = new JsonMap();
-		Class<?> ca = a.annotationType();
-		for (Method m : ca.getDeclaredMethods()) {
+		ClassInfo ca = ClassInfo.of(a.annotationType());
+		ca.forEachDeclaredMethod(null, x -> {
 			try {
-				Object v = m.invoke(a);
-				Object d = m.getDefaultValue();
-				if (! Objects.equals(v, d)) {
+				Object v = x.invoke(a);
+				Object d = x.inner().getDefaultValue();
+				if (ne(v, d)) {
 					if (! (ArrayUtils.isArray(v) && Array.getLength(v) == 0 && Array.getLength(d) == 0))
 						ja.put(m.getName(), v);
 				}
 			} catch (Exception e) {
 				ja.put(m.getName(), e.getLocalizedMessage());
 			}
-		}
+		});
 		jm.put("@" + ca.getSimpleName(), ja);
 		return jm;
 	}
@@ -290,7 +292,7 @@ public class AnnotationInfo<T extends Annotation> {
 	 */
 	@SuppressWarnings("unchecked")
 	public <V> AnnotationInfo<?> forEachValue(Class<V> type, String name, Predicate<V> test, Consumer<V> action) {
-		for (Method m : a.annotationType().getMethods())
+		for (Method m : _getMethods())
 			if (m.getName().equals(name) && m.getReturnType().equals(type))
 				safeRun(() -> consume(test, action, (V)m.invoke(a)));
 		return this;
@@ -306,7 +308,7 @@ public class AnnotationInfo<T extends Annotation> {
 	 */
 	@SuppressWarnings("unchecked")
 	public <V> Optional<V> getValue(Class<V> type, String name, Predicate<V> test) {
-		for (Method m : a.annotationType().getMethods())
+		for (Method m : _getMethods())
 			if (m.getName().equals(name) && m.getReturnType().equals(type)) {
 				try {
 					V v = (V)m.invoke(a);
@@ -318,4 +320,12 @@ public class AnnotationInfo<T extends Annotation> {
 			}
 		return empty();
 	}
+
+	Method[] _getMethods() {
+		if (methods == null)
+			synchronized(this) {
+				methods = a.annotationType().getMethods();
+			}
+		return methods;
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationList.java
index 6d0ec64..c29d2e7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationList.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationList.java
@@ -28,7 +28,7 @@ import java.util.function.*;
  *
  * @serial exclude
  */
-public class AnnotationList extends ArrayList<AnnotationInfo<?>> {
+public final class AnnotationList extends ArrayList<AnnotationInfo<?>> {
 	private static final long serialVersionUID = 1L;
 
 	private static final Comparator<AnnotationInfo<?>> RANK_COMPARATOR = new Comparator<AnnotationInfo<?>>() {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index 6e72595..de5d4ed 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -45,7 +45,7 @@ import org.apache.juneau.internal.*;
  * 	ClassInfo <jv>classInfo</jv> = ClassInfo.<jsm>of</jsm>(MyClass.<jk>class</jk>);
  *
  * 	<jc>// Get all methods in parent-to-child order, sorted alphabetically per class.</jc>
- * 	<jk>for</jk> (MethodInfo <jv>methodInfo</jv> : <jv>classInfo</jv>.getAllMethodsParentFirst()) {
+ * 	<jk>for</jk> (MethodInfo <jv>methodInfo</jv> : <jv>classInfo</jv>.getAllMethods()) {
  * 		<jc>// Do something with it.</jc>
  * 	}
  *
@@ -169,6 +169,7 @@ public final class ClassInfo {
 	private volatile MethodInfo repeatedAnnotationMethod;
 	private volatile ConstructorInfo[] publicConstructors, declaredConstructors;
 	private volatile FieldInfo[] publicFields, declaredFields, allFields;
+	private volatile Annotation[] declaredAnnotations;
 	private int dim = -1;
 	private ClassInfo componentType;
 
@@ -281,7 +282,7 @@ public final class ClassInfo {
 	 * @return
 	 * 	The parent class, or <jk>null</jk> if the class has no parent.
 	 */
-	public ClassInfo getParent() {
+	public ClassInfo getSuperclass() {
 		return c == null ? null : of(c.getSuperclass());
 	}
 
@@ -362,56 +363,64 @@ public final class ClassInfo {
 	}
 
 	/** Results are in child-to-parent order. */
-	synchronized ClassInfo[] _getInterfaces() {
+	ClassInfo[] _getInterfaces() {
 		if (interfaces == null) {
-			Set<ClassInfo> s = set();
-			for (ClassInfo ci : _getParents())
-				for (ClassInfo ci2 : ci._getDeclaredInterfaces()) {
-					s.add(ci2);
-					for (ClassInfo ci3 : ci2._getInterfaces())
-						s.add(ci3);
-				}
-			interfaces = s.toArray(new ClassInfo[s.size()]);
+			synchronized(this) {
+				Set<ClassInfo> s = set();
+				for (ClassInfo ci : _getParents())
+					for (ClassInfo ci2 : ci._getDeclaredInterfaces()) {
+						s.add(ci2);
+						for (ClassInfo ci3 : ci2._getInterfaces())
+							s.add(ci3);
+					}
+				interfaces = s.toArray(new ClassInfo[s.size()]);
+			}
 		}
 		return interfaces;
 	}
 
 	/** Results are in the same order as Class.getInterfaces(). */
-	private synchronized ClassInfo[] _getDeclaredInterfaces() {
+	ClassInfo[] _getDeclaredInterfaces() {
 		if (declaredInterfaces == null) {
-			Class<?>[] ii = c == null ? new Class[0] : c.getInterfaces();
-			ClassInfo[] l = new ClassInfo[ii.length];
-			for (int i = 0; i < ii.length; i++)
-				l[i] = of(ii[i]);
-			declaredInterfaces = l;
+			synchronized(this) {
+				Class<?>[] ii = c == null ? new Class[0] : c.getInterfaces();
+				ClassInfo[] l = new ClassInfo[ii.length];
+				for (int i = 0; i < ii.length; i++)
+					l[i] = of(ii[i]);
+				declaredInterfaces = l;
+			}
 		}
 		return declaredInterfaces;
 	}
 
 	/** Results are in child-to-parent order. */
-	synchronized ClassInfo[] _getParents() {
+	ClassInfo[] _getParents() {
 		if (parents == null) {
-			List<ClassInfo> l = list();
-			Class<?> pc = c;
-			while (pc != null && pc != Object.class) {
-				l.add(of(pc));
-				pc = pc.getSuperclass();
+			synchronized(this) {
+				List<ClassInfo> l = list();
+				Class<?> pc = c;
+				while (pc != null && pc != Object.class) {
+					l.add(of(pc));
+					pc = pc.getSuperclass();
+				}
+				parents = l.toArray(new ClassInfo[l.size()]);
 			}
-			parents = l.toArray(new ClassInfo[l.size()]);
 		}
 		return parents;
 	}
 
 	/** Results are classes-before-interfaces, then child-to-parent order. */
-	private synchronized ClassInfo[] _getAllParents() {
+	ClassInfo[] _getAllParents() {
 		if (allParents == null) {
-			ClassInfo[] a1 = _getParents(), a2 = _getInterfaces();
-			ClassInfo[] l = new ClassInfo[a1.length + a2.length];
-			for (int i = 0; i < a1.length; i++)
-				l[i] = a1[i];
-			for (int i = 0; i < a2.length; i++)
-				l[i+a1.length] = a2[i];
-			allParents = l;
+			synchronized(this) {
+				ClassInfo[] a1 = _getParents(), a2 = _getInterfaces();
+				ClassInfo[] l = new ClassInfo[a1.length + a2.length];
+				for (int i = 0; i < a1.length; i++)
+					l[i] = a1[i];
+				for (int i = 0; i < a2.length; i++)
+					l[i+a1.length] = a2[i];
+				allParents = l;
+			}
 		}
 		return allParents;
 	}
@@ -561,7 +570,7 @@ public final class ClassInfo {
 		return this;
 	}
 
-	private synchronized MethodInfo[] _getPublicMethods() {
+	MethodInfo[] _getPublicMethods() {
 		if (publicMethods == null) {
 			synchronized(this) {
 				Method[] mm = c == null ? new Method[0] : c.getMethods();
@@ -576,7 +585,7 @@ public final class ClassInfo {
 		return publicMethods;
 	}
 
-	private synchronized MethodInfo[] _getDeclaredMethods() {
+	MethodInfo[] _getDeclaredMethods() {
 		if (declaredMethods == null) {
 			synchronized(this) {
 				Method[] mm = c == null ? new Method[0] : c.getDeclaredMethods();
@@ -591,7 +600,7 @@ public final class ClassInfo {
 		return declaredMethods;
 	}
 
-	private synchronized MethodInfo[] _getAllMethods() {
+	MethodInfo[] _getAllMethods() {
 		if (allMethods == null) {
 			synchronized(this) {
 				List<MethodInfo> l = list();
@@ -603,7 +612,7 @@ public final class ClassInfo {
 		return allMethods;
 	}
 
-	private synchronized MethodInfo[] _getAllMethodsParentFirst() {
+	MethodInfo[] _getAllMethodsParentFirst() {
 		if (allMethodsParentFirst == null) {
 			synchronized(this) {
 				List<MethodInfo> l = list();
@@ -698,7 +707,7 @@ public final class ClassInfo {
 		return null;
 	}
 
-	private synchronized ConstructorInfo[] _getPublicConstructors() {
+	ConstructorInfo[] _getPublicConstructors() {
 		if (publicConstructors == null) {
 			synchronized(this) {
 				Constructor<?>[] cc = c == null ? new Constructor[0] : c.getConstructors();
@@ -712,7 +721,7 @@ public final class ClassInfo {
 		return publicConstructors;
 	}
 
-	private synchronized ConstructorInfo[] _getDeclaredConstructors() {
+	ConstructorInfo[] _getDeclaredConstructors() {
 		if (declaredConstructors == null) {
 			synchronized(this) {
 				Constructor<?>[] cc = c == null ? new Constructor[0] : c.getDeclaredConstructors();
@@ -864,7 +873,7 @@ public final class ClassInfo {
 		return this;
 	}
 
-	private FieldInfo[] _getPublicFields() {
+	FieldInfo[] _getPublicFields() {
 		if (publicFields == null) {
 			synchronized(this) {
 				Map<String,FieldInfo> m = map();
@@ -883,7 +892,7 @@ public final class ClassInfo {
 		return publicFields;
 	}
 
-	private synchronized FieldInfo[] _getDeclaredFields() {
+	FieldInfo[] _getDeclaredFields() {
 		if (declaredFields == null) {
 			synchronized(this) {
 				Field[] ff = c == null ? new Field[0] : c.getDeclaredFields();
@@ -898,7 +907,7 @@ public final class ClassInfo {
 		return declaredFields;
 	}
 
-	private synchronized FieldInfo[] _getAllFields() {
+	FieldInfo[] _getAllFields() {
 		if (allFields == null) {
 			synchronized(this) {
 				List<FieldInfo> l = list();
@@ -1256,7 +1265,7 @@ public final class ClassInfo {
 		A t = ap.firstDeclaredAnnotation(a, c, x -> true);
 		if (t != null)
 			return t;
-		ClassInfo sci = getParent();
+		ClassInfo sci = getSuperclass();
 		if (sci != null) {
 			t = sci.getAnnotation(ap, a);
 			if (t != null)
@@ -1326,6 +1335,15 @@ public final class ClassInfo {
 		return this;
 	}
 
+	Annotation[] _getDeclaredAnnotations() {
+		if (declaredAnnotations == null) {
+			synchronized(this) {
+				declaredAnnotations = c.getDeclaredAnnotations();
+			}
+		}
+		return declaredAnnotations;
+	}
+
 	//-----------------------------------------------------------------------------------------------------------------
 	// Characteristics
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
index b3f6cf5..e1501b7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
@@ -162,7 +162,7 @@ public abstract class ExecutableInfo {
 	 * @return The parameter types on this executable.
 	 */
 	public final List<ClassInfo> getParamTypes() {
-		return ulist(_getParamTypes());
+		return ulist(_getParameterTypes());
 	}
 
 	/**
@@ -173,7 +173,7 @@ public abstract class ExecutableInfo {
 	 */
 	public final ClassInfo getParamType(int index) {
 		checkIndex(index);
-		return _getParamTypes()[index];
+		return _getParameterTypes()[index];
 	}
 
 	/**
@@ -238,7 +238,7 @@ public abstract class ExecutableInfo {
 		return _getRawParameters()[index];
 	}
 
-	private ParamInfo[] _getParams() {
+	final ParamInfo[] _getParams() {
 		if (params == null) {
 			synchronized(this) {
 				Parameter[] rp = _getRawParameters();
@@ -251,7 +251,7 @@ public abstract class ExecutableInfo {
 		return params;
 	}
 
-	ClassInfo[] _getParamTypes() {
+	final ClassInfo[] _getParameterTypes() {
 		if (paramTypes == null) {
 			synchronized(this) {
 				Class<?>[] ptc = _getRawParamTypes();
@@ -289,7 +289,7 @@ public abstract class ExecutableInfo {
 		return rawParamTypes;
 	}
 
-	private Type[] _getRawGenericParamTypes() {
+	final Type[] _getRawGenericParamTypes() {
 		if (rawGenericParamTypes == null) {
 			synchronized(this) {
 				rawGenericParamTypes = e.getGenericParameterTypes();
@@ -298,7 +298,7 @@ public abstract class ExecutableInfo {
 		return rawGenericParamTypes;
 	}
 
-	private Parameter[] _getRawParameters() {
+	final Parameter[] _getRawParameters() {
 		if (rawParameters == null) {
 			synchronized(this) {
 				rawParameters = e.getParameters();
@@ -328,8 +328,8 @@ public abstract class ExecutableInfo {
 	 * @param consumer The consumer.
 	 * @return This object.
 	 */
-	public <A extends Annotation> ExecutableInfo forEachParameterAnnotation(int index, Class<A> type, Predicate<A> predicate, Consumer<A> consumer) {
-		for (Annotation a : getParameterAnnotations(index))
+	public final <A extends Annotation> ExecutableInfo forEachParameterAnnotation(int index, Class<A> type, Predicate<A> predicate, Consumer<A> consumer) {
+		for (Annotation a : _getParameterAnnotations(index))
 			if (type.isInstance(a))
 				consume(predicate, consumer, type.cast(a));
 		return this;
@@ -344,7 +344,7 @@ public abstract class ExecutableInfo {
 		return parameterAnnotations;
 	}
 
-	final Annotation[] getParameterAnnotations(int index) {
+	final Annotation[] _getParameterAnnotations(int index) {
 		checkIndex(index);
 		Annotation[][] x = _getParameterAnnotations();
 		int c = e.getParameterCount();
@@ -361,7 +361,7 @@ public abstract class ExecutableInfo {
 		return x[index];
 	}
 
-	final Annotation[] getDeclaredAnnotations() {
+	final Annotation[] _getDeclaredAnnotations() {
 		if (declaredAnnotations == null) {
 			synchronized(this) {
 				declaredAnnotations = e.getDeclaredAnnotations();
@@ -383,7 +383,7 @@ public abstract class ExecutableInfo {
 		return ulist(_getExceptionTypes());
 	}
 
-	private ClassInfo[] _getExceptionTypes() {
+	final ClassInfo[] _getExceptionTypes() {
 		if (exceptionInfos == null) {
 			synchronized(this) {
 				Class<?>[] exceptionTypes = e.getExceptionTypes();
@@ -470,7 +470,7 @@ public abstract class ExecutableInfo {
 	 * @param flags The flags to test for.
 	 * @return <jk>true</jk> if all specified flags are applicable to this field.
 	 */
-	public boolean is(ReflectFlags...flags) {
+	public final boolean is(ReflectFlags...flags) {
 		return isAll(flags);
 	}
 
@@ -579,7 +579,7 @@ public abstract class ExecutableInfo {
 	 * @return <jk>true</jk> if this method has this arguments in the exact order.
 	 */
 	public final boolean hasMatchingParamTypes(Class<?>...args) {
-		ClassInfo[] pt = _getParamTypes();
+		ClassInfo[] pt = _getParameterTypes();
 		if (pt.length != args.length)
 			return false;
 		for (int i = 0; i < pt.length; i++) {
@@ -600,7 +600,7 @@ public abstract class ExecutableInfo {
 	 * @return <jk>true</jk> if this method has this arguments in the exact order.
 	 */
 	public final boolean hasMatchingParamTypes(ClassInfo...args) {
-		ClassInfo[] pt = _getParamTypes();
+		ClassInfo[] pt = _getParameterTypes();
 		if (pt.length != args.length)
 			return false;
 		for (int i = 0; i < pt.length; i++) {
@@ -634,7 +634,7 @@ public abstract class ExecutableInfo {
 	 * @param argTypes The arg types to check against.
 	 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments.
 	 */
-	public int fuzzyArgsMatch(Class<?>... argTypes) {
+	public final int fuzzyArgsMatch(Class<?>... argTypes) {
 		int matches = 0;
 		outer: for (ClassInfo pi : getParamTypes()) {
 			for (Class<?> a : argTypes) {
@@ -658,7 +658,7 @@ public abstract class ExecutableInfo {
 	 * @param argTypes The arg types to check against.
 	 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments.
 	 */
-	public int fuzzyArgsMatch(Object... argTypes) {
+	public final int fuzzyArgsMatch(Object... argTypes) {
 		int matches = 0;
 		outer: for (ClassInfo pi : getParamTypes()) {
 			for (Object a : argTypes) {
@@ -678,7 +678,7 @@ public abstract class ExecutableInfo {
 	 * @param args The arguments to test for.
 	 * @return <jk>true</jk> if this method has at most only this arguments in any order.
 	 */
-	public boolean hasFuzzyParamTypes(ClassInfo...args) {
+	public final boolean hasFuzzyParamTypes(ClassInfo...args) {
 		return fuzzyArgsMatch(args) != -1;
 	}
 
@@ -692,7 +692,7 @@ public abstract class ExecutableInfo {
 	 * @param argTypes The arg types to check against.
 	 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments.
 	 */
-	public int fuzzyArgsMatch(ClassInfo... argTypes) {
+	public final int fuzzyArgsMatch(ClassInfo... argTypes) {
 		int matches = 0;
 		outer: for (ClassInfo pi : getParamTypes()) {
 			for (ClassInfo a : argTypes) {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
index 08e3af9..7db33bc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
@@ -133,7 +133,7 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho
 	 */
 	public int canAcceptFuzzy(Object...args) {
 		int matches = 0;
-		outer: for (ClassInfo pi : getParamTypes()) {
+		outer: for (ClassInfo pi : _getParameterTypes()) {
 			for (Object a : args) {
 				if (pi.canAcceptArg(a)) {
 					matches++;
@@ -178,29 +178,29 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho
 		return this;
 	}
 
-	private static List<MethodInfo> findMatching(List<MethodInfo> l, Method m, Class<?> c) {
-		for (Method m2 : c.getDeclaredMethods())
-			if (m.getName().equals(m2.getName()) && Arrays.equals(m.getParameterTypes(), m2.getParameterTypes()))
-				l.add(MethodInfo.of(m2));
-		Class<?> pc = c.getSuperclass();
+	private static List<MethodInfo> findMatching(List<MethodInfo> l, MethodInfo m, ClassInfo c) {
+		for (MethodInfo m2 : c._getDeclaredMethods())
+			if (m.hasName(m2.getName()) && Arrays.equals(m._getParameterTypes(), m2._getParameterTypes()))
+				l.add(m2);
+		ClassInfo pc = c.getSuperclass();
 		if (pc != null)
 			findMatching(l, m, pc);
-		for (Class<?> ic : c.getInterfaces())
+		for (ClassInfo ic : c._getDeclaredInterfaces())
 			findMatching(l, m, ic);
 		return l;
 	}
 
 	private MethodInfo findMatchingOnClass(ClassInfo c) {
-		for (Method m2 : c.inner().getDeclaredMethods())
-			if (m.getName().equals(m2.getName()) && Arrays.equals(m.getParameterTypes(), m2.getParameterTypes()))
-				return MethodInfo.of(m2);
+		for (MethodInfo m2 : c._getDeclaredMethods())
+			if (hasName(m2.getName()) && Arrays.equals(_getParameterTypes(), m2._getParameterTypes()))
+				return m2;
 		return null;
 	}
 
-	private MethodInfo[] _getMatching() {
+	MethodInfo[] _getMatching() {
 		if (matching == null) {
 			synchronized(this) {
-				List<MethodInfo> l = findMatching(list(), m, m.getDeclaringClass());
+				List<MethodInfo> l = findMatching(list(), this, getDeclaringClass());
 				matching = l.toArray(new MethodInfo[l.size()]);
 			}
 		}
@@ -343,7 +343,7 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho
 		declaringClass.forEachAnnotation(annotationProvider, type, filter, action);
 		MethodInfo[] m = _getMatching();
 		for (int i = m.length-1; i >= 0; i--)
-			for (Annotation a2 : m[i].getDeclaredAnnotations())
+			for (Annotation a2 : m[i]._getDeclaredAnnotations())
 				consume(type, filter, action, a2);
 		getReturnType().unwrap(Value.class,Optional.class).forEachAnnotation(annotationProvider, type, filter, action);
 		return this;
@@ -459,14 +459,14 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho
 
 	private void forEachDeclaredAnnotationInfo(ClassInfo ci, Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
 		if (ci != null)
-			for (Annotation a : ci.c.getDeclaredAnnotations())
+			for (Annotation a : ci._getDeclaredAnnotations())
 				AnnotationInfo.of(ci, a).accept(filter, action);
 	}
 
 	private void forEachDeclaredMethodAnnotationInfo(ClassInfo ci, Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
 		MethodInfo m = findMatchingOnClass(ci);
 		if (m != null)
-			for (Annotation a : m.getDeclaredAnnotations())
+			for (Annotation a : m._getDeclaredAnnotations())
 				AnnotationInfo.of(m, a).accept(filter, action);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
index 8494ad9..f6f1434 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java
@@ -105,7 +105,7 @@ public final class ParamInfo {
 	 * @return This object.
 	 */
 	public <A extends Annotation> ParamInfo forEachDeclaredAnnotation(Class<A> type, Predicate<A> filter, Consumer<A> action) {
-		for (Annotation a : eInfo.getParameterAnnotations(index))
+		for (Annotation a : eInfo._getParameterAnnotations(index))
 			consume(type, filter, action, a);
 		return this;
 	}
@@ -121,7 +121,7 @@ public final class ParamInfo {
 	 */
 	public <A extends Annotation> A getDeclaredAnnotation(Class<A> type) {
 		if (type != null)
-			for (Annotation a : eInfo.getParameterAnnotations(index))
+			for (Annotation a : eInfo._getParameterAnnotations(index))
 				if (type.isInstance(a))
 					return type.cast(a);
 		return null;
@@ -179,7 +179,7 @@ public final class ParamInfo {
 
 	private <A extends Annotation> A findAnnotation(Class<A> type) {
 		if (eInfo.isConstructor()) {
-			for (Annotation a2 : eInfo.getParameterAnnotations(index))
+			for (Annotation a2 : eInfo._getParameterAnnotations(index))
 				if (type.isInstance(a2))
 					return type.cast(a2);
 			return eInfo.getParamType(index).unwrap(Value.class,Optional.class).getAnnotation(type);
@@ -228,7 +228,7 @@ public final class ParamInfo {
 			A o = ci.getAnnotation(type, filter);
 			if (o != null)
 				return o;
-			for (Annotation a2 : eInfo.getParameterAnnotations(index))
+			for (Annotation a2 : eInfo._getParameterAnnotations(index))
 				if (passes(type, filter, a2))
 					return (A)a2;
 		} else {
@@ -247,7 +247,7 @@ public final class ParamInfo {
 	private <A extends Annotation> ParamInfo forEachAnnotation(AnnotationProvider ap, Class<A> a, Predicate<A> filter, Consumer<A> action) {
 		if (eInfo.isConstructor) {
 			ClassInfo ci = eInfo.getParamType(index).unwrap(Value.class,Optional.class);
-			Annotation[] annotations = eInfo.getParameterAnnotations(index);
+			Annotation[] annotations = eInfo._getParameterAnnotations(index);
 			ci.forEachAnnotation(ap, a, filter, action);
 			for (Annotation a2 : annotations)
 				consume(a, filter, action, a2);
@@ -260,7 +260,7 @@ public final class ParamInfo {
 		return this;
 	}
 
-	private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() {
+	private Map<Class<?>,Optional<Annotation>> annotationMap() {
 		if (annotationMap == null) {
 			synchronized(this) {
 				annotationMap = new ConcurrentHashMap<>();
diff --git a/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java b/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
index 0ed2efd..c960ab6 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
@@ -270,21 +270,21 @@ public class ClassInfoTest {
 
 	@Test
 	public void getParent() {
-		check("BC2", bc3.getParent());
-		check("BC1", bc2.getParent());
-		check("Object", bc1.getParent());
-		check(null, object.getParent());
-		check(null, bi2.getParent());
-		check(null, bi1.getParent());
+		check("BC2", bc3.getSuperclass());
+		check("BC1", bc2.getSuperclass());
+		check("Object", bc1.getSuperclass());
+		check(null, object.getSuperclass());
+		check(null, bi2.getSuperclass());
+		check(null, bi1.getSuperclass());
 	}
 
 	@Test
 	public void getParent_onType() {
-		check("Object", aTypeInfo.getParent());
-		check(null, pTypeInfo.getParent());
-		check(null, pTypeDimensionalInfo.getParent());
-		check("Object", pTypeGenericInfo.getParent());
-		check(null, pTypeGenericArgInfo.getParent());
+		check("Object", aTypeInfo.getSuperclass());
+		check(null, pTypeInfo.getSuperclass());
+		check(null, pTypeDimensionalInfo.getSuperclass());
+		check("Object", pTypeGenericInfo.getSuperclass());
+		check(null, pTypeGenericArgInfo.getSuperclass());
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-utest/src/test/java/org/apache/juneau/reflect/ExecutableInfoTest.java b/juneau-utest/src/test/java/org/apache/juneau/reflect/ExecutableInfoTest.java
index 50f058d..79d883a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/reflect/ExecutableInfoTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/reflect/ExecutableInfoTest.java
@@ -289,8 +289,8 @@ public class ExecutableInfoTest {
 
 	@Test
 	public void getParameterAnnotations_atIndex() {
-		check("@CA()", c_c2.getParameterAnnotations(0));
-		check("@CA()", c_m2.getParameterAnnotations(0));
+		check("@CA()", c_c2._getParameterAnnotations(0));
+		check("@CA()", c_m2._getParameterAnnotations(0));
 	}
 
 	@Test
diff --git a/juneau-utest/src/test/java/org/apache/juneau/utils/MultiSetTest.java b/juneau-utest/src/test/java/org/apache/juneau/utils/MultiSetTest.java
index a6bfbf0..9536790 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/utils/MultiSetTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/utils/MultiSetTest.java
@@ -85,7 +85,7 @@ public class MultiSetTest {
 
 		l1 = new LinkedList<>(Arrays.asList(new String[]{"1","2"}));
 		l2 = new LinkedList<>(Arrays.asList(new String[]{"3","4"}));
-		ms = new MultiSet<>(l1).append(l2);
+		ms = new MultiSet<>(l1, l2);
 		assertObject(ms).asJson().is("['1','2','3','4']");
 		assertObject(ms.enumerator()).asJson().is("['1','2','3','4']");
 		assertEquals(4, ms.size());