这是一个专门为 `com.axis.innovators.box.Log4j2OutputStream` 类编写的技术介绍文档。 --- # Log4j2OutputStream 类技术文档 **包路径:** `com.axis.innovators.box.Log4j2OutputStream` **主要功能:** 标准输出重定向与日志集成 **作者:** tzdwindows 7 ## 1. 概述 `Log4j2OutputStream` 是一个高度定制化的 `OutputStream` 实现,旨在解决 Java 应用程序中标准输出 (`System.out`) 和标准错误 (`System.err`) 与日志框架(Log4j2)集成时的冲突问题。 传统的日志重定向往往会“吞掉”控制台输出,导致开发者在调试时无法实时看到控制台信息。该类通过**多路输出机制**,实现了在保持控制台原始输出的同时,将内容自动同步到 Log4j2 日志记录器中,并保留一份副本在内存中用于崩溃诊断。 ## 2. 核心特性 * **三路并行输出 (Triple-Way Output):** 任何写入此流的数据会同时流向: 1. **原始控制台流:** 保证开发环境下的实时可见性。 2. **Log4j2 Logger:** 将普通的 `print` 语句转换为结构化的日志条目。 3. **内存缓冲区:** 静态存储在 `systemOutContent` 和 `systemErrContent` 中,供系统在发生崩溃时提取诊断数据。 * **智能行缓冲 (Line-Buffered Logging):** 为了避免日志碎片化,该流会累积字符直到遇到换行符 (`\n`) 或手动触发 `flush()` 时,才会将其作为一条完整的日志记录(INFO 或 ERROR 级别)发送给 Log4j2。 * **字符编码安全:** 全程采用 `StandardCharsets.UTF_8` 处理,有效防止中文字符在重定向过程中出现乱码。 * **无缝集成:** 提供静态方法一键重定向整个系统的标准流。 ## 3. 工作原理 ### 3.1 数据流向图 ```text System.out.println("Hello") │ ▼ Log4j2OutputStream.write() │ ├───> 原始 PrintStream (控制台显示) ├───> 内存 ByteArrayOutputStream (诊断快照) └───> 内部 Buffer ───(遇到 \n)───> LogManager.getLogger().info() ``` ### 3.2 级别映射 * `System.out` 映射为 Log4j2 的 **INFO** 级别。 * `System.err` 映射为 Log4j2 的 **ERROR** 级别。 ## 4. API 说明 ### 4.1 核心静态方法 | 方法 | 描述 | | :--- | :--- | | `static void redirectSystemStreams()` | **最常用的方法**。调用后会立即劫持全局 `System.out` 和 `System.err`,并将其替换为封装后的 `Log4j2OutputStream`。 | | `static String getSystemOutContent()` | 获取自程序启动(或上次清空)以来标准输出的所有文本内容。 | | `static String getSystemErrContent()` | 获取自程序启动以来标准错误的所有文本内容。 | | `static void clearBuffers()` | 重置内存中的静态缓冲区,释放内存。 | ### 4.2 构造函数 ```java public Log4j2OutputStream(boolean isErrorStream, PrintStream originalStream) ``` * `isErrorStream`: 指定该流是否作为错误流处理(影响日志级别)。 * `originalStream`: 传入系统原始的打印流(如 `System.out` 在重定向前的副本),确保数据能回流到控制台。 ## 5. 使用场景:崩溃诊断报告 该类与 `AxisInnovatorsBox` 的崩溃报告系统紧密配合。当程序发生未捕获异常时,`AxisInnovatorsBox` 会调用: ```java String systemOut = Log4j2OutputStream.systemOutContent.toString(); String systemErr = Log4j2OutputStream.systemErrContent.toString(); // ... 组合成完整的诊断报告 ``` 这确保了即使用户没有查看日志文件的习惯,程序也能在崩溃瞬间抓取到最后时刻的控制台输出,极大地方便了远程排查。 ## 6. 使用示例 在程序启动的最早期(通常在 `main` 方法或初始化块中)调用: ```java public static void main(String[] args) { // 初始化并启动重定向 Log4j2OutputStream.redirectSystemStreams(); // 现在的 println 既会出现在控制台,也会进入 log4j2 配置文件定义的 Appender 中 System.out.println("This is a test message."); System.err.println("This error will be logged as ERROR level."); } ``` ## 7. 注意事项 1. **资源开销:** 由于内存中保留了输出副本,如果程序产生极大量的控制台输出(如数 GB 的日志),应定期调用 `clearBuffers()` 以防止内存溢出。 2. **线程安全:** 该类依赖 `ByteArrayOutputStream` 的同步机制和 Log4j2 的线程安全保证。 --- *文档生成时间: 2026-01-02*