1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache license, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the license for the specific language governing permissions and 15 * limitations under the license. 16 */ 17 package org.apache.logging.log4j.message; 18 19 import org.apache.logging.log4j.status.StatusLogger; 20 21 /** 22 * Creates {@link FormattedMessage} instances for {@link MessageFactory2} methods (and {@link MessageFactory} by 23 * extension.) 24 * <p> 25 * Creates {@link SimpleMessage} objects that do not retain a reference to the parameter object. 26 * </p> 27 * <p> 28 * Intended for use by the {@link StatusLogger}: this logger retains a queue of recently logged messages in memory, 29 * causing memory leaks in web applications. (LOG4J2-1176) 30 * </p> 31 * <p> 32 * This class is immutable. 33 * </p> 34 * <h4>Note to implementors</h4> 35 * <p> 36 * This class does <em>not</em> implement any {@link MessageFactory2} methods and lets the superclass funnel those calls 37 * through {@link #newMessage(String, Object...)}. 38 * </p> 39 */ 40 public final class ParameterizedNoReferenceMessageFactory extends AbstractMessageFactory { 41 private static final long serialVersionUID = 5027639245636870500L; 42 43 /** 44 * Message implementation that only keeps a reference to the error text and the error (if any), not to the 45 * message parameters, in order to avoid memory leaks. This addresses LOG4J2-1368. 46 * @since 2.6 47 */ 48 static class StatusMessage implements Message { 49 private static final long serialVersionUID = 4199272162767841280L; 50 private final String formattedMessage; 51 private final Throwable throwable; 52 53 public StatusMessage(final String formattedMessage, final Throwable throwable) { 54 this.formattedMessage = formattedMessage; 55 this.throwable = throwable; 56 } 57 58 @Override 59 public String getFormattedMessage() { 60 return formattedMessage; 61 } 62 63 @Override 64 public String getFormat() { 65 return formattedMessage; 66 } 67 68 @Override 69 public Object[] getParameters() { 70 return null; 71 } 72 73 @Override 74 public Throwable getThrowable() { 75 return throwable; 76 } 77 } 78 79 /** 80 * Constructs a message factory with default flow strings. 81 */ 82 public ParameterizedNoReferenceMessageFactory() { 83 } 84 85 /** 86 * Instance of ParameterizedStatusMessageFactory. 87 */ 88 public static final ParameterizedNoReferenceMessageFactory INSTANCE = new ParameterizedNoReferenceMessageFactory(); 89 90 /** 91 * Creates {@link SimpleMessage} instances containing the formatted parameterized message string. 92 * 93 * @param message The message pattern. 94 * @param params The message parameters. 95 * @return The Message. 96 * 97 * @see MessageFactory#newMessage(String, Object...) 98 */ 99 @Override 100 public Message newMessage(final String message, final Object... params) { 101 if (params == null) { 102 return new SimpleMessage(message); 103 } 104 final ParameterizedMessage msg = new ParameterizedMessage(message, params); 105 return new StatusMessage(msg.getFormattedMessage(), msg.getThrowable()); 106 } 107 }