@@ -103,10 +103,14 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
103
103
final Throwable rootThrowable , final Map <Throwable , Metadata > metadataByThrowable ) {
104
104
105
105
// 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.
107
107
// 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.
110
114
final Map <String , ClassResourceInfo > classResourceInfoByName = new HashMap <>();
111
115
112
116
// Walk over the causal chain
@@ -127,40 +131,46 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
127
131
continue ;
128
132
}
129
133
130
- Class <?> clazz = rootStackTrace .isEmpty () ? null : rootStackTrace .peekLast ();
134
+ Class <?> executionStackTraceElementClass =
135
+ executionStackTrace .isEmpty () ? null : executionStackTrace .peekLast ();
131
136
ClassLoader lastLoader = null ;
132
- ClassResourceInfo classResourceInfo ;
133
137
final StackTraceElement [] stackTraceElements = throwable .getStackTrace ();
134
138
for (int throwableStackIndex = metadata .stackLength - 1 ;
135
139
throwableStackIndex >= 0 ;
136
140
--throwableStackIndex ) {
137
141
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 ();
162
152
}
163
153
}
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
+ }
164
174
}
165
175
}
166
176
return classResourceInfoByName ;
0 commit comments