LOG4J2-1326 ensure that in garbage-free mode, logging a CharSequence does not create temporary objects: CharSequence.toString() should NOT be called
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/2bf358d2 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/2bf358d2 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/2bf358d2 Branch: refs/heads/LOG4J2-1356 Commit: 2bf358d2909fcb6a392648c73fba71d5066a9f26 Parents: 7b63d6c Author: rpopma <[email protected]> Authored: Thu Apr 7 22:18:57 2016 +0900 Committer: rpopma <[email protected]> Committed: Thu Apr 7 22:18:57 2016 +0900 ---------------------------------------------------------------------- .../logging/log4j/core/GcFreeLoggingTest.java | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/2bf358d2/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java index eafdac5..b5761f8 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java @@ -24,6 +24,7 @@ import com.google.monitoring.runtime.instrumentation.AllocationRecorder; import com.google.monitoring.runtime.instrumentation.Sampler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.MarkerManager; import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector; import org.apache.logging.log4j.core.util.Constants; import org.junit.Ignore; @@ -38,6 +39,31 @@ import static org.junit.Assert.*; */ public class GcFreeLoggingTest { + private static class MyCharSeq implements CharSequence { + final String seq = GcFreeLoggingTest.class.toString(); + + @Override + public int length() { + return seq.length(); + } + + @Override + public char charAt(final int index) { + return seq.charAt(index); + } + + @Override + public CharSequence subSequence(final int start, final int end) { + return seq.subSequence(start, end); + } + + @Override + public String toString() { + System.err.println("TEMP OBJECT CREATED!"); + throw new IllegalStateException("TEMP OBJECT CREATED!"); + } + } + @Test public void testNoAllocationDuringSteadyStateLogging() throws Throwable { if (!Constants.ENABLE_THREADLOCALS || !Constants.ENABLE_DIRECT_ENCODERS) { @@ -77,6 +103,9 @@ public class GcFreeLoggingTest { assertTrue("Constants.ENABLE_THREADLOCALS", Constants.ENABLE_THREADLOCALS); assertFalse("Constants.IS_WEB_APP", Constants.IS_WEB_APP); + MyCharSeq myCharSeq = new MyCharSeq(); + MarkerManager.getMarker("test"); // initial creation, value is cached + // initialize LoggerContext etc. // This is not steady-state logging and will allocate objects. final Logger logger = LogManager.getLogger(GcFreeLoggingTest.class.getName()); @@ -113,6 +142,8 @@ public class GcFreeLoggingTest { // now do some steady-state logging final int ITERATIONS = 5; for (int i = 0; i < ITERATIONS; i++) { + logger.error(myCharSeq); + logger.error(MarkerManager.getMarker("test"), myCharSeq); logger.error("Test message"); logger.error("Test parameterized message {}", "param"); logger.error("Test parameterized message {}{}", "param", "param2"); @@ -120,6 +151,7 @@ public class GcFreeLoggingTest { } Thread.sleep(50); AllocationRecorder.removeSampler(sampler); + Thread.sleep(100); } private static File agentJar() {
