1616 */
1717package org .apache .logging .log4j .core .pattern ;
1818
19+ import org .apache .logging .log4j .util .LoaderUtil ;
20+ import org .apache .logging .log4j .util .StackLocatorUtil ;
21+
1922import java .util .ArrayDeque ;
2023import java .util .Collections ;
24+ import java .util .Deque ;
25+ import java .util .HashMap ;
2126import java .util .HashSet ;
2227import java .util .List ;
2328import java .util .Map ;
2429import java .util .Objects ;
2530import java .util .Queue ;
2631import java .util .Set ;
27- import java .util .stream .Collectors ;
2832import java .util .stream .Stream ;
29- import org .apache .logging .log4j .util .LoaderUtil ;
30- import org .apache .logging .log4j .util .StackLocatorUtil ;
3133
3234/**
3335 * {@link ThrowableStackTraceRenderer} variant where the rendered {@link StackTraceElement}s are enriched with the enclosing JAR file and its version information, if available.
@@ -105,12 +107,8 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
105107 // But we need the associated `Class<?>` to extract its resource information, i.e., JAR file and version.
106108 // We are capturing the current stack to find suitable class loaders.
107109 // We will use this as a bootstrap to go from a class name in a stack trace to a `Class<?>`.
108- final Map <String , ClassResourceInfo > classResourceInfoByName =
109- StackLocatorUtil .getCurrentStackTrace ().stream ()
110- .collect (Collectors .toMap (
111- Class ::getName ,
112- clazz -> new ClassResourceInfo (clazz , true ),
113- (classResourceInfo1 , classResourceInfo2 ) -> classResourceInfo1 ));
110+ final Deque <Class <?>> rootStackTrace = StackLocatorUtil .getCurrentStackTrace ();
111+ final Map <String , ClassResourceInfo > classResourceInfoByName = new HashMap <>();
114112
115113 // Walk over the causal chain
116114 final Set <Throwable > visitedThrowables = new HashSet <>();
@@ -130,7 +128,9 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
130128 continue ;
131129 }
132130
131+ Class <?> clazz = rootStackTrace .isEmpty () ? null : rootStackTrace .peekLast ();
133132 ClassLoader lastLoader = null ;
133+ ClassResourceInfo classResourceInfo ;
134134 final StackTraceElement [] stackTraceElements = throwable .getStackTrace ();
135135 for (int throwableStackIndex = metadata .stackLength - 1 ;
136136 throwableStackIndex >= 0 ;
@@ -139,20 +139,29 @@ private static Map<String, ClassResourceInfo> createClassResourceInfoByName(
139139 // Skip if the current class name is either known, or already visited and is unknown
140140 final StackTraceElement stackTraceElement = stackTraceElements [throwableStackIndex ];
141141 final String stackTraceElementClassName = stackTraceElement .getClassName ();
142- ClassResourceInfo classResourceInfo = classResourceInfoByName .get (stackTraceElementClassName );
143- if (classResourceInfo != null ) {
144- if (classResourceInfo .clazz != null ) {
145- lastLoader = classResourceInfo .clazz .getClassLoader ();
142+ if (clazz != null && stackTraceElementClassName .equals (clazz .getName ())) {
143+ classResourceInfo = new ClassResourceInfo (clazz , true );
144+ classResourceInfoByName .put (clazz .getName (), classResourceInfo );
145+ lastLoader = classResourceInfo .clazz .getClassLoader ();
146+ rootStackTrace .pollLast ();
147+ clazz = rootStackTrace .peekLast ();
148+ } else {
149+ classResourceInfo = classResourceInfoByName .get (stackTraceElementClassName );
150+ if (classResourceInfo != null ) {
151+ if (classResourceInfo .clazz != null ) {
152+ lastLoader = classResourceInfo .clazz .getClassLoader ();
153+ }
154+ } else {
155+ final Class <?> stackTraceElementClass = loadClass (lastLoader , stackTraceElementClassName );
156+ classResourceInfo = stackTraceElementClass != null
157+ ? new ClassResourceInfo (stackTraceElementClass , false )
158+ : ClassResourceInfo .UNKNOWN ;
159+ classResourceInfoByName .put (stackTraceElementClassName , classResourceInfo );
160+ if (classResourceInfo .clazz != null ) {
161+ lastLoader = classResourceInfo .clazz .getClassLoader ();
162+ }
146163 }
147- continue ;
148164 }
149-
150- // Try to determine the stack trace element class, and register the result to the lookup table
151- final Class <?> stackTraceElementClass = loadClass (lastLoader , stackTraceElementClassName );
152- classResourceInfo = stackTraceElementClass != null
153- ? new ClassResourceInfo (stackTraceElementClass , false )
154- : ClassResourceInfo .UNKNOWN ;
155- classResourceInfoByName .put (stackTraceElementClassName , classResourceInfo );
156165 }
157166 }
158167 return classResourceInfoByName ;
0 commit comments