JUL默认只输出到控制台,需显式添加FileHandler并确保路径权限、层级继承、Level匹配及Formatter配置正确,否则日志静默丢失。
Logger输出不到文件?默认只打到控制台
Java自带的
(JUL)默认只用
,不写文件——这是最常被忽略的前提。你调了
却找不到日志文件,不是代码写错了,是根本没配Handler。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
必须显式创建
并
到Logger,JUL不会自动帮你做
Logger层级继承:如果给
加了FileHandler,它的子Logger(如
)会自动继承,但根Logger(
)的Handler不影响自定义Logger,除非你调用
注意权限:Windows下路径含中文或空格、Linux下目录无写权限,会导致
,建议先确保
FileHandler构造参数怎么选?路径和模式最关键
构造函数有多个重载,最容易踩坑的是
这个两参数版本——它不支持自动轮转,且
里不能带
或
占位符(那些只在四参数版本生效)。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
要轮转日志(比如每天一个文件),必须用四参数构造:
,其中
是索引,
是最大文件数,
表示追加
路径建议用绝对路径或基于
拼接,避免相对路径在IDE/打包后失效
如果只想要单文件且不轮转,用两参数版即可,但记得手动确保父目录存在,否则抛
日志格式太简陋?Formatter决定内容可读性
JUL默认用
,输出只有时间、级别、类名和消息,没有线程名、方法名、毫秒级时间戳——排查并发问题时基本不够用。
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
换用
可得结构化输出,但人类阅读不友好;更常用的是自定义Formatter,继承
重写
,重点处理
、
等字段
别直接改根Logger的Formatter:
会影响所有未单独设置Formatter的Logger,容易误伤
如果用了Log4j或SLF4J桥接,JUL的Formatter配置可能被覆盖,此时应优先查桥接层配置
为什么设置了FileHandler还是没日志?检查Level和Filter
即使Handler加对了、路径也合法,日志仍可能“消失”——大概率是Logger或Handler自身的
设得太高,或者被
拦截了。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
Logger默认Level是
,Handler默认Level也是
,但如果你调过
,那
消息就进不了Handler,哪怕Handler Level是
Handler的Level独立于Logger:可以设Logger为
,只让某个FileHandler响应
以上,用于分离错误日志
检查是否无意中加了
,尤其是第三方库(如某些监控SDK)可能偷偷注册Filter
真正麻烦的不是写几行配置,而是JUL的层级继承、Level双控、Handler生命周期这些隐式规则——它们不会报错,只会静默丢日志。动手前先用
和
打个断点,比反复猜路径更省时间。
java.util.loggingConsoleHandlerlogger.info()FileHandleraddHandler()Logger.getLogger("com.example")"com.example.service"""setUseParentHandlers(true)java.io.IOException: Permission deniednew File("logs/app.log").getParentFile().mkdirs()FileHandlerFileHandler(String pattern, boolean append)pattern%u%gnew FileHandler("logs/app.%g.log", 1024 * 1024, 5, true)%g5trueSystem.getProperty("user.dir")IOExceptionjava.util.logging.SimpleFormatterjava.util.logging.XMLFormatterFormatterformat()record.getMillis()record.getSourceMethodName()Logger.getLogger("").getHandlers()[0].setFormatter(...)LevelFilterINFOINFOlogger.setLevel(Level.WARNING)INFOALLINFOWARNINGhandler.setFilter(...)logger.getHandlers()logger.getLevel()