You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by ta...@apache.org on 2026/07/24 13:25:18 UTC
(openwebbeans) 02/04: speed up getNonPrivateMethods: drop O(n^2) List#contains, skip redundant per-level getMethods()
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch startupperf
in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
commit 50fd394b94d96237b062e43617f1c1a548a88223
Author: tandraschko <ta...@apache.org>
AuthorDate: Fri Jul 24 15:22:16 2026 +0200
speed up getNonPrivateMethods: drop O(n^2) List#contains, skip redundant per-level getMethods()
---
.../java/org/apache/webbeans/util/ClassUtil.java | 43 +++++++++++++++++-----
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java b/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
index 86d727c4d..80ffbe36f 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/util/ClassUtil.java
@@ -293,22 +293,29 @@ public final class ClassUtil
{
Map<String, List<Method>> methodMap = new HashMap<>();
List<Method> allMethods = new ArrayList<>(10);
+ // mirrors allMethods for O(1) membership checks (avoids O(n^2) List#contains with Method#equals)
+ Set<Method> allMethodsSet = new HashSet<>();
Class<?> clazz = topClass;
if (!clazz.isAnnotation() && clazz.isInterface())
{
- addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, clazz);
+ addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, allMethodsSet, clazz, true);
for (Class<?> parent : clazz.getInterfaces())
{
- addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, parent);
+ addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, allMethodsSet, parent, true);
}
}
else
{
+ // topClass.getMethods() already returns every public method in the whole hierarchy, so only the
+ // top class needs that (expensive) call; superclasses only add their declared (non-public) methods.
+ // Public methods declared higher up are already collected and deduped via allMethodsSet.
+ boolean topLevel = true;
while (clazz != null)
{
- addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, clazz);
+ addNonPrivateMethods(topClass, excludeFinalMethods, methodMap, allMethods, allMethodsSet, clazz, topLevel);
+ topLevel = false;
clazz = clazz.getSuperclass();
}
}
@@ -391,20 +398,36 @@ public final class ClassUtil
private static void addNonPrivateMethods(Class<?> topClass, boolean excludeFinalMethods,
Map<String, List<Method>> methodMap, List<Method> allMethods,
- Class<?> clazz)
+ Set<Method> allMethodsSet, Class<?> clazz, boolean includeInheritedPublicMethods)
{
- List<Method> temp = new ArrayList<>(Arrays.asList(clazz.getMethods()));
- for (Method method : clazz.getDeclaredMethods())
+ List<Method> temp;
+ if (includeInheritedPublicMethods)
{
- if (!temp.contains(method))
+ Method[] classMethods = clazz.getMethods();
+ Method[] declaredMethods = clazz.getDeclaredMethods();
+ temp = new ArrayList<>(classMethods.length + declaredMethods.length);
+ Collections.addAll(temp, classMethods);
+ for (Method method : declaredMethods)
{
- temp.add(method);
+ // a declared method is in getMethods() iff it is public, so only the non-public
+ // declared methods (private/protected/package) still need to be added here.
+ // This avoids both an O(n^2) List#contains and a temporary de-dup Set.
+ if (!Modifier.isPublic(method.getModifiers()))
+ {
+ temp.add(method);
+ }
}
}
+ else
+ {
+ // inherited public methods were already collected from the top class (and deduped via
+ // allMethodsSet below), so this level only needs to contribute its declared methods.
+ temp = Arrays.asList(clazz.getDeclaredMethods());
+ }
for (Method method : temp)
{
- if (allMethods.contains(method))
+ if (allMethodsSet.contains(method))
{
continue;
}
@@ -450,6 +473,7 @@ public final class ClassUtil
methods = new ArrayList<>();
methods.add(method);
allMethods.add(method);
+ allMethodsSet.add(method);
methodMap.put(method.getName(), methods);
}
else
@@ -459,6 +483,7 @@ public final class ClassUtil
// method is not overridden, so add it
methods.add(method);
allMethods.add(method);
+ allMethodsSet.add(method);
}
}
}