LOG4J2-1334 MutableLogEvent and ReusableLogEventFactory improvements - better comments - use size constants defined in Constants - trim message size back to max in clear() - implement ThreadNameCachingStrategy
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/a743e8ee Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/a743e8ee Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/a743e8ee Branch: refs/heads/LOG4J2-1365 Commit: a743e8ee5705ed4188ef2f8dcc7052c1ff3378c4 Parents: 7cbc43f Author: rpopma <[email protected]> Authored: Sun Apr 17 14:34:21 2016 +0900 Committer: rpopma <[email protected]> Committed: Sun Apr 17 14:34:21 2016 +0900 ---------------------------------------------------------------------- .../log4j/core/impl/MutableLogEvent.java | 33 ++++++++++++-------- .../core/impl/ReusableLogEventFactory.java | 23 ++++++++------ 2 files changed, 33 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a743e8ee/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java index 3dce409..e86c553 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java @@ -1,5 +1,9 @@ package org.apache.logging.log4j.core.impl; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Map; + import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; @@ -8,20 +12,13 @@ import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.ReusableMessage; import org.apache.logging.log4j.message.SimpleMessage; -import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.Strings; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.util.Map; - /** * Mutable implementation of the {@code LogEvent} interface. * @since 2.6 */ public class MutableLogEvent implements LogEvent, ReusableMessage { - private static final int INITIAL_REUSABLE_MESSAGE_SIZE = size("log4j.initialReusableMsgSize", 128); - private static final int MAX_REUSABLE_MESSAGE_SIZE = size("log4j.maxReusableMsgSize", (128 * 2 + 2) * 2 + 2); private static final Object[] PARAMS = new Object[0]; private static final Message EMPTY = new SimpleMessage(Strings.EMPTY); @@ -44,10 +41,6 @@ public class MutableLogEvent implements LogEvent, ReusableMessage { private long nanoTime; private StringBuilder messageText; - private static int size(final String property, final int defaultValue) { - return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue); - } - /** * Initialize the fields of this {@code MutableLogEvent} from another event. * Similar in purpose and usage as {@link org.apache.logging.log4j.core.impl.Log4jLogEvent.LogEventProxy}, @@ -88,7 +81,13 @@ public class MutableLogEvent implements LogEvent, ReusableMessage { source = null; contextMap = null; contextStack = null; - // threadName = null; // THreadName should not be cleared + + // ThreadName should not be cleared: this field is set in the ReusableLogEventFactory + // where this instance is kept in a ThreadLocal, so it usually does not change. + // threadName = null; // no need to clear threadName + + trimMessageText(); + // primitive fields that cannot be cleared: //timeMillis; //threadId; @@ -98,6 +97,14 @@ public class MutableLogEvent implements LogEvent, ReusableMessage { //nanoTime; } + // ensure that excessively long char[] arrays are not kept in memory forever + private void trimMessageText() { + if (messageText != null && messageText.length() > Constants.MAX_REUSABLE_MESSAGE_SIZE) { + messageText.setLength(Constants.MAX_REUSABLE_MESSAGE_SIZE); + messageText.trimToSize(); + } + } + @Override public String getLoggerFqcn() { return loggerFqcn; @@ -158,7 +165,7 @@ public class MutableLogEvent implements LogEvent, ReusableMessage { if (messageText == null) { // Should never happen: // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false - messageText = new StringBuilder(INITIAL_REUSABLE_MESSAGE_SIZE); + messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE); } messageText.setLength(0); return messageText; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a743e8ee/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java index 2912d91..f396a4c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java @@ -16,26 +16,28 @@ */ package org.apache.logging.log4j.core.impl; +import java.util.List; + import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.async.ThreadNameCachingStrategy; import org.apache.logging.log4j.core.config.Property; import org.apache.logging.log4j.core.util.Clock; import org.apache.logging.log4j.core.util.ClockFactory; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.TimestampMessage; -import java.util.List; - /** * Garbage-free LogEventFactory that reuses a single mutable log event. * @since 2.6 */ public class ReusableLogEventFactory implements LogEventFactory { + private static final ThreadNameCachingStrategy THREAD_NAME_CACHING_STRATEGY = ThreadNameCachingStrategy.create(); + private static final Clock CLOCK = ClockFactory.getClock(); private static ThreadLocal<MutableLogEvent> mutableLogEventThreadLocal = new ThreadLocal<>(); - private static final Clock CLOCK = ClockFactory.getClock(); /** * Creates a log event. * @@ -55,12 +57,14 @@ public class ReusableLogEventFactory implements LogEventFactory { MutableLogEvent result = mutableLogEventThreadLocal.get(); if (result == null) { result = new MutableLogEvent(); + + // usually no need to re-initialize thread-specific fields since the event is stored in a ThreadLocal result.setThreadId(Thread.currentThread().getId()); - result.setThreadName(Thread.currentThread().getName()); + result.setThreadName(Thread.currentThread().getName()); // Thread.getName() allocates Objects on each call result.setThreadPriority(Thread.currentThread().getPriority()); mutableLogEventThreadLocal.set(result); } - result.clear(); + result.clear(); // ensure any previously cached values (thrownProxy, source, etc.) are cleared result.setLoggerName(loggerName); result.setMarker(marker); @@ -75,11 +79,10 @@ public class ReusableLogEventFactory implements LogEventFactory { : CLOCK.currentTimeMillis()); result.setNanoTime(Log4jLogEvent.getNanoClock().nanoTime()); - // TODO -// result.setEndOfBatch(); -// result.setIncludeLocation(); -// result.setSource(); - //return new Log4jLogEvent(loggerName, marker, fqcn, level, data, properties, t); + if (THREAD_NAME_CACHING_STRATEGY == ThreadNameCachingStrategy.UNCACHED) { + result.setThreadName(Thread.currentThread().getName()); // Thread.getName() allocates Objects on each call + result.setThreadPriority(Thread.currentThread().getPriority()); + } return result; } }
