垃圾回收器日志 (loggc) 文件轮换与 logrotate 无法正常工作

2022-09-04 21:29:18

在将JVM垃圾回收日志选项与Linux logrotate命令一起使用时,我遇到了一个奇怪的问题。当执行旋转时,它填充作为 JVM 参数的文件的第一行的 NUL ( ^@ ) 值。

假设这是java调用(Test.class位于/home/test/中):

java -Xloggc:/home/test/test.log -cp /home/test/ Test

此文件的 logrotate 配置如下:

/home/test/test.log {
   rotate 56
   missingok
   notifempty
   copytruncate
   nocreate
   nomail
}

我还有一个 crontab 条目记录每分钟用于测试目的:

*/1 * * * * /usr/sbin/logrotate -f /etc/logrotate.d/gcLog

我得出的结论是,JVM在追加模式下写入,并保留某种用于写入相关文件中下一行的偏移量,即使该文件被logrotate截断(我可能是错的)。


我的下一个想法是尝试将标准输出重定向到测试.log文件。我使用了这个java调用,并为logrotate和cron保持相同的配置:

java -verbose:gc -cp /home/test/ test > /home/test/test.log

同样,当 test.log 被 logrotate 截断时,新创建的文件将在第一行填充 NUL (^@) 值。


不用说,我没有发现任何有用的东西使用谷歌。我发现另一个关于stackoverflow的问题有点相关,但我无法设法设置Java脚本包装器,所以这不起作用。

有没有人遇到过这个问题?任何想法为什么会发生这种情况?更好的是,任何解决方法或解决方案?我需要尝试将对应用程序的调用通过管道传输到一些读取输出的脚本,也许可以查看Tomcat在catalina.out中记录和旋转stdout的方式(在这里,一些帮助也将不胜感激)


答案 1

我们在运行Jboss7和Java6的地方遇到了同样的问题,我们在GC文件中获得了NUL,它们只是不断增长。

解决方案是将 GC 记录到 stdout,然后将 stdout 附加到文件中:

简单示例:

java -verbose:gc >> console.log

显然,使用追加(>>)可以摆脱Java“指针”到文件中的某个位置。额外的好处是每次服务器重新启动时都没有重置GC日志,因此我们可以随着时间的推移获得一些统计信息。

至少 IBM PMAT 工具使用 GC 输出解析系统没有问题。

最简单的解决方案有时是最好的:)

虽然我希望Java能够支持GC日志的轮换,但正如我之前看到有人一直在讨论的那样:http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-April/002061.html


答案 2

为了解释 null,Java 维护了一个内部引用,用于计算缩进的位置,当您将文件移开时,它会导致 null 字符写入日志。

我见过篡改GC日志文件导致系统崩溃,在写入日志文件时导致的中止被忽略(请参阅此处的代码 http://pastebin.com/HWkNv3PM),导致JVM继续忽略错误。

当文件重新打开时,我相信仓位计数器不会被重置。

至于如何滚动日志文件的其他想法 - 另请参阅:在java中滚动垃圾回收器日志