java.util.logging实现多类日志时生成多份日志文件及lck锁文件问题
问题根源分析
FileHandler的初始化逻辑写在了info()方法中,每次调用info方法都会新建一个FileHandler实例- FileHandler默认会检测目标文件是否被占用,若被占用就自动生成
MyLogFile.log.1、MyLogFile.log.2这类带序号的增量文件 - 旧的FileHandler没有主动关闭,会残留
.lck后缀的锁文件
- FileHandler默认会检测目标文件是否被占用,若被占用就自动生成
- Logger本身是全局单例的,重复添加处理器会导致同一条日志被多次输出到不同文件
修复方案
把Logger和FileHandler的初始化逻辑移到MyLog单例的私有构造方法中,整个程序生命周期仅初始化一次,同时注册JVM关闭钩子主动释放资源,避免锁文件残留。
修改后的MyLog代码
import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; public class MyLog { private static final MyLog instance = new MyLog(); private final Logger logger = Logger.getLogger("MyLog"); private FileHandler fh; // 初始化逻辑放在私有构造里,全局仅执行一次 private MyLog() { try { // 第二个参数true表示开启文件追加,不会每次启动覆盖旧日志 fh = new FileHandler("f://MyLogFile.log", true); SimpleFormatter formatter = new SimpleFormatter(); fh.setFormatter(formatter); logger.addHandler(fh); // 不需要日志同时输出到控制台可以保留下面这行,不需要就删除 logger.setUseParentHandlers(false); } catch (SecurityException | IOException e) { e.printStackTrace(); } // 注册JVM关闭钩子,程序退出时自动关闭FileHandler,清理锁文件 Runtime.getRuntime().addShutdownHook(new Thread(() -> { if (fh != null) { fh.close(); } })); } public static MyLog getInstance() { return instance; } public void info(String msg) { logger.info(msg); } // 可按需扩展其他日志级别方法 public void error(String msg, Throwable e) { logger.log(java.util.logging.Level.SEVERE, msg, e); } }
额外优化建议
- 如果需要按不同业务类区分日志,可以给日志方法增加Class入参,调用
Logger.getLogger(clazz.getName())生成类粒度的日志实例 - 日志路径不要写死绝对路径,可以改成项目相对路径,或者读取配置文件动态配置
内容的提问来源于stack exchange,提问作者Karthikeyan
相关产品推荐
相关产品推荐

