当前位置: 首页 > 面试题库 >

Java 8中的java.util.logging.FileHandler是否损坏?

鄂琛
2023-03-14
问题内容

首先,一个简单的测试代码:

package javaapplication23;

import java.io.IOException;
import java.util.logging.FileHandler;

public class JavaApplication23 {
    public static void main(String[] args) throws IOException {
        new FileHandler("./test_%u_%g.log", 10000, 100, true);
    }
}

该测试代码使用Java 7仅创建一个文件“
test_0_0.log”,无论我运行该程序的频率如何。这是预期的行为,因为构造函数中的append参数设置为true。

但是,如果我使用Java
8运行此示例,则每次运行都会创建一个新文件(test_0_0.log,test_0_1.log,test_0_2.log等)。我认为这是一个错误。

恕我直言,Java的相关变化是:

@@ -413,18 +428,18 @@
                     // object.  Try again.
                     continue;
                 }
-                FileChannel fc;
+
                 try {
-                    lockStream = new FileOutputStream(lockFileName);
-                    fc = lockStream.getChannel();
-                } catch (IOException ix) {
-                    // We got an IOException while trying to open the file.
-                    // Try the next file.
+                    lockFileChannel = FileChannel.open(Paths.get(lockFileName),
+                            CREATE_NEW, WRITE);
+                } catch (FileAlreadyExistsException ix) {
+                    // try the next lock file name in the sequence
                     continue;
                 }
+
                 boolean available;
                 try {
-                    available = fc.tryLock() != null;
+                    available = lockFileChannel.tryLock() != null;
                     // We got the lock OK.
                 } catch (IOException ix) {
                     // We got an IOException while trying to get the lock.
@@ -440,7 +455,7 @@
                 }

                 // We failed to get the lock.  Try next file.
-                fc.close();
+                lockFileChannel.close();
             }
         }

(完整:OpenJDK变更集6123:ac22a52a732c)

我知道通常FileHandler被Logmanager关闭,但事实并非如此,如果系统或应用程序崩溃或进程被杀死。这就是为什么我在上面的示例代码中没有“
close”语句的原因。

现在我有两个问题:

1)您对此有何看法?这是一个错误吗?(几乎在以下评论和答案中得到答复)

2)您知道在Java 8中获得旧Java 7行为的解决方法吗?(更重要的问题…)

感谢您的回答。


问题答案:

FileHandler的关闭将删除“
lck”文件。如果锁定文件在低于更新40(java.util.logging)的JDK8版本中根本存在,则FileHandler将旋转。根据OpenJDK的讨论,如果当前进程无法锁定lck文件,则决定始终旋转。给出的原因是,当存在锁定文件时,旋转总是更安全。因此,如果您在混合JDK版本中使用旋转模式,这将变得非常讨厌,因为JDK7版本将重用锁,而JDK8版本将保留并旋转。您正在使用测试用例做什么。

如果我从工作目录中 清除所有日志和lck文件 ,然后使用JDK8 运行:

public static void main(String[] args) throws IOException {
    System.out.println(System.getProperty("java.runtime.version"));
    new FileHandler("./test_%u.log", 10000, 100, true).close();
}

我总是看到一个名为“ test_0.log.0”的文件。使用JDK7我得到相同的结果。

最重要的是,您必须确保关闭FileHandlers。如果从未对其进行过垃圾收集或从记录器树中删除,则LogManager将关闭您的FileHandler。否则,您必须关闭它。解决此问题之后,请清除所有锁定文件,然后再运行新的修补代码。然后请注意,如果JVM进程崩溃或被杀死,锁定文件将不会被删除。如果关闭时遇到I
/ O错误,则不会删除锁定文件。当下一个进程开始时,FileHandler将旋转。

如您所指出的,如果上述情况超过100次运行,就有可能用完JDK8上的所有锁定文件。一个简单的测试是两次运行以下代码,而不删除log和lck文件:

public static void main(String[] args) throws Exception {
    System.out.println(System.getProperty("java.runtime.version"));
    ReferenceQueue<FileHandler> q = new ReferenceQueue<>();
    for (int i=0; i<100; i++) {
        WeakReference<FileHandler> h = new WeakReference<>(
                new FileHandler("./test_%u.log", 10000, 2, true), q);
        while (q.poll() != h) {
            System.runFinalization();
            System.gc();
            System.runFinalization();
            Thread.yield();
        }
    }
}

但是,如果正确修复了JDK-6774110,则上述测试用例将无法正常工作。可以在OpenJDK站点上的RFR下追踪此问题:8048020-java.util.logging.FileHandler和FileHandler webrev
上的回归。



 类似资料:
  • 问题内容: 有些人认为这样做存在一些缺陷,即使正确使用也无法保护您的查询。 带一些化石的物品作为证明。 因此,问题是:mysql [i] _real escape_string()完全不可接受吗? 还是仍然可以使用此功能来创建自己的预备语句? 请提供校对码。 问题答案: 从MySQL的C API函数描述 : 如果需要更改连接的字符集,则应使用函数而不是执行(或)语句。的工作方式类似,但也会影响所使

  • 问题内容: 据我所知,使用旧的JMM来实现懒惰单调的DCL(双重检查锁定)技巧被打破了,但是我坚信它已被新的JMM和volatile字段所修复… 但是,在这篇不错的文章中,这显然已经足够新,足以引用DCL中的新旧JMM和volatile字段,表明它仍然坏了… 我在这里到那里读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了? 我的理解是,通过波动性地在关系发生之前保证发生的先兆并有效

  • 问题内容: 我正在尝试做一个简单的例子… 在IE10中 窗口/标签页之间(相对于iframe) 跨起源 删除这些条件中的任何一个,一切正常:-) 但是据我所知,只有两个窗口共享一个原点时,窗口间才在IE10中起作用。(事实上​​,而且很奇怪,这种行为比这更宽松:共享 宿主的 两个不同来源似乎也起作用)。 (注意:此问题涉及问题,但答案是关于IE8和IE9的,而不是10) 更多详情+示例… 启动器页

  • 问题内容: 从目前的情况来看,这个问题不适合我们的问答形式。我们希望答案能得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 7年前关闭。 人们经常说在Python 2中应该避免使用它。我在Python 2中的使用中发现,除非我提供所有示例这样的参数,否则它永远不会达到我期望的方式: 在我看来,

  • 就像Java 8中的(在某种程度上)与Scala的类型等价一样,是否存在与Scala的等价的类型?

  • 问题内容: 我正在使用Java 7,下面有下面的类。我实现和正确的,但问题是,收益的主要方法,下面又返回两个对象相同的散列码。我可以让更多的眼睛看着这个班级,看看我在这里做错了什么吗? 更新: 我更换了我称之为行方法用我自己的哈希函数:。它返回一个不同的哈希码,这是当两个对象不同时应该执行的操作。是方法打破? 对你的帮助表示感谢! 问题答案: 实际上,您碰巧触发了纯粹的巧合。:) 碰巧是通过相继添