Java日志记录打开";“太多”;日志文件

Java日志记录打开";“太多”;日志文件,java,java.util.logging,Java,Java.util.logging,这有点奇怪,但我对日志包及其属性的使用还不熟悉。通过谷歌搜索,我能找到的所有问题都是“如何让日志打开多个文件?”但我今天的问题是如何让它停止同时执行多个文件。我们走吧 第一件事:此项目仅限于使用java.util.logging,不,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更棒。:-) 因此,当这个小程序启动时,它会运行以下代码: import java.util.logging.Logger; import java.util.logging.LogManager;

这有点奇怪,但我对日志包及其属性的使用还不熟悉。通过谷歌搜索,我能找到的所有问题都是“如何让日志打开多个文件?”但我今天的问题是如何让它停止同时执行多个文件。我们走吧

第一件事:此项目仅限于使用java.util.logging,不,我不能切换到log4j或任何其他第三方软件包,是的,我知道它们应该更棒。:-)

因此,当这个小程序启动时,它会运行以下代码:

import java.util.logging.Logger;
import java.util.logging.LogManager;

// in startup routine:
LogManager.getLogManager().readConfiguration(
  this.getClass().getResourceAsStream("/logging.properties"));
将属性文件从JAR中拉出并应用它们,这很有效。
readConfiguration()
应该从VM启动时重置所有现有设置。项目的其余部分有如下行

private final static Logger LOGGER = Logger.getLogger(NameOfClass.class.getName());
我认为这是相当标准的。我们所有的类都在同一个包中(例如,将其称为project),并且funky日志名称/属性层次结构遵循相同的约定,因为java.util.logging就是这样运行的

logging.properties文件最初是Java 6 SE JRE附带的文件的副本,后来被修改。现在看起来是这样的:

handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler

# Default global logging level. 
.level=INFO

# Loggers 
# ------------------------------------------ 
# Loggers are usually attached to packages. 
# Here, the level for each package is specified. 
# The global level is used by default, so levels 
# specified here simply act as an override. 
java.level = INFO
javax.swing.level = INFO
sun.awt.level = INFO
theproject.level = ALL

# Handlers 
# -----------------------------------------
theproject.handlers=java.util.logging.FileHandler

# Override of global logging level 
java.util.logging.FileHandler.level=ALL

# Naming style for the output file: 
java.util.logging.FileHandler.pattern=/path/to/logfiles/TheProject%u.%g.log
所有这些都“起作用”,因为日志消息显示在Java控制台中,也显示在磁盘文件中。奇怪的是:小程序一运行,就会同时打开两个文件,即project0.0.log和project1.0.log。当日志消息被触发时,它们会同时显示在两个文件中。这两个文件在任何时候都是彼此的精确副本,包括达到最大大小并(都!)旋转时

我检查过,一次只有一个JRE虚拟机在运行

在任何给定的时间,要么两个文件都被打开,要么两个文件都被关闭。这不像是一个比另一个开放的时间更长或更短

如果日志文件已被另一个进程打开,则两个文件名之间不同的%u标记将被记录为“解决冲突的唯一编号”,但我认为这里不是这种情况,因为两个日志都获得相同的数据,没有其他东西打开该文件。(证据:当虚拟机运行时,Windows不允许我删除这两个文件,但一旦虚拟机最终退出,它就会删除。)

我是否在属性文件中做了一些愚蠢的事情,或者误解了如何正确加载属性,或者…?

我认为它的工作方式与您认为的不同。形成JavaDocs:

重新初始化日志记录属性并重新读取日志记录 来自给定流的配置,该流应位于 java.util.Properties格式。PropertyChangeEvent将在 属性被读取

新配置文件中的任何日志级别定义都将被删除 如果目标记录器存在,则使用Logger.setLevel()应用

我不确定这是否真的会重置日志记录配置,或者只是附加/更新当前配置

我想你可能需要在打电话之前先打个电话

重置日志记录配置

对于所有命名记录器,重置操作将删除并关闭所有 处理程序和(根记录器除外)将级别设置为null。这个 根记录器的级别设置为level.INFO

编辑:为了表明属性文件没有问题,您可以在项目
包中创建一个名为test的类,如下所示,然后运行它。只需确保删除现有的日志文件,以便知道在运行时创建了多少日志文件

package theproject;

import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class Test {

    private final static Logger LOGGER = Logger.getLogger(Test.class.getName());

    public static void main(String[] args) throws Exception {
        LogManager.getLogManager().readConfiguration(
                  Test.class.getResourceAsStream("/logging.properties"));
//      The only way I could get it to create two log files was to uncomment the line below that
//      adds another FileHandler to the root logger.
//      LogManager.getLogManager().getLogger("").addHandler(new FileHandler("/path/to/logfiles/TheProject%u.%g.log"));
        Test test = new Test();
    }   

    public Test(){
        LOGGER.log(Level.INFO, "Info");
    }

}
@乔普(在一篇评论中,不能被标记为答案)说得很对。事实证明,设置处理程序是一个添加过程,它不会简单地覆盖以前的设置。这对我来说似乎很不直观,但这是java.util.logging for ya。。。保留所有其他属性,但删除处理程序分配,是一种方法

我还使用了@jschoen建议的reset()调用,因为这似乎是一件明智的事情


非常感谢你们所有人。我不知道如何将这一切标记为“关闭”。。。是时候去摆弄一下网站了。

你有没有试着对项目进行评论。
处理程序=…
?你发布的东西似乎没有问题。您是否可能在java代码的某个地方向记录器添加了第二个
文件处理程序
(例如
LogManager.getLogManager().getLogger(NameOfClass.class.getName()).addHandler(新的文件处理程序(“/path/to/logfiles/TheProject%u.%g.log”);
)。这是我复制它的唯一方法。捕捉得好!我将代码改为
LogManager LM=LogManager.getLogManager();LM.reset();LM.读取配置(…)不幸的是,这根本没有效果。我在重置之前、重置之后和readConfig之后使用LogManager的getLoggerNames添加了一些转储代码,并且所有三个打印输出都是相同的。@TiStrga我不确定
getLoggerNames
是否是您应该查找的,但是每个记录器中都有
getHandlers()
。它们似乎以某种方式连接了两个
FileHandler
s。您是否检查了代码中是否向记录器添加了第二个FileHandler?