diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java index 5fcc6f6..a45ea38 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java @@ -20,6 +20,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.util.ObjectPool; +import org.apache.logging.log4j.core.util.StringBuilderPool; /** * Abstract base class for Layouts that result in a String. @@ -45,20 +47,8 @@ public abstract class AbstractStringLayout extends AbstractLayout { return null; } - protected static ThreadLocal newStringBuilderThreadLocal() { - return new ThreadLocal() { - @Override - protected StringBuilder initialValue() { - return new StringBuilder(DEFAULT_STRING_BUILDER_SIZE); - } - }; - } + protected StringBuilderPool pool = new StringBuilderPool(DEFAULT_STRING_BUILDER_SIZE); - protected static StringBuilder prepareStringBuilder(ThreadLocal threadLocal) { - final StringBuilder buf = threadLocal.get(); - buf.setLength(0); - return buf; - } /** * The charset for the formatted message. diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java index 9fb36b0..fda5c0c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java @@ -41,8 +41,6 @@ import org.apache.logging.log4j.status.StatusLogger; public class CsvLogEventLayout extends AbstractCsvLayout { private static final long serialVersionUID = 1L; - - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); public static CsvLogEventLayout createDefaultLayout() { return new CsvLogEventLayout(Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null); @@ -78,7 +76,7 @@ public class CsvLogEventLayout extends AbstractCsvLayout { @Override public String toSerializable(final LogEvent event) { - final StringBuilder buffer = prepareStringBuilder(strBuilder); + final StringBuilder buffer = pool.borrowObject(); try { // Revisit when 1.3 is out so that we do not need to create a new // printer for each event. @@ -101,6 +99,8 @@ public class CsvLogEventLayout extends AbstractCsvLayout { } catch (final IOException e) { StatusLogger.getLogger().error(event.toString(), e); return getFormat().getCommentMarker() + " " + e; + } finally { + pool.returnObject(buffer); } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java index bb0bc6e..a4d5c44 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java @@ -50,8 +50,6 @@ import org.apache.logging.log4j.status.StatusLogger; public class CsvParameterLayout extends AbstractCsvLayout { private static final long serialVersionUID = 1L; - - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); public static AbstractCsvLayout createDefaultLayout() { return new CsvParameterLayout(Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null); @@ -89,7 +87,7 @@ public class CsvParameterLayout extends AbstractCsvLayout { public String toSerializable(final LogEvent event) { final Message message = event.getMessage(); final Object[] parameters = message.getParameters(); - final StringBuilder buffer = prepareStringBuilder(strBuilder); + final StringBuilder buffer = pool.borrowObject(); try { // Revisit when 1.3 is out so that we do not need to create a new // printer for each event. @@ -100,6 +98,8 @@ public class CsvParameterLayout extends AbstractCsvLayout { } catch (final IOException e) { StatusLogger.getLogger().error(message, e); return getFormat().getCommentMarker() + " " + e; + } finally { + pool.returnObject(buffer); } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java index 6433f91..eaabb86 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java @@ -104,8 +104,6 @@ public final class GelfLayout extends AbstractStringLayout { private static final String QU = "\"_"; private static final long serialVersionUID = 1L; private static final BigDecimal TIME_DIVISOR = new BigDecimal(1000); - - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); @PluginFactory public static GelfLayout createLayout( @@ -192,37 +190,41 @@ public final class GelfLayout extends AbstractStringLayout { @Override public String toSerializable(final LogEvent event) { - final StringBuilder builder = prepareStringBuilder(strBuilder); - final JsonStringEncoder jsonEncoder = JsonStringEncoder.getInstance(); - builder.append('{'); - builder.append("\"version\":\"1.1\","); - builder.append("\"host\":\"").append(jsonEncoder.quoteAsString(toNullSafeString(host))).append(QC); - builder.append("\"timestamp\":").append(formatTimestamp(event.getTimeMillis())).append(C); - builder.append("\"level\":").append(formatLevel(event.getLevel())).append(C); - if (event.getThreadName() != null) { - builder.append("\"_thread\":\"").append(jsonEncoder.quoteAsString(event.getThreadName())).append(QC); - } - if (event.getLoggerName() != null) { - builder.append("\"_logger\":\"").append(jsonEncoder.quoteAsString(event.getLoggerName())).append(QC); - } + final StringBuilder builder = pool.borrowObject(); + try { + final JsonStringEncoder jsonEncoder = JsonStringEncoder.getInstance(); + builder.append('{'); + builder.append("\"version\":\"1.1\","); + builder.append("\"host\":\"").append(jsonEncoder.quoteAsString(toNullSafeString(host))).append(QC); + builder.append("\"timestamp\":").append(formatTimestamp(event.getTimeMillis())).append(C); + builder.append("\"level\":").append(formatLevel(event.getLevel())).append(C); + if (event.getThreadName() != null) { + builder.append("\"_thread\":\"").append(jsonEncoder.quoteAsString(event.getThreadName())).append(QC); + } + if (event.getLoggerName() != null) { + builder.append("\"_logger\":\"").append(jsonEncoder.quoteAsString(event.getLoggerName())).append(QC); + } - for (final KeyValuePair additionalField : additionalFields) { - builder.append(QU).append(jsonEncoder.quoteAsString(additionalField.getKey())).append("\":\"") - .append(jsonEncoder.quoteAsString(toNullSafeString(additionalField.getValue()))).append(QC); - } - for (final Map.Entry entry : event.getContextMap().entrySet()) { - builder.append(QU).append(jsonEncoder.quoteAsString(entry.getKey())).append("\":\"") - .append(jsonEncoder.quoteAsString(toNullSafeString(entry.getValue()))).append(QC); - } - if (event.getThrown() != null) { - builder.append("\"full_message\":\"").append(jsonEncoder.quoteAsString(formatThrowable(event.getThrown()))) - .append(QC); - } + for (final KeyValuePair additionalField : additionalFields) { + builder.append(QU).append(jsonEncoder.quoteAsString(additionalField.getKey())).append("\":\"") + .append(jsonEncoder.quoteAsString(toNullSafeString(additionalField.getValue()))).append(QC); + } + for (final Map.Entry entry : event.getContextMap().entrySet()) { + builder.append(QU).append(jsonEncoder.quoteAsString(entry.getKey())).append("\":\"") + .append(jsonEncoder.quoteAsString(toNullSafeString(entry.getValue()))).append(QC); + } + if (event.getThrown() != null) { + builder.append("\"full_message\":\"").append(jsonEncoder.quoteAsString(formatThrowable(event.getThrown()))) + .append(QC); + } - builder.append("\"short_message\":\"").append(jsonEncoder.quoteAsString(toNullSafeString(event.getMessage().getFormattedMessage()))) - .append(Q); - builder.append('}'); - return builder.toString(); + builder.append("\"short_message\":\"").append(jsonEncoder.quoteAsString(toNullSafeString(event.getMessage().getFormattedMessage()))) + .append(Q); + builder.append('}'); + return builder.toString(); + } finally { + pool.returnObject(builder); + } } private String toNullSafeString(final String s) { diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/HtmlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/HtmlLayout.java index a12ee47..3508287 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/HtmlLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/HtmlLayout.java @@ -63,8 +63,6 @@ public final class HtmlLayout extends AbstractStringLayout { public static final String DEFAULT_FONT_FAMILY = "arial,sans-serif"; private final long jvmStartTime = ManagementFactory.getRuntimeMXBean().getStartTime(); - - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); // Print no location info by default private final boolean locationInfo; @@ -132,80 +130,84 @@ public final class HtmlLayout extends AbstractStringLayout { */ @Override public String toSerializable(final LogEvent event) { - final StringBuilder sbuf = prepareStringBuilder(strBuilder); - - sbuf.append(Constants.LINE_SEPARATOR).append("").append(Constants.LINE_SEPARATOR); - - sbuf.append(""); - sbuf.append(event.getTimeMillis() - jvmStartTime); - sbuf.append("").append(Constants.LINE_SEPARATOR); - - final String escapedThread = Transform.escapeHtmlTags(event.getThreadName()); - sbuf.append(""); - sbuf.append(escapedThread); - sbuf.append("").append(Constants.LINE_SEPARATOR); - - sbuf.append(""); - if (event.getLevel().equals(Level.DEBUG)) { - sbuf.append(""); - sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); - sbuf.append(""); - } else if (event.getLevel().isMoreSpecificThan(Level.WARN)) { - sbuf.append(""); - sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); - sbuf.append(""); - } else { - sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); - } - sbuf.append("").append(Constants.LINE_SEPARATOR); + final StringBuilder sbuf = pool.borrowObject(); + try { - String escapedLogger = Transform.escapeHtmlTags(event.getLoggerName()); - if (escapedLogger.isEmpty()) { - escapedLogger = LoggerConfig.ROOT; - } - sbuf.append(""); - sbuf.append(escapedLogger); - sbuf.append("").append(Constants.LINE_SEPARATOR); + sbuf.append(Constants.LINE_SEPARATOR).append("").append(Constants.LINE_SEPARATOR); - if (locationInfo) { - final StackTraceElement element = event.getSource(); sbuf.append(""); - sbuf.append(Transform.escapeHtmlTags(element.getFileName())); - sbuf.append(':'); - sbuf.append(element.getLineNumber()); + sbuf.append(event.getTimeMillis() - jvmStartTime); sbuf.append("").append(Constants.LINE_SEPARATOR); - } - sbuf.append(""); - sbuf.append(Transform.escapeHtmlTags(event.getMessage().getFormattedMessage()).replaceAll(REGEXP, "
")); - sbuf.append("").append(Constants.LINE_SEPARATOR); - sbuf.append("").append(Constants.LINE_SEPARATOR); + final String escapedThread = Transform.escapeHtmlTags(event.getThreadName()); + sbuf.append(""); + sbuf.append(escapedThread); + sbuf.append("").append(Constants.LINE_SEPARATOR); - if (event.getContextStack() != null && !event.getContextStack().isEmpty()) { - sbuf.append(""); - sbuf.append("NDC: ").append(Transform.escapeHtmlTags(event.getContextStack().toString())); - sbuf.append("").append(Constants.LINE_SEPARATOR); - } + sbuf.append(""); + if (event.getLevel().equals(Level.DEBUG)) { + sbuf.append(""); + sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); + sbuf.append(""); + } else if (event.getLevel().isMoreSpecificThan(Level.WARN)) { + sbuf.append(""); + sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); + sbuf.append(""); + } else { + sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel()))); + } + sbuf.append("").append(Constants.LINE_SEPARATOR); - if (event.getContextMap() != null && !event.getContextMap().isEmpty()) { - sbuf.append(""); - sbuf.append("MDC: ").append(Transform.escapeHtmlTags(event.getContextMap().toString())); - sbuf.append("").append(Constants.LINE_SEPARATOR); - } + String escapedLogger = Transform.escapeHtmlTags(event.getLoggerName()); + if (escapedLogger.isEmpty()) { + escapedLogger = LoggerConfig.ROOT; + } + sbuf.append(""); + sbuf.append(escapedLogger); + sbuf.append("").append(Constants.LINE_SEPARATOR); - final Throwable throwable = event.getThrown(); - if (throwable != null) { - sbuf.append(""); - appendThrowableAsHtml(throwable, sbuf); - sbuf.append("").append(Constants.LINE_SEPARATOR); - } + if (locationInfo) { + final StackTraceElement element = event.getSource(); + sbuf.append(""); + sbuf.append(Transform.escapeHtmlTags(element.getFileName())); + sbuf.append(':'); + sbuf.append(element.getLineNumber()); + sbuf.append("").append(Constants.LINE_SEPARATOR); + } + + sbuf.append(""); + sbuf.append(Transform.escapeHtmlTags(event.getMessage().getFormattedMessage()).replaceAll(REGEXP, "
")); + sbuf.append("").append(Constants.LINE_SEPARATOR); + sbuf.append("").append(Constants.LINE_SEPARATOR); + + if (event.getContextStack() != null && !event.getContextStack().isEmpty()) { + sbuf.append(""); + sbuf.append("NDC: ").append(Transform.escapeHtmlTags(event.getContextStack().toString())); + sbuf.append("").append(Constants.LINE_SEPARATOR); + } + + if (event.getContextMap() != null && !event.getContextMap().isEmpty()) { + sbuf.append(""); + sbuf.append("MDC: ").append(Transform.escapeHtmlTags(event.getContextMap().toString())); + sbuf.append("").append(Constants.LINE_SEPARATOR); + } - return sbuf.toString(); + final Throwable throwable = event.getThrown(); + if (throwable != null) { + sbuf.append(""); + appendThrowableAsHtml(throwable, sbuf); + sbuf.append("").append(Constants.LINE_SEPARATOR); + } + + return sbuf.toString(); + } finally { + pool.returnObject(sbuf); + } } @Override diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java index e5b78d3..441e6c8 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java @@ -37,6 +37,7 @@ import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; import org.apache.logging.log4j.core.pattern.PatternFormatter; import org.apache.logging.log4j.core.pattern.PatternParser; import org.apache.logging.log4j.core.pattern.RegexReplacement; +import org.apache.logging.log4j.core.util.StringBuilderPool; /** * A flexible layout configurable with pattern string. @@ -81,8 +82,6 @@ public final class PatternLayout extends AbstractStringLayout { /** Key to identify pattern converters. */ public static final String KEY = "Converter"; - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); - /** * Initial converter for pattern. */ @@ -135,7 +134,7 @@ public final class PatternLayout extends AbstractStringLayout { this.alwaysWriteExceptions = alwaysWriteExceptions; this.noConsoleNoAnsi = noConsoleNoAnsi; if (patternSelector == null) { - serializer = new PatternSerializer(); + serializer = new PatternSerializer(pool); final PatternParser parser = createPatternParser(config); try { List list = parser.parse(pattern == null ? DEFAULT_CONVERSION_PATTERN : pattern, @@ -146,7 +145,7 @@ public final class PatternLayout extends AbstractStringLayout { } } else { this.formatters = null; - serializer = new PatternSelectorSerializer(); + serializer = new PatternSelectorSerializer(pool); } } @@ -282,15 +281,26 @@ public final class PatternLayout extends AbstractStringLayout { } private class PatternSerializer implements Serializer { + private final StringBuilderPool stringBuilderPool; + + public PatternSerializer(StringBuilderPool pool) { + stringBuilderPool = pool; + } + @Override public String toSerializable(final LogEvent event) { - final StringBuilder buf = strBuilder.get(); - buf.setLength(0); - final int len = formatters.length; - for (int i = 0; i < len; i++) { - formatters[i].format(event, buf); + final StringBuilder buf = stringBuilderPool.borrowObject(); + String str; + try { + buf.setLength(0); + final int len = formatters.length; + for (int i = 0; i < len; i++) { + formatters[i].format(event, buf); + } + str = buf.toString(); + } finally { + stringBuilderPool.returnObject(buf); } - String str = buf.toString(); if (replace != null) { str = replace.format(str); } @@ -299,16 +309,27 @@ public final class PatternLayout extends AbstractStringLayout { } private class PatternSelectorSerializer implements Serializer { + private final StringBuilderPool stringBuilderPool; + + public PatternSelectorSerializer(StringBuilderPool pool) { + stringBuilderPool = pool; + } + @Override public String toSerializable(final LogEvent event) { - final StringBuilder buf = strBuilder.get(); - buf.setLength(0); - PatternFormatter[] formatters = patternSelector.getFormatters(event); - final int len = formatters.length; - for (int i = 0; i < len; i++) { - formatters[i].format(event, buf); + final StringBuilder buf = stringBuilderPool.borrowObject(); + String str; + try { + buf.setLength(0); + PatternFormatter[] formatters = patternSelector.getFormatters(event); + final int len = formatters.length; + for (int i = 0; i < len; i++) { + formatters[i].format(event, buf); + } + str = buf.toString(); + } finally { + stringBuilderPool.returnObject(buf); } - String str = buf.toString(); if (replace != null) { str = replace.format(str); } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/Rfc5424Layout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/Rfc5424Layout.java index e062798..d8d8ebc 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/Rfc5424Layout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/Rfc5424Layout.java @@ -93,8 +93,6 @@ public final class Rfc5424Layout extends AbstractStringLayout { private static final int MINUTES_PER_HOUR = 60; private static final String COMPONENT_KEY = "RFC5424-Converter"; - - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); private final Facility facility; private final String defaultId; @@ -266,24 +264,28 @@ public final class Rfc5424Layout extends AbstractStringLayout { */ @Override public String toSerializable(final LogEvent event) { - final StringBuilder buf = prepareStringBuilder(strBuilder); - appendPriority(buf, event.getLevel()); - appendTimestamp(buf, event.getTimeMillis()); - appendSpace(buf); - appendHostName(buf); - appendSpace(buf); - appendAppName(buf); - appendSpace(buf); - appendProcessId(buf); - appendSpace(buf); - appendMessageId(buf, event.getMessage()); - appendSpace(buf); - appendStructuredElements(buf, event); - appendMessage(buf, event); - if (useTlsMessageFormat) { - return new TlsSyslogFrame(buf.toString()).toString(); - } - return buf.toString(); + final StringBuilder buf = pool.borrowObject(); + try { + appendPriority(buf, event.getLevel()); + appendTimestamp(buf, event.getTimeMillis()); + appendSpace(buf); + appendHostName(buf); + appendSpace(buf); + appendAppName(buf); + appendSpace(buf); + appendProcessId(buf); + appendSpace(buf); + appendMessageId(buf, event.getMessage()); + appendSpace(buf); + appendStructuredElements(buf, event); + appendMessage(buf, event); + if (useTlsMessageFormat) { + return new TlsSyslogFrame(buf.toString()).toString(); + } + return buf.toString(); + } finally { + pool.returnObject(buf); + } } private void appendPriority(final StringBuilder buffer, final Level logLevel) { diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java index 350e217..96592ad 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java @@ -45,8 +45,6 @@ public final class SyslogLayout extends AbstractStringLayout { private static final long serialVersionUID = 1L; - private static ThreadLocal strBuilder = newStringBuilderThreadLocal(); - /** * Match newlines in a platform-independent manner. */ @@ -80,26 +78,30 @@ public final class SyslogLayout extends AbstractStringLayout { */ @Override public String toSerializable(final LogEvent event) { - final StringBuilder buf = prepareStringBuilder(strBuilder); - - buf.append('<'); - buf.append(Priority.getPriority(facility, event.getLevel())); - buf.append('>'); - addDate(event.getTimeMillis(), buf); - buf.append(Chars.SPACE); - buf.append(localHostname); - buf.append(Chars.SPACE); - - String message = event.getMessage().getFormattedMessage(); - if (null != escapeNewLine) { - message = NEWLINE_PATTERN.matcher(message).replaceAll(escapeNewLine); - } - buf.append(message); - - if (includeNewLine) { - buf.append('\n'); + final StringBuilder buf = pool.borrowObject(); + try { + + buf.append('<'); + buf.append(Priority.getPriority(facility, event.getLevel())); + buf.append('>'); + addDate(event.getTimeMillis(), buf); + buf.append(Chars.SPACE); + buf.append(localHostname); + buf.append(Chars.SPACE); + + String message = event.getMessage().getFormattedMessage(); + if (null != escapeNewLine) { + message = NEWLINE_PATTERN.matcher(message).replaceAll(escapeNewLine); + } + buf.append(message); + + if (includeNewLine) { + buf.append('\n'); + } + return buf.toString(); + } finally { + pool.returnObject(buf); } - return buf.toString(); } private synchronized void addDate(final long timestamp, final StringBuilder buf) { diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ObjectPool.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ObjectPool.java index 84934fb..d8cab06 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ObjectPool.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/ObjectPool.java @@ -1,7 +1,39 @@ +/* + * 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.core.util; +import java.util.Deque; +import java.util.concurrent.ConcurrentLinkedDeque; + /** - * Created by rgoers on 9/30/15. + * */ -public class ObjectPool { +public abstract class ObjectPool { + + private final Deque pool = new ConcurrentLinkedDeque<>(); + + public T borrowObject() { + T object = pool.poll(); + return object == null ? createObject() : object; + } + + public void returnObject(T object) { + pool.add(object); + } + + protected abstract T createObject(); } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/StringBuilderPool.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/StringBuilderPool.java index 9da840f..0d21a98 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/StringBuilderPool.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/StringBuilderPool.java @@ -1,7 +1,39 @@ +/* + * 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.core.util; /** - * Created by rgoers on 9/30/15. + * */ -public class StringBuilderPool { +public class StringBuilderPool extends ObjectPool { + + private final int initialSize; + + public StringBuilderPool(int stringBuilderSize) { + this.initialSize = stringBuilderSize; + } + + @Override + public void returnObject(StringBuilder stringBuilder) { + stringBuilder.setLength(0); + super.returnObject(stringBuilder); + } + + protected StringBuilder createObject() { + return new StringBuilder(initialSize); + } }