在jdk7的watch service API中,什么时候会抛出OVERFLOW事件?

7
溢出的文档说明如下:

溢出 - 表示事件可能已经丢失或丢弃。

它并没有说在什么情况下我应该期望事件会丢失或被丢弃?起初我认为这可能是因为将大量文件非常快地写入文件夹的结果。我创建了几千个大小为零的文件,并将它们移动到一个监视目录中,但没有发生溢出。
我错过了什么?

文件系统可能会比检索或处理事件更快地报告事件,并且实现可能对其可以累积的事件数量施加未指定的限制。如果实现知道丢弃事件,则它会安排键的pollEvents方法返回一个具有事件类型为OVERFLOW的元素。此事件可由使用者用作重新检查对象状态的触发器。也许您没有施加足够的负载以创建溢出。 - Fildor
@Fildor,谢谢。我忘记阅读这个JavaDoc了。请发布为答案,这样我就可以接受它了。 - Vitaliy
4个回答

7

生成溢出的最小示例

只需要在watcherService.registerwatcherService.take之间创建文件即可。

使用以下命令调用:

java Overflow 256

控制事件数量。

Java 7和Ubuntu 14.04的最大事件数为512个。

每次发生溢出时,pollEvents()仅返回一个事件,但这在Javadoc上并没有明确说明。

我认为这个限制太小了,考虑到以下事实:

代码:

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchService;
import java.util.List;

public class Overflow {

    @SuppressWarnings("unchecked")
    static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>)event;
    }

    public static void main(final String[] args) throws InterruptedException, IOException {
        int nfiles;
        if (args.length > 0)
            nfiles = Integer.parseInt(args[0]);
        else
            nfiles = 10_000;
        Path directory = Files.createTempDirectory("watch-service-overflow");
        final WatchService watchService = FileSystems.getDefault().newWatchService();
        directory.register(
                watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE);
        final Path p = directory.resolve(Paths.get("Hello World!"));
        for (int i = 0; i < nfiles; i++) {
            Files.createFile(p);
            Files.delete(p);
        }
        List<WatchEvent<?>> events = watchService.take().pollEvents();
        for (final WatchEvent<?> event : events) {
            if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
                System.out.println("Overflow.");
                System.out.println("Number of events: " + events.size());
                return;
            }
        }
        System.out.println("No overflow.");
        Files.delete(directory);
    }
}

6
“文件系统可能比它们能够被检索或处理的速度更快地报告事件,并且实现可能对其可以累积的事件数量施加未指定的限制。如果实现明知道丢弃事件,则它会安排键的pollEvents方法返回一个具有溢出事件类型的元素。此事件可由消费者用作重新检查对象状态的触发器。”
来自JavaDoc
另请参见Steven C的答案。我认为他关于未消耗事件的观点是不同的。

6

我创建了几千个大小为零的文件,并将它们移动到监视的目录中。没有溢出。

假设你正在并行消费这些事件。如果想触发一个溢出,可以尝试暂停事件的消费,生成大量事件(如上所述),然后恢复消费。操作系统可以缓冲未消费事件的数量肯定有限制。


-1

来自OpenJDK中的源代码JDK17

abstract class AbstractWatchKey implements WatchKey {

    /**
     * Maximum size of event list (in the future this may be tunable)
     */
    static final int MAX_EVENT_LIST_SIZE    = 512;

自2011年以来应该是“可调的”......

因此,您可以在Linux中修改inotify.max_user_watches,因为您希望它没有影响......

我们现在是2022年7月......自11年以来什么也没做。这个错误自2013年以来就已经被报告了:

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8034864

不要浪费时间在Java、Oracle或OpenJDK上...它们只是不关心。

试试使用Python的watchdog 2.1.9 API,处理成千上万个文件,只需一试,就能像魅力一样运行...无论事件数量如何。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接