You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/04/17 15:17:02 UTC

[2/2] logging-log4j2 git commit: LOG4J2-1334 improved and added gc-free unit tests:

LOG4J2-1334 improved and added gc-free unit tests:

- Move shared logic to new class GcFreeLoggingTestUtil
- Renamed GcFreeLoggingTest to GcFreeAsynchronousLoggingTest
- Added GcFreeSynchronousLoggingTest
- Added GcFreeMixedSyncAsyncLoggingTest with config gcFreeMixedSyncAsyncLogging.xml


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/8ebed8fc
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/8ebed8fc
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/8ebed8fc

Branch: refs/heads/master
Commit: 8ebed8fc0e87d0bc1a95b1a9851702ac336c9374
Parents: 3706664
Author: rpopma <rp...@apache.org>
Authored: Sun Apr 17 22:17:01 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Apr 17 22:17:01 2016 +0900

----------------------------------------------------------------------
 .../core/GcFreeAsynchronousLoggingTest.java     |  41 +++++
 .../logging/log4j/core/GcFreeLoggingTest.java   | 173 -------------------
 .../log4j/core/GcFreeLoggingTestUtil.java       | 169 ++++++++++++++++++
 .../core/GcFreeMixedSyncAyncLoggingTest.java    |  58 +++++++
 .../core/GcFreeSynchronousLoggingTest.java      |  58 +++++++
 .../resources/gcFreeMixedSyncAsyncLogging.xml   |  71 ++++++++
 6 files changed, 397 insertions(+), 173 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeAsynchronousLoggingTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeAsynchronousLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeAsynchronousLoggingTest.java
new file mode 100644
index 0000000..a74a35b
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeAsynchronousLoggingTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core;
+
+import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
+import org.junit.Test;
+
+/**
+ * Verifies steady state logging is GC-free.
+ *
+ * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
+ */
+public class GcFreeAsynchronousLoggingTest {
+
+    @Test
+    public void testNoAllocationDuringSteadyStateLogging() throws Throwable {
+        GcFreeLoggingTestUtil.runTest(getClass());
+    }
+
+    /**
+     * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
+     */
+    public static void main(String[] args) throws Exception {
+        System.setProperty("Log4jContextSelector", AsyncLoggerContextSelector.class.getName());
+        GcFreeLoggingTestUtil.executeLogging("gcFreeLogging.xml", GcFreeAsynchronousLoggingTest.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/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
deleted file mode 100644
index c66bae3..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core;
-
-import java.io.File;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.List;
-
-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.Test;
-
-import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
-import com.google.monitoring.runtime.instrumentation.Sampler;
-
-import static org.junit.Assert.*;
-
-/**
- * Verifies steady state logging is GC-free.
- *
- * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
- */
-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) {
-            return;
-        }
-        final String javaHome = System.getProperty("java.home");
-        final String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
-        final String classpath = System.getProperty("java.class.path");
-        final String javaagent = "-javaagent:" + agentJar();
-
-        final File tempFile = File.createTempFile("allocations", ".txt");
-        tempFile.deleteOnExit();
-
-        final ProcessBuilder builder = new ProcessBuilder( //
-                javaBin, javaagent, "-cp", classpath, GcFreeLoggingTest.class.getName());
-        builder.redirectError(ProcessBuilder.Redirect.to(tempFile));
-        builder.redirectOutput(ProcessBuilder.Redirect.to(tempFile));
-        final Process process = builder.start();
-        process.waitFor();
-        process.exitValue();
-
-        final List<String> lines = Files.readAllLines(tempFile.toPath(), Charset.defaultCharset());
-        assertEquals("FATAL o.a.l.l.c.GcFreeLoggingTest [main]  This message is logged to the console",
-                lines.get(0));
-
-        for (int i = 1; i < lines.size(); i++) {
-            final String line = lines.get(i);
-            assertFalse(line, line.contains("allocated") || line.contains("array"));
-        }
-    }
-
-    /**
-     * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
-     */
-    public static void main(String[] args) throws Exception {
-        System.setProperty("log4j2.enable.threadlocals", "true");
-        System.setProperty("log4j2.is.webapp", "false");
-        System.setProperty("log4j.configurationFile", "gcFreeLogging.xml");
-        System.setProperty("Log4jContextSelector", AsyncLoggerContextSelector.class.getName());
-
-        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());
-        logger.debug("debug not set");
-        logger.fatal("This message is logged to the console");
-        logger.error("Sample error message");
-        logger.error("Test parameterized message {}", "param");
-
-        // BlockingWaitStrategy uses ReentrantLock which allocates Node objects. Ignore this.
-        final String[] exclude = new String[] {
-                "java/util/concurrent/locks/AbstractQueuedSynchronizer$Node", //
-                "com/google/monitoring/runtime/instrumentation/Sampler", //
-        };
-        final Sampler sampler = new Sampler() {
-            public void sampleAllocation(int count, String desc, Object newObj, long size) {
-                for (int i = 0; i < exclude.length; i++) {
-                    if (exclude[i].equals(desc)) {
-                        return; // exclude
-                    }
-                }
-                System.err.println("I just allocated the object " + newObj +
-                        " of type " + desc + " whose size is " + size);
-                if (count != -1) {
-                    System.err.println("It's an array of size " + count);
-                }
-
-                // show a stack trace to see which line caused allocation
-                new RuntimeException().printStackTrace();
-            }
-        };
-        Thread.sleep(500);
-        AllocationRecorder.addSampler(sampler);
-
-        // 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");
-            logger.error("Test parameterized message {}{}{}", "param", "param2", "abc");
-        }
-        Thread.sleep(50);
-        AllocationRecorder.removeSampler(sampler);
-        Thread.sleep(100);
-    }
-
-    private static File agentJar() {
-        final String name = AllocationRecorder.class.getName();
-        final URL url = AllocationRecorder.class.getResource("/" + name.replace('.', '/').concat(".class"));
-        if (url == null) {
-            throw new IllegalStateException("Could not find url for " + name);
-        }
-        final String temp = url.toString();
-        final String path = temp.substring("jar:file:".length(), temp.indexOf('!'));
-        return new File(path);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTestUtil.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTestUtil.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTestUtil.java
new file mode 100644
index 0000000..e5b205c
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeLoggingTestUtil.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.*;
+import org.apache.logging.log4j.core.util.Constants;
+
+import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
+import com.google.monitoring.runtime.instrumentation.Sampler;
+
+import static org.junit.Assert.*;
+
+/**
+ * Utily methods for the GC-free logging tests.s.
+ */
+public class GcFreeLoggingTestUtil {
+
+    public static void executeLogging(final String configurationFile,
+            final Class<?> testClass) throws Exception {
+
+        System.setProperty("log4j2.enable.threadlocals", "true");
+        System.setProperty("log4j2.enable.direct.encoders", "true");
+        System.setProperty("log4j2.is.webapp", "false");
+        System.setProperty("log4j.configurationFile", configurationFile);
+
+        assertTrue("Constants.ENABLE_THREADLOCALS", Constants.ENABLE_THREADLOCALS);
+        assertTrue("Constants.ENABLE_DIRECT_ENCODERS", Constants.ENABLE_DIRECT_ENCODERS);
+        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 org.apache.logging.log4j.Logger logger = LogManager.getLogger(testClass.getName());
+        logger.debug("debug not set");
+        logger.fatal("This message is logged to the console");
+        logger.error("Sample error message");
+        logger.error("Test parameterized message {}", "param");
+        for (int i = 0; i < 128; i++) {
+            logger.debug("ensure all ringbuffer slots have been used once"); // allocate MutableLogEvent.messageText
+        }
+
+        // BlockingWaitStrategy uses ReentrantLock which allocates Node objects. Ignore this.
+        final String[] exclude = new String[] {
+                "java/util/concurrent/locks/AbstractQueuedSynchronizer$Node", //
+                "com/google/monitoring/runtime/instrumentation/Sampler", //
+        };
+        final Sampler sampler = new Sampler() {
+            public void sampleAllocation(int count, String desc, Object newObj, long size) {
+                for (int i = 0; i < exclude.length; i++) {
+                    if (exclude[i].equals(desc)) {
+                        return; // exclude
+                    }
+                }
+                System.err.println("I just allocated the object " + newObj +
+                        " of type " + desc + " whose size is " + size);
+                if (count != -1) {
+                    System.err.println("It's an array of size " + count);
+                }
+
+                // show a stack trace to see which line caused allocation
+                new RuntimeException().printStackTrace();
+            }
+        };
+        Thread.sleep(500);
+        AllocationRecorder.addSampler(sampler);
+
+        // 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");
+            logger.error("Test parameterized message {}{}{}", "param", "param2", "abc");
+        }
+        Thread.sleep(50);
+        AllocationRecorder.removeSampler(sampler);
+        Thread.sleep(100);
+    }
+
+    public static void runTest(Class<?> cls) throws Exception {
+        final String javaHome = System.getProperty("java.home");
+        final String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
+        final String classpath = System.getProperty("java.class.path");
+        final String javaagent = "-javaagent:" + agentJar();
+
+        final File tempFile = File.createTempFile("allocations", ".txt");
+        tempFile.deleteOnExit();
+
+        final ProcessBuilder builder = new ProcessBuilder( //
+                javaBin, javaagent, "-cp", classpath, cls.getName());
+        builder.redirectError(ProcessBuilder.Redirect.to(tempFile));
+        builder.redirectOutput(ProcessBuilder.Redirect.to(tempFile));
+        final Process process = builder.start();
+        process.waitFor();
+        process.exitValue();
+
+        final String text = new String(Files.readAllBytes(tempFile.toPath()));
+        final List<String> lines = Files.readAllLines(tempFile.toPath(), Charset.defaultCharset());
+        final String className = cls.getSimpleName();
+        assertEquals(text, "FATAL o.a.l.l.c." + className + " [main]  This message is logged to the console",
+                lines.get(0));
+
+        final String LINESEP = System.getProperty("line.separator");
+        for (int i = 1; i < lines.size(); i++) {
+            final String line = lines.get(i);
+            assertFalse(i + ": " + line + LINESEP + text, line.contains("allocated") || line.contains("array"));
+        }
+    }
+
+    private static File agentJar() {
+        final String name = AllocationRecorder.class.getName();
+        final URL url = AllocationRecorder.class.getResource("/" + name.replace('.', '/').concat(".class"));
+        if (url == null) {
+            throw new IllegalStateException("Could not find url for " + name);
+        }
+        final String temp = url.toString();
+        final String path = temp.substring("jar:file:".length(), temp.indexOf('!'));
+        return new File(path);
+    }
+
+    public static class MyCharSeq implements CharSequence {
+        final String seq = GcFreeLoggingTestUtil.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!");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
new file mode 100644
index 0000000..e954640
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.core.util.Constants;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
+import com.google.monitoring.runtime.instrumentation.Sampler;
+
+import static org.junit.Assert.*;
+
+/**
+ * Verifies steady state mixed synchronous and asynchronous logging is GC-free.
+ *
+ * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
+ */
+public class GcFreeMixedSyncAyncLoggingTest {
+
+    // Ignore until mixed synchronous/asynchronous logging is gc-free
+    @Ignore
+    @Test
+    public void testNoAllocationDuringSteadyStateLogging() throws Throwable {
+        GcFreeLoggingTestUtil.runTest(getClass());
+    }
+
+    /**
+     * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
+     */
+    public static void main(String[] args) throws Exception {
+        System.setProperty("AsyncLoggerConfig.RingBufferSize", "128"); // minimum ringbuffer size
+        GcFreeLoggingTestUtil.executeLogging("gcFreeMixedSyncAsyncLogging.xml", GcFreeMixedSyncAyncLoggingTest.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
new file mode 100644
index 0000000..11dd182
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+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;
+import org.junit.Test;
+
+import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
+import com.google.monitoring.runtime.instrumentation.Sampler;
+
+import static org.junit.Assert.*;
+
+/**
+ * Verifies steady state synchronous logging is GC-free.
+ *
+ * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
+ */
+public class GcFreeSynchronousLoggingTest {
+
+    // Ignore until synchronous logging is gc-free
+    @Ignore
+    @Test
+    public void testNoAllocationDuringSteadyStateLogging() throws Throwable {
+        GcFreeLoggingTestUtil.runTest(getClass());
+    }
+
+    /**
+     * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
+     */
+    public static void main(String[] args) throws Exception {
+        GcFreeLoggingTestUtil.executeLogging("gcFreeLogging.xml", GcFreeSynchronousLoggingTest.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8ebed8fc/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
new file mode 100644
index 0000000..e4c0000
--- /dev/null
+++ b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="OFF">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %m%ex%n" />
+    </Console>
+    <File name="File" fileName="target/gcfreefileMixed.log" bufferedIO="false">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+    </File>
+    <RollingFile name="RollingFile" fileName="target/gcfreeRollingFileMixed.log"
+        filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+      <Policies>
+        <SizeBasedTriggeringPolicy size="50M" />
+      </Policies>
+    </RollingFile>
+    <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAFMixed.log" immediateFlush="false" append="false">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %ex%n</Pattern>
+      </PatternLayout>
+    </RandomAccessFile>
+    <RollingRandomAccessFile name="RollingRandomAccessFile"
+        fileName="target/gcfreeRRAFMixed.log"
+        filePattern="target/afterRollover-%i.log" append="false"
+        immediateFlush="false">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
+      </PatternLayout>
+      <Policies>
+        <SizeBasedTriggeringPolicy size="50 M"/>
+      </Policies>
+    </RollingRandomAccessFile>
+    <MemoryMappedFile name="MemoryMappedFile"
+        fileName="target/gcfreemmapMixed.log"
+        immediateFlush="false" append="false">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
+      </PatternLayout>
+    </MemoryMappedFile>
+    <RandomAccessFile name="RandomAccessFileGelf" fileName="target/gcfreeMixed.json" immediateFlush="false" append="false">
+       <GelfLayout compressionType="OFF"/>
+    </RandomAccessFile>
+  </Appenders>
+  <Loggers>
+    <AsyncLogger name="org.apache.logging.log4j.core.GcFreeMixedSyncAyncLoggingTest"
+        level="info" includeLocation="false">
+      <appender-ref ref="Console" level="FATAL" />
+      <appender-ref ref="File"/>
+      <appender-ref ref="RandomAccessFile"/>
+      <appender-ref ref="RollingRandomAccessFile"/>
+      <appender-ref ref="File"/>
+      <appender-ref ref="RollingFile"/>
+      <appender-ref ref="MemoryMappedFile"/>
+      <appender-ref ref="RandomAccessFileGelf"/>
+    </AsyncLogger>
+    <Root level="info" includeLocation="false">
+      <appender-ref ref="Console" level="FATAL" />
+      <appender-ref ref="File"/>
+      <appender-ref ref="RandomAccessFile"/>
+      <appender-ref ref="RollingRandomAccessFile"/>
+      <appender-ref ref="File"/>
+      <appender-ref ref="RollingFile"/>
+      <appender-ref ref="MemoryMappedFile"/>
+      <appender-ref ref="RandomAccessFileGelf"/>
+    </Root>
+  </Loggers>
+</Configuration>