log4j2 大日志导致占用内存过多问题

代码里有频繁的日志打印,并且会打印大对象,单条日志较大,导致jvm被大量日志对象占用。

LOG4J2-1858

log4j22.9.0版本代码

org.apache.logging.log4j.message.ParameterizedMessage

@Override
public String getFormattedMessage() {
    if (formattedMessage == null) {
        final StringBuilder buffer = getThreadLocalStringBuilder();
        formatTo(buffer);
        formattedMessage = buffer.toString();
        StringBuilders.trimToMaxSize(buffer, Constants.MAX_REUSABLE_MESSAGE_SIZE);
    }
    return formattedMessage;
}

private static StringBuilder getThreadLocalStringBuilder() {
    StringBuilder buffer = threadLocalStringBuilder.get();
    if (buffer == null) {
        buffer = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
        threadLocalStringBuilder.set(buffer);
    }
    buffer.setLength(0);
    return buffer;
}

org.apache.logging.log4j.util.StringBuilders

public static void trimToMaxSize(final StringBuilder stringBuilder, final int maxSize) {
    if (stringBuilder != null && stringBuilder.capacity() > maxSize) {
        stringBuilder.setLength(maxSize);
        stringBuilder.trimToSize();
    }
}

2.9.0以下版本

@Override
@Override
public String getFormattedMessage() {
    if (formattedMessage == null) {
        final StringBuilder buffer = getThreadLocalStringBuilder();
        formatTo(buffer);
        formattedMessage = buffer.toString();
    }
    return formattedMessage;
}

private static StringBuilder getThreadLocalStringBuilder() {
    StringBuilder buffer = threadLocalStringBuilder.get();
    if (buffer == null) {
        buffer = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
        threadLocalStringBuilder.set(buffer);
    }
    buffer.setLength(0);
    return buffer;
}

在使用 log.info("test ->, {}", body)代码时,log4j2会走到getFormattedMessage方法,由于低于2.9.0版本的只会将length设置为0,对于stringbuilder只是字符个数变为了0,实际上其持有的字符还是在内存中,具体可以参考它的capacity方法,stringbuilder容量并没有改变。

2.9.0版本修复了此问题,stringbuilder会被裁剪容量,最大容量被设置为(128 * 2 + 2) * 2 + 2,通过裁剪避免日志占用大量内存导致oom的问题。

2.9.0之后可以通过设置log4j.maxReusableMsgSize调整最大容量。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值