Log4j2 内置 Garbage-free(无垃圾)模式,可重用对象和缓冲区,减少日志记录时产生的垃圾对象,避免 JVM 进行 GC 回收,进而提升应用程序的性能与响应速度。以下以 Log4j2 的 2.24.3 版本为基础,客观、真实、全面地介绍 Garbage-free 无垃圾回收模式,并总结其特性和应用场景。

先说结论: Log4j2 的 Garbage-free 无垃圾回收模式在实际使用中支持和适用场景极为有限,意义不大,不建议开启。

一、如何启用

默认情况下,Log4j2 根据应用是否为 Web 类型(通过判断 classpath 中是否包含 Servlet 类)来决定是否启用 Garbage-free 运行模式。若是 Web 应用,不开启,此时 log4j2.isWebapp 和 log4j2.enableThreadlocals 属性值分别为 true 和 false;反之,可将两属性值设置为 false 和 true,则强制开启 Garbage-free 模式。

在 Web 应用中,若 ThreadLocal 变量持有非 JDK 类,且 Web 应用程序卸载后,应用服务器的线程池仍继续引用这些变量,可能导致应用内存泄漏。因此,为避免内存泄漏,Web 应用默认不开启 Garbage-free 模式。Web 应用可通过强制指定 log4j2.enableThreadlocals=true 来开启该模式。此外,若使用线程上下文字段(如 MDC),还需将 log4j2.garbagefreeThreadContextMap 属性设为 true。

建议将上述配置属性统一放在类路径(通常是 src/main/resources/)下的 log4j2.component.properties 文件中。这种配置方式可被 JVM 变量、系统环境变量和编码覆盖。

二、配套要求

启用 Garbage-free 模式(log4j2.enableThreadlocals 属性值设置为 true)后,需配套使用支持 Garbage-free 的 Layouts、Appenders 和 Filters,并合理使用 API,才能确保该模式真正生效。

1. 支持的 Layout

(1)有条件支持 GelfLayout、JsonTemplateLayout 和 PatternLayout 这三种 Layout,不支持常用的 CsvLayout。

(2)上述三种 Layout 并非完全支持。如果其中使用了不支持 Garbage-free 的参数、配置或方法,会导致该 Layout 不支持 Garbage-free。例如,在 PatternLayout 中输出 Exception、Method、Line、Location、Class、File 等字段,就会使得该 Layout 不支持 Garbage-free。

2. 支持的 Appender

(1)ConsoleAppender 及文件类 Appender,如 FileAppender、MemoryMappedFileAppender、RandomAccessFileAppender、RollingFileAppender(非轮转期间)、RollingRandomAccessFileAppender(非轮转期间)均支持。

(2)大部分涉及外部 IO(网络、数据库和消息队列等)的 Appender 均不支持,例如 JDBCAppender、KafkaAppender 等。

(3)上述结论仅源于官方文档,未经详细测试。总结 Layout 使用经验,建议仔细参考各 Appender 文档,判断是否存在具体限制。

3. 支持的 Filter

(1)CompositeFilter、DynamicThresholdFilter、LevelRangeFilter、MapFilter、MarkerFilter、StructuredDataFilter、ThreadContextMapFilter、ThresholdFilter 和 TimeFilter 均支持。

(2)上述结论仅源于官方文档,未经详细测试。总结 Layout 使用经验,建议仔细参考各 Appender 文档,判断是否存在具体限制。

4. 其他情况

(1)如果使用了 NDC(Nested Diagnostic Context),则无法支持 Garbage 模式。

(2)异步日志(AsyncLogger)如果使用默认的 timeout 等待策略,则支持 Garbage 模式。

(3)从测试情况来看,即便使用的 Layout、Appender 和 Filter 都支持 Garbage 模式,但如果 logger 输出内容包不支持 Garbage 模式的字段,最终也无法使用 Garbage 模式。

三、强烈建议

在实际项目中,即便应用启用 Garbage 模式,受各种使用限制和配置要求影响,实际也未必真正启用。强烈建议使用 JMH 对相应的日志配置进行压测,并添加“prof gc”参数,以验证 GC 的回收情况,从而判断该日志配置是否真正支持 Garbage 模式。

四、性能对比

以下我们将使用相同的性能测试基准,通过配置参数强制开启或关闭 Garbage 模式,以此判断该模式对性能的帮助。

1. 测试基准

(1)硬件:Windows 笔记本,配置为 I5-1350P CPU、32G DDR5 5200 内存以及三星 MZVL4512HBLU-00BLL 512G SSD(顺序写入速度为 2430MB/s)。

(2)软件:基于 JDK 1.8.171,使用 1.37 版 JMH 和 2.24.3 版 Log4j2。

(3)配置:采用 FileAppender 及其默认配置(append 和 immediateFlush 均为 true),使用同步 Logger 进行压测。

(4)参考日常使用情况,输出长度为 100 个的固定字符串,日志 PatternLayout 布局为:“% d {yyyy-MM-dd HH:mm:ss.SSS} %-5level % pid % t - % msg % n”。

(5)在 classpath 下添加 log4j2.component.properties 配置文件,通过 log4j2.enableThreadlocals 配置项来开启或关闭 Garbage-free 模式。

2. Log4j2 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="log4j2AppenderTest" status="error">
<Properties>
<Property name="log.pattern">
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %pid %t - %msg %n
</Property>
</Properties> <Appenders>
<Console name="Console">
<PatternLayout pattern="${log.pattern}"/>
</Console>
<File name="File"
fileName="log/log4j2-file.log">
<PatternLayout pattern="${log.pattern}"/>
</File>
</Appenders> <Loggers>
<Root level="debug">
<AppenderRef ref="Console" />
</Root>
<Logger name="FileLogger" level="debug" additivity="false">
<AppenderRef ref="File" />
</Logger>
</Configuration>

3. JMH 压测代码

@State(Scope.Benchmark)
public class Log4J2FileAppenderBenchmark { static Logger fileLogger; int delFilesCount = 0; @Setup(Level.Trial)
public void setUp() throws Exception {
System.setProperty("log4j.configurationFile", "log4j2.xml");
fileLogger = LogManager.getLogger("FileLogger");
} @TearDown
public void tearDown() {
System.clearProperty("log4j.configurationFile");
} @BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Benchmark
public void fileLogger() {
fileLogger.debug(Const.MSG_HAVE_100_CHARS);
}
}

4. JMH 参数

JMH 执行的参数为:-jvmArgs "-Xmx512m -Xms512m" -f 2 -t 4 -w 10 -wi 2 -r 30 -i 2 -to 300 -prof gc,即设置 JVM 参数为 -Xmx512m -Xms512m(堆内存最大和最小均为 512MB),使用 2 个 fork(-f 2),每个 fork 使用 4 个线程(-t 4),预热阶段每次运行 10 秒(-w 10),预热迭代 2 次(-wi 2),正式测试每次运行 30 秒(-r 30),正式测试迭代 2 次(-i 2),超时时间为 300 秒(-to 300),并启用 GC 性能分析(-prof gc)。

5. 测试结果

类型 平均吞吐量 内存分配速率(MB/sec) 垃圾回收次数
Garbage-free 模式 137.1 ops/ms 10 MB/sec 0
非 Garbage-free 模式 135.5 ops/ms 18.8 MB/sec 18

6. 测试总结

(1)由于不少 PatternLayout 参数不支持无垃圾回收模式,因此上述 PatternLayout 配置参数略微简单,在相同配置下,启用 Garbage-free 模式后,内存分配量明显下降,且无 GC 回收及耗时,但吞吐量并无明显提高。

(2)此外,经其他测试发现,越不支持无垃圾回收模式的参数,越占内存,如输出日志所在的类、方法、行数及完整异常堆栈信息等。

五、总结

在日常研发中,我们主要将 Log4j2 用于 Web 开发,默认不开启 Garbage-free 模式。若强制启用,一旦使用不当,可能导致内存泄露。即便强制启用,实际使用时,各类日志输出字段需包含产生日志的类、方法、行数及完整异常堆栈等基本字段,而这些字段又不支持 Garbage-free 模式,仍会产生垃圾回收,最终真正启用该模式。所以我认为,Log4j2 的 Garbage-free 无垃圾回收模式在实际使用中支持和适用场景极为有限,意义不大,不建议开启。

六、参考文档

(1)log4j2.x garbagefree

Log4j2 Garbage-free 无垃圾回收模式实践与总结的更多相关文章

  1. 2.5 – Garbage Collection 自动垃圾回收 Stop-the-world vs. incremental vs. concurrent 垃圾回收策略

    2.5 – Garbage Collection  自动垃圾回收 Lua 5.3 Reference Manual http://www.lua.org/manual/5.3/manual.html# ...

  2. GC(Garbage Collection)垃圾回收机制

    1.在垃圾回收器中,程序员没有执行权,只有通知它的权利. 2.程序员可以通过System.gc().通知GC运行,但是Java规范并不能保证立刻运行. 3.finalize()方法,是java提供给程 ...

  3. python 之gc(回收机制)--garbage collection(GC垃圾回收)

    ######################引用计数######################### 引用计数:python 当中一种用来解决垃圾回收的策略之一 char 1个字节(2**8) in ...

  4. [Java] 垃圾回收机制 ( Garbage Collection ) 简介

    自动垃圾回收( Automatic Garbage Collection ) 自动垃圾回收,是指在堆(Heap)内存上分辨哪些对象还在被使用,哪些对象没有被使用,并清除没有被使用的对象.所以,这里的垃 ...

  5. 【python进阶】Garbage collection垃圾回收1

    前言 GC垃圾回收在python中是很重要的一部分,同样我将分两次去讲解Garbage collection垃圾回收,此篇为Garbage collection垃圾回收第一篇,下面开始今天的说明~~~ ...

  6. 【python进阶】Garbage collection垃圾回收2

    前言 在上一篇文章[python进阶]Garbage collection垃圾回收1,我们讲述了Garbage collection(GC垃圾回收),画说Ruby与Python垃圾回收,Python中 ...

  7. Java进阶 JVM 内存与垃圾回收篇(一)

    JVM 1. 引言 1.1 什么是JVM? 定义 Java Vritual Machine - java 程序的运行环境(Java二进制字节码的运行环境) 好处 一次编译 ,到处运行 自动内存管理,垃 ...

  8. Chrome 浏览器垃圾回收机制与内存泄漏分析

    Chorme 浏览器中的垃圾回收和内存泄漏 垃圾回收 通常情况下,垃圾数据回收分为手动回收和自动回收两种策略. 手动回收策略,何时分配内存.何时销毁内存都是由代码控制的. 自动回收策略,产生的垃圾数据 ...

  9. JVM 专题二十一:垃圾回收(五)垃圾回收器 (二)

    3. 回收器 3.1 Serial回收器:串行回收 3.1.1 概述 Serial收集器是最基本.历史最悠久的垃圾收集器了.JDK1.3之前回收新生代唯一的选择. Serial收集器作为Hotspot ...

  10. Java垃圾回收机制详解

    前言 Java 相比 C/C++ 最显著的特点便是引入了自动垃圾回收 (下文统一用 GC 指代自动垃圾回收),它解决了 C/C++ 最令人头疼的内存管理问题,让程序员专注于程序本身,不用关心内存回收这 ...

随机推荐

  1. 浏览器实时查看日志系统-log.io

    log.io 是一个实时日志监控工具,采用 node.js + socket.io 开发,使用浏览器访问,每秒可以处理超过5000条日志变动消息.有一点要指出来的是 log.io 只监视日志变动并不存 ...

  2. IEDA 控制台乱码解决

    1.修改idea 目录下的文件 idea64.exe.vmoptions idea.exe.vmoptions 在这个文件尾部增加 -Dfile.encoding=UTF-8 2.编辑ieda 文件配 ...

  3. 【C++】类的继承的深入探讨

    继承是扩展现有类并为基类提供新功能的一种方式. 本文主要探讨一个问题:子类会包含父类所包含的一切吗? 起初,作者认为这个问题的答案是否定的,因为子类无法访问父类的private成员 但是,运行下述一个 ...

  4. 使用AES加密时,结果不一样

    使用AES加密时,发现得到的结果不一致. python示例 from Crypto.Cipher import AES from Crypto.Util.Padding import pad from ...

  5. bluetooth_stack开源蓝牙协议栈源码分析与漏洞挖掘

    文章首发地址 https://xz.aliyun.com/t/9205 前言 网上闲逛的时候,发现github有个开源的蓝牙协议栈项目 https://github.com/sj15712795029 ...

  6. win10重装如何跳过微软账号直接设置本地帐户

    ​在添加你的帐户界面,选择脱机帐户 第二个页面,选择有限的体验 第三个页面,设置自己本地的用户名 第四个页面,设置自己本地的密码

  7. 一文学会powshell使用及功能

    声明! 原文来自微信公众号泷羽Sec-track 认识powsehll PowerShell(通常称作PowerShell或Windows PowerShell)是由微软开发的一种任务自动化和配置管理 ...

  8. Netty有关

    https://www.baeldung.com/tag/netty/ https://github.com/eugenp/tutorials https://stackoverflow.com/qu ...

  9. Qt/C++音视频开发73-高效滤镜/文字水印/图形水印/图片水印/yolo运算后的结果显示到画面中

    一.前言 视频监控系统发展到今天,越来越智能,比如这些年流行的人脸识别.物体识别.烟感识别等,都是需要拿到图片数据去做运算处理,然后将结果显示到视频画面中,或者还有要求将结果保存到视频录像文件中,以便 ...

  10. 《AutoCAD2020中文版基础教程》和《从零开始—AutoCAD 2020中文版基础教程》配套资源下载

    <AutoCAD2020中文版基础教程>作者:姜春峰//武小紅//魏春雪中国青年出版社配套资源链接:https://pan.baidu.com/s/1kPGNKZEw2kOTGqZyXjp ...