Repository: logging-log4j2
Updated Branches:
  refs/heads/master 6d7adb992 -> abc0f9483


LOG4J2-1176 fixed some memory leaks caused by objects being retained in
the ParameterizedMessage objects kept in the StatusLogger's bounded
queue of StatusData objects.

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

Branch: refs/heads/master
Commit: abc0f9483b897f53d18362c5498c4b13ee7b48d3
Parents: 6d7adb9
Author: rpopma <rpo...@apache.org>
Authored: Sun Nov 1 20:54:01 2015 +0900
Committer: rpopma <rpo...@apache.org>
Committed: Sun Nov 1 20:54:01 2015 +0900

----------------------------------------------------------------------
 .../ParameterizedNoReferenceMessageFactory.java | 61 ++++++++++++++++++++
 .../logging/log4j/status/StatusLogger.java      | 13 +++--
 2 files changed, 70 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/abc0f948/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java
new file mode 100644
index 0000000..413227e
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java
@@ -0,0 +1,61 @@
+/*
+ * 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.message;
+
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Specialized {@link ParameterizedMessageFactory} that creates {@link 
ParameterizedMessage} objects that do not retain
+ * a reference to the parameter object.
+ * <p>
+ * Intended for use by the {@link StatusLogger}: this logger retains a queue 
of recently logged messages in memory,
+ * causing memory leaks in web applications. (LOG4J2-1176)
+ * </p>
+ * <p>
+ * This class is immutable.
+ * </p>
+ */
+public final class ParameterizedNoReferenceMessageFactory extends 
AbstractMessageFactory {
+
+    /**
+     * Instance of ParameterizedStatusMessageFactory.
+     */
+    public static final ParameterizedNoReferenceMessageFactory INSTANCE = new 
ParameterizedNoReferenceMessageFactory();
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Creates {@link ParameterizedMessage} instances.
+     * 
+     * @param message The message pattern.
+     * @param params The message parameters.
+     * @return The Message.
+     *
+     * @see MessageFactory#newMessage(String, Object...)
+     */
+    @Override
+    public Message newMessage(final String message, final Object... params) {
+        if (params == null) {
+            return new ParameterizedMessage(message, null);
+        }
+        String[] stringParams = new String[params.length];
+        for (int i = 0; i < stringParams.length; i++) {
+            stringParams[i] = String.valueOf(params[i]);
+        }
+        return new ParameterizedMessage(message, stringParams);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/abc0f948/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
index fb015f1..1ce7efd 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
@@ -32,6 +32,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.message.ParameterizedNoReferenceMessageFactory;
 import org.apache.logging.log4j.simple.SimpleLogger;
 import org.apache.logging.log4j.spi.AbstractLogger;
 import org.apache.logging.log4j.util.PropertiesUtil;
@@ -58,7 +60,9 @@ public final class StatusLogger extends AbstractLogger {
 
     private static final String DEFAULT_STATUS_LEVEL = 
PROPS.getStringProperty("log4j2.StatusLogger.level");
 
-    private static final StatusLogger STATUS_LOGGER = new StatusLogger();
+    // LOG4J2-1176: normal parameterized message remembers param object, 
causing memory leaks.
+    private static final StatusLogger STATUS_LOGGER = new 
StatusLogger(StatusLogger.class.getName(),
+            ParameterizedNoReferenceMessageFactory.INSTANCE);
 
     private final SimpleLogger logger;
 
@@ -76,9 +80,10 @@ public final class StatusLogger extends AbstractLogger {
 
     private int listenersLevel;
 
-    private StatusLogger() {
-        this.logger = new SimpleLogger("StatusLogger", Level.ERROR, false, 
true, false, false, Strings.EMPTY, null,
-                PROPS, System.err);
+    private StatusLogger(String name, MessageFactory messageFactory) {
+        super(name, messageFactory);
+        this.logger = new SimpleLogger("StatusLogger", Level.ERROR, false, 
true, false, false, Strings.EMPTY,
+                messageFactory, PROPS, System.err);
         this.listenersLevel = Level.toLevel(DEFAULT_STATUS_LEVEL, 
Level.WARN).intLevel();
     }
 

Reply via email to