Java Logger默认只输出INFO及以上级别,FINE及更低级别需同时设置Logger和Handler(如ConsoleHandler)的level为ALL才能输出;SEVERE到FINEST共7级,按严重性降序排列,OFF关闭日志、ALL启用全部。

Java 中 Logger 的基础配置和级别对应关系
Java 自带的 java.util.logging.Logger 默认只输出 INFO 及以上级别(WARNING、SEVERE),FINE、FINER、FINEST 默认被过滤掉——这不是 bug,是默认 Level 配置限制。要记录调试级日志,必须显式设置 Handler 的级别,同时确保 Logger 本身也允许该级别。
常见误区是只调用 logger.setLevel(Level.FINE) 却没改 ConsoleHandler 的级别,结果日志依然不输出。
-
SEVERE:严重错误,应用可能已不可用(如空指针导致核心流程中断) -
WARNING:潜在问题,但未中断执行(如配置项缺失,使用默认值) -
INFO:关键业务节点(如“订单创建成功”,“缓存刷新完成”) -
FINE:常规调试信息(如方法入参、SQL 执行前拼接结果) -
FINER:更细粒度追踪(如循环内每次迭代的中间状态) -
FINEST:高频/低价值细节(如网络请求每个 header 的收发)
如何让 FINE 级日志真正打印到控制台
必须同时设置 Logger 实例和它的 Handler(比如 ConsoleHandler)的级别,否则 Handler 会拦截掉低级别日志。
Logger logger = Logger.getLogger("MyApp");
logger.setLevel(Level.ALL); // 允许所有级别通过 Logger
ConsoleHandler handler = new ConsoleHandler();
handler.setLevel(Level.ALL); // 关键:Handler 也要放开
handler.setFormatter(new SimpleFormatter()); // 可选,避免 XML 格式干扰阅读
logger.addHandler(handler);
如果使用 IDE 运行,注意部分环境(如 IntelliJ 的 JUnit 模式)会重定向 System.out,导致 ConsoleHandler 不可见——此时建议改用 FileHandler 或切换为 SLF4J + Logback。
log.info() 和 log.log(Level.INFO, ...) 的区别
表面上等价,但参数处理逻辑不同:log.info(String) 是快捷方法,而 log.log(Level.INFO, String, Object) 支持延迟求值和异常堆栈自动附加。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 用
log.info("User {0} logged in", userId)时,若日志被禁用,userId.toString()不会执行 —— 这是性能优势 - 用
log.log(Level.WARNING, "DB timeout", ex)会自动把ex的 stack trace 输出在日志末尾;而log.warning("DB timeout: " + ex)只打印toString(),丢失堆栈 - 不要混用占位符风格和字符串拼接:
log.info("id=" + id + ", name=" + name)总是触发对象转换,无条件消耗 CPU
生产环境为什么不该直接用 JUL(java.util.logging)
JUL 的 Handler 是全局共享的,默认 ConsoleHandler 和 FileHandler 都是单例,多个 Logger.addHander() 会导致日志重复输出;且配置只能通过 logging.properties 文件或硬编码,无法按包动态调权。
真实项目中,几乎都用桥接方案:
- 引入
slf4j-jdk14把 SLF4J 日志转给 JUL(兼容遗留系统) - 更常见的是用
slf4j-api+logback-classic,通过logback.xml精确控制每个包的日志级别、输出格式、滚动策略 - Spring Boot 默认集成 Logback,
application.properties中写logging.level.com.example.service=DEBUG就生效,比 JUL 的 properties 文件直观得多
如果你正在维护一个老系统且不能引入新依赖,那 JUL 能用,但得小心 Handler 复用和级别穿透问题——这点最容易在多模块共用同一个 Logger 名称时暴露出来。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










