@@ -103,10 +103,14 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
103103 final Throwable rootThrowable , final Map <Throwable , Metadata > metadataByThrowable ) {
104104
105105 // Stack trace elements of a `Throwable` only contain the class name.
106- // But we need the associated `Class<?> ` to extract its resource information, i.e., JAR file and version.
106+ // But we need the associated `Class` to extract its resource information, i.e., JAR file and version.
107107 // We are capturing the current stack to find suitable class loaders.
108- // We will use this as a bootstrap to go from a class name in a stack trace to a `Class<?>`.
109- final Deque <Class <?>> rootStackTrace = StackLocatorUtil .getCurrentStackTrace ();
108+ // We will use this as a bootstrap to go from a class name in a stack trace to a `Class`.
109+ final Deque <Class <?>> executionStackTrace = StackLocatorUtil .getCurrentStackTrace ();
110+
111+ // Mapping a class name to a `ClassResourceInfo` is an expensive operation.
112+ // Next to `ClassResourceInfo` allocation, it requires extraction of the associated `Class`.
113+ // We will use this lookup table to speed things up.
110114 final Map <String , ClassResourceInfo > classResourceInfoByName = new HashMap <>();
111115
112116 // Walk over the causal chain
@@ -127,40 +131,46 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
127131 continue ;
128132 }
129133
130- Class <?> clazz = rootStackTrace .isEmpty () ? null : rootStackTrace .peekLast ();
134+ Class <?> executionStackTraceElementClass =
135+ executionStackTrace .isEmpty () ? null : executionStackTrace .peekLast ();
131136 ClassLoader lastLoader = null ;
132- ClassResourceInfo classResourceInfo ;
133137 final StackTraceElement [] stackTraceElements = throwable .getStackTrace ();
134138 for (int throwableStackIndex = metadata .stackLength - 1 ;
135139 throwableStackIndex >= 0 ;
136140 --throwableStackIndex ) {
137141
138- // Skip if the current class name is either known, or already visited and is unknown
139- final StackTraceElement stackTraceElement = stackTraceElements [throwableStackIndex ];
140- final String stackTraceElementClassName = stackTraceElement .getClassName ();
141- if (clazz != null && stackTraceElementClassName .equals (clazz .getName ())) {
142- classResourceInfo = new ClassResourceInfo (clazz , true );
143- classResourceInfoByName .put (clazz .getName (), classResourceInfo );
144- lastLoader = classResourceInfo .clazz .getClassLoader ();
145- rootStackTrace .pollLast ();
146- clazz = rootStackTrace .peekLast ();
147- } else {
148- classResourceInfo = classResourceInfoByName .get (stackTraceElementClassName );
149- if (classResourceInfo != null ) {
150- if (classResourceInfo .clazz != null ) {
151- lastLoader = classResourceInfo .clazz .getClassLoader ();
152- }
153- } else {
154- final Class <?> stackTraceElementClass = loadClass (lastLoader , stackTraceElementClassName );
155- classResourceInfo = stackTraceElementClass != null
156- ? new ClassResourceInfo (stackTraceElementClass , false )
157- : ClassResourceInfo .UNKNOWN ;
158- classResourceInfoByName .put (stackTraceElementClassName , classResourceInfo );
159- if (classResourceInfo .clazz != null ) {
160- lastLoader = classResourceInfo .clazz .getClassLoader ();
161- }
142+ // Get the exception's stack trace element
143+ final StackTraceElement throwableStackTraceElement = stackTraceElements [throwableStackIndex ];
144+ final String throwableStackTraceElementClassName = throwableStackTraceElement .getClassName ();
145+
146+ // Skip if the current class name is already registered
147+ ClassResourceInfo classResourceInfo =
148+ classResourceInfoByName .get (throwableStackTraceElementClassName );
149+ if (classResourceInfo != null ) {
150+ if (classResourceInfo .clazz != null ) {
151+ lastLoader = classResourceInfo .clazz .getClassLoader ();
162152 }
163153 }
154+
155+ // See if we get a match from the execution stack trace
156+ else if (executionStackTraceElementClass != null
157+ && throwableStackTraceElementClassName .equals (executionStackTraceElementClass .getName ())) {
158+ classResourceInfo = new ClassResourceInfo (executionStackTraceElementClass , true );
159+ classResourceInfoByName .put (throwableStackTraceElementClassName , classResourceInfo );
160+ lastLoader = classResourceInfo .clazz .getClassLoader ();
161+ executionStackTrace .pollLast ();
162+ executionStackTraceElementClass = executionStackTrace .peekLast ();
163+ }
164+
165+ // We don't know this class name, try to load it using the last found loader
166+ else {
167+ final Class <?> stackTraceElementClass =
168+ loadClass (lastLoader , throwableStackTraceElementClassName );
169+ classResourceInfo = stackTraceElementClass != null
170+ ? new ClassResourceInfo (stackTraceElementClass , false )
171+ : ClassResourceInfo .UNKNOWN ;
172+ classResourceInfoByName .put (throwableStackTraceElementClassName , classResourceInfo );
173+ }
164174 }
165175 }
166176 return classResourceInfoByName ;
0 commit comments