Skip to content

Commit 02eee31

Browse files
committed
Fix stack locator calc location on JDK 9
This commit fixes a bug in StackLocator#calcLocation on JDK 9. The particular issue here is that on JDK 9, all stack trace locations report as line 71 of StackLocatorUtil. This is due to a bug in the JDK 9 implementation of StackLocator. The bug is that instead of dropping the top frames of the stack until the first frame that matches the fully-qualified class name of the logger, the implementation would drop all frames from the top that match the fully-qualified class name of the logger. Of course, at this point in the stack trace, there would be none. The fix is to reverse the condition, that we drop all frames until we reach a frame matching the fully-qualified class name of the logger, and then drop all frames matching the fully-qualified class name of the logger. This commit also adds a test that was broken before this change and now passes.
1 parent e67bf82 commit 02eee31

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

log4j-api-java9/src/main/java/org/apache/logging/log4j/util/StackLocator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ public Stack<Class<?>> getCurrentStackTrace() {
6868
}
6969

7070
public StackTraceElement calcLocation(final String fqcnOfLogger) {
71-
return stackWalker.walk(s -> s.dropWhile(f -> f.getClassName().equals(fqcnOfLogger)).
72-
dropWhile(f -> f.getClassName().equals(fqcnOfLogger)).findFirst()).get().toStackTraceElement();
71+
return stackWalker.walk(
72+
s -> s.dropWhile(f -> !f.getClassName().equals(fqcnOfLogger)) // drop the top frames until we reach the logger
73+
.dropWhile(f -> f.getClassName().equals(fqcnOfLogger)) // drop the logger frames
74+
.findFirst())
75+
.get()
76+
.toStackTraceElement();
7377
}
7478

7579
public StackTraceElement getStackTraceElement(final int depth) {

log4j-api-java9/src/test/java/org/apache/logging/log4j/util/StackLocatorTest.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@
1616
*/
1717
package org.apache.logging.log4j.util;
1818

19-
import java.util.Stack;
20-
2119
import org.junit.BeforeClass;
2220
import org.junit.Test;
2321
import org.junit.runner.RunWith;
2422
import org.junit.runners.BlockJUnit4ClassRunner;
2523
import org.junit.runners.ParentRunner;
26-
import static org.junit.Assert.*;
24+
25+
import java.util.Stack;
26+
27+
import static org.junit.Assert.assertEquals;
28+
import static org.junit.Assert.assertNotNull;
29+
import static org.junit.Assert.assertSame;
2730

2831
@RunWith(BlockJUnit4ClassRunner.class)
2932
public class StackLocatorTest {
@@ -91,6 +94,47 @@ public void testLocateClass() {
9194
assertEquals("Incorrect class", this.getClass(), clazz);
9295
}
9396

97+
private final class Foo {
98+
99+
private StackTraceElement foo() {
100+
return new Bar().bar();
101+
}
102+
103+
}
104+
105+
private final class Bar {
106+
107+
private StackTraceElement bar() {
108+
return baz();
109+
}
110+
111+
private StackTraceElement baz() {
112+
return quux();
113+
}
114+
115+
}
116+
117+
private StackTraceElement quux() {
118+
return stackLocator.calcLocation("org.apache.logging.log4j.util.StackLocatorTest$Bar");
119+
}
120+
121+
@Test
122+
public void testCalcLocation() {
123+
/*
124+
* We are setting up a stack trace that looks like:
125+
* - org.apache.logging.log4j.util.StackLocatorTest#quux(line:118)
126+
* - org.apache.logging.log4j.util.StackLocatorTest$Bar#baz(line:112)
127+
* - org.apache.logging.log4j.util.StackLocatorTest$Bar#bar(line:108)
128+
* - org.apache.logging.log4j.util.StackLocatorTest$Foo(line:100)
129+
*
130+
* We are pretending that org.apache.logging.log4j.util.StackLocatorTest$Bar is the logging class, and
131+
* org.apache.logging.log4j.util.StackLocatorTest$Foo is where the log line emanated.
132+
*/
133+
final StackTraceElement element = new Foo().foo();
134+
assertEquals("org.apache.logging.log4j.util.StackLocatorTest$Foo", element.getClassName());
135+
assertEquals(100, element.getLineNumber());
136+
}
137+
94138
class ClassLocator {
95139

96140
public Class<?> locateClass() {

0 commit comments

Comments
 (0)