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 2013/07/12 00:01:23 UTC

svn commit: r1502380 - in /logging/log4j/log4j2/trunk: core/src/main/java/org/apache/logging/log4j/core/async/ src/changes/

Author: rpopma
Date: Thu Jul 11 22:01:23 2013
New Revision: 1502380

URL: http://svn.apache.org/r1502380
Log:
LOG4J2-304: fixed Async Loggers memory leak

Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java?rev=1502380&r1=1502379&r2=1502380&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigHelper.java Thu Jul 11 22:01:23 2013
@@ -85,7 +85,8 @@ class AsyncLoggerConfigHelper {
      */
     private final EventTranslator<Log4jEventWrapper> translator = new EventTranslator<Log4jEventWrapper>() {
         @Override
-        public void translateTo(final Log4jEventWrapper event, final long sequence) {
+        public void translateTo(final Log4jEventWrapper event,
+                final long sequence) {
             event.event = currentLogEvent.get();
             event.loggerConfig = asyncLoggerConfig;
         }
@@ -120,7 +121,8 @@ class AsyncLoggerConfigHelper {
     }
 
     private static WaitStrategy createWaitStrategy() {
-        final String strategy = System.getProperty("AsyncLoggerConfig.WaitStrategy");
+        final String strategy = System
+                .getProperty("AsyncLoggerConfig.WaitStrategy");
         LOGGER.debug("property AsyncLoggerConfig.WaitStrategy={}", strategy);
         if ("Sleep".equals(strategy)) {
             LOGGER.debug("disruptor event handler uses SleepingWaitStrategy");
@@ -158,15 +160,15 @@ class AsyncLoggerConfigHelper {
     }
 
     private static ExceptionHandler getExceptionHandler() {
-        final String cls = System.getProperty("AsyncLoggerConfig.ExceptionHandler");
+        final String cls = System
+                .getProperty("AsyncLoggerConfig.ExceptionHandler");
         if (cls == null) {
             LOGGER.debug("No AsyncLoggerConfig.ExceptionHandler specified");
             return null;
         }
         try {
             @SuppressWarnings("unchecked")
-            final
-            Class<? extends ExceptionHandler> klass = (Class<? extends ExceptionHandler>) Class
+            final Class<? extends ExceptionHandler> klass = (Class<? extends ExceptionHandler>) Class
                     .forName(cls);
             final ExceptionHandler result = klass.newInstance();
             LOGGER.debug("AsyncLoggerConfig.ExceptionHandler=" + result);
@@ -186,6 +188,15 @@ class AsyncLoggerConfigHelper {
     private static class Log4jEventWrapper {
         private AsyncLoggerConfig loggerConfig;
         private LogEvent event;
+
+        /**
+         * Release references held by ring buffer to allow objects to be
+         * garbage-collected.
+         */
+        public void clear() {
+            loggerConfig = null;
+            event = null;
+        }
     }
 
     /**
@@ -207,6 +218,7 @@ class AsyncLoggerConfigHelper {
                 final boolean endOfBatch) throws Exception {
             event.event.setEndOfBatch(endOfBatch);
             event.loggerConfig.asyncCallAppenders(event.event);
+            event.clear();
 
             // notify the BatchEventProcessor that the sequence has progressed.
             // Without this callback the sequence would not be progressed

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java?rev=1502380&r1=1502379&r2=1502380&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java Thu Jul 11 22:01:23 2013
@@ -66,8 +66,9 @@ public class RingBufferLogEvent implemen
     private boolean endOfBatch;
     private boolean includeLocation;
 
-    public void setValues(final AsyncLogger asyncLogger, final String loggerName,
-            final Marker marker, final String fqcn, final Level level, final Message data, final Throwable t,
+    public void setValues(final AsyncLogger asyncLogger,
+            final String loggerName, final Marker marker, final String fqcn,
+            final Level level, final Message data, final Throwable t,
             final Map<String, String> map, final ContextStack contextStack,
             final String threadName, final StackTraceElement location,
             final long currentTimeMillis) {
@@ -124,31 +125,26 @@ public class RingBufferLogEvent implemen
         this.includeLocation = includeLocation;
     }
 
-    // @Override
     @Override
     public String getLoggerName() {
         return loggerName;
     }
 
-    // @Override
     @Override
     public Marker getMarker() {
         return marker;
     }
 
-    // @Override
     @Override
     public String getFQCN() {
         return fqcn;
     }
 
-    // @Override
     @Override
     public Level getLevel() {
         return level;
     }
 
-    // @Override
     @Override
     public Message getMessage() {
         if (message == null) {
@@ -157,37 +153,31 @@ public class RingBufferLogEvent implemen
         return message;
     }
 
-    // @Override
     @Override
     public Throwable getThrown() {
         return thrown;
     }
 
-    // @Override
     @Override
     public Map<String, String> getContextMap() {
         return contextMap;
     }
 
-    // @Override
     @Override
     public ContextStack getContextStack() {
         return contextStack;
     }
 
-    // @Override
     @Override
     public String getThreadName() {
         return threadName;
     }
 
-    // @Override
     @Override
     public StackTraceElement getSource() {
         return location;
     }
 
-    // @Override
     @Override
     public long getMillis() {
         return currentTimeMillis;
@@ -202,7 +192,8 @@ public class RingBufferLogEvent implemen
      * @param strSubstitutor used to lookup values of variables in properties
      */
     public void mergePropertiesIntoContextMap(
-            final Map<Property, Boolean> properties, final StrSubstitutor strSubstitutor) {
+            final Map<Property, Boolean> properties,
+            final StrSubstitutor strSubstitutor) {
         if (properties == null) {
             return; // nothing to do
         }
@@ -221,4 +212,24 @@ public class RingBufferLogEvent implemen
         }
         contextMap = map;
     }
+
+    /**
+     * Release references held by ring buffer to allow objects to be
+     * garbage-collected.
+     */
+    public void clear() {
+        setValues(null, // asyncLogger
+                null, // loggerName
+                null, // marker
+                null, // fqcn
+                null, // level
+                null, // data
+                null, // t
+                null, // map
+                null, // contextStack
+                null, // threadName
+                null, // location
+                0 // currentTimeMillis
+        );
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java?rev=1502380&r1=1502379&r2=1502380&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventHandler.java Thu Jul 11 22:01:23 2013
@@ -41,6 +41,7 @@ public class RingBufferLogEventHandler i
     public void onEvent(final RingBufferLogEvent event, final long sequence,
             final boolean endOfBatch) throws Exception {
         event.execute(endOfBatch);
+        event.clear();
         
         // notify the BatchEventProcessor that the sequence has progressed.
         // Without this callback the sequence would not be progressed

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1502380&r1=1502379&r2=1502380&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Thu Jul 11 22:01:23 2013
@@ -20,6 +20,11 @@
     <title>Changes</title>
   </properties>
   <body>
+    <release version="2.0-beta9" date="soon, very soon" description="Bug fixes and enhancements">
+      <action issue="LOG4J2-304" dev="rpopma" type="fix">
+        Fixed Async Loggers memory leak.
+      </action>
+    </release>
     <release version="2.0-beta8" date="2013-07-10" description="Bug fixes and enhancements">
       <action issue="LOG4J2-270" dev="nickwilliams" type="update">
         Improved logging initialization in Servlet containers, especially Servlet 3.0 and newer where Log4j now