Index: src/main/java/org/apache/logging/log4j/message/FormattedMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/FormattedMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/FormattedMessage.java (working copy) @@ -46,12 +46,11 @@ this.messagePattern = messagePattern; this.argArray = arguments; this.throwable = throwable; + getFormattedMessage(); // LOG4J2-763 take snapshot of parameters at message construction time } public FormattedMessage(final String messagePattern, final Object[] arguments) { - this.messagePattern = messagePattern; - this.argArray = arguments; - this.throwable = null; + this(messagePattern, arguments, null); } /** @@ -60,9 +59,7 @@ * @param arg The parameter. */ public FormattedMessage(final String messagePattern, final Object arg) { - this.messagePattern = messagePattern; - this.argArray = new Object[] {arg}; - this.throwable = null; + this(messagePattern, new Object[] {arg}, null); } /** Index: src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java (working copy) @@ -78,6 +78,7 @@ this.baseName = baseName; this.resourceBundle = null; this.locale = locale; + getFormattedMessage(); // LOG4J2-763 take snapshot of parameters at message construction time } public LocalizedMessage(final ResourceBundle bundle, final Locale locale, final String key, @@ -88,6 +89,7 @@ this.baseName = null; this.resourceBundle = bundle; this.locale = locale; + getFormattedMessage(); // LOG4J2-763 take snapshot of parameters at message construction time } public LocalizedMessage(final Locale locale, final String key, final Object[] arguments) { Index: src/main/java/org/apache/logging/log4j/message/MapMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/MapMessage.java (revision 1616259) +++ src/main/java/org/apache/logging/log4j/message/MapMessage.java (working copy) @@ -26,6 +26,11 @@ /** * Represents a Message that consists of a Map. + *

+ * Thread-safety note: the contents of this message can be modified after construction. + * When using asynchronous loggers and appenders it is not recommended to modify this message after the message is + * logged, because it is undefined whether the logged message string will contain the old values or the modified + * values. */ public class MapMessage implements MultiformatMessage { /** Index: src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java (working copy) @@ -49,6 +49,7 @@ if (arguments != null && arguments.length > 0 && arguments[arguments.length - 1] instanceof Throwable) { this.throwable = (Throwable) arguments[arguments.length - 1]; } + getFormattedMessage(); // LOG4J2-763 take snapshot of parameters at message construction time } /** Index: src/main/java/org/apache/logging/log4j/message/ObjectMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/ObjectMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/ObjectMessage.java (working copy) @@ -29,6 +29,7 @@ private static final long serialVersionUID = -5903272448334166185L; private transient Object obj; + private final String objectString; /** * Create the ObjectMessage. @@ -39,6 +40,9 @@ obj = "null"; } this.obj = obj; + + // LOG4J2-763: take snapshot of parameters at message construction time + objectString = String.valueOf(obj); } /** @@ -47,7 +51,7 @@ */ @Override public String getFormattedMessage() { - return obj.toString(); + return objectString; } /** @@ -56,7 +60,7 @@ */ @Override public String getFormat() { - return obj.toString(); + return objectString; } /** @@ -89,7 +93,7 @@ @Override public String toString() { - return "ObjectMessage[obj=" + obj.toString() + ']'; + return "ObjectMessage[obj=" + objectString + ']'; } private void writeObject(final ObjectOutputStream out) throws IOException { Index: src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java (working copy) @@ -48,6 +48,7 @@ if (arguments != null && arguments.length > 0 && arguments[arguments.length - 1] instanceof Throwable) { this.throwable = (Throwable) arguments[arguments.length - 1]; } + getFormattedMessage(); // LOG4J2-763 take snapshot of parameters at message construction time } /** Index: src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java (working copy) @@ -22,6 +22,11 @@ /** * Represents a Message that conforms to an RFC 5424 StructuredData element along with the syslog message. + *

+ * Thread-safety note: the contents of this message can be modified after construction. + * When using asynchronous loggers and appenders it is not recommended to modify this message after the message is + * logged, because it is undefined whether the logged message string will contain the old values or the modified + * values. * * @see RFC 5424 */ Index: src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java =================================================================== --- src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java (revision 1616228) +++ src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java (working copy) @@ -38,9 +38,7 @@ private static final ThreadInfoFactory FACTORY; private volatile Map threads; - private final String title; - private String formattedMessage; static { @@ -61,7 +59,10 @@ */ public ThreadDumpMessage(final String title) { this.title = title == null ? Strings.EMPTY : title; - threads = FACTORY.createThreadInfo(); + this.threads = FACTORY.createThreadInfo(); + + // LOG4J2-763: take snapshot of parameters at message construction time + this.formattedMessage = getFormattedMessage(); } private ThreadDumpMessage(final String formattedMsg, final String title) {