Detecting File Changes in Java and Bypassing the JDK‑8177809 Bug

This article walks through a simple Java file‑change watcher, reveals a JDK 8/9 bug where lastModified returns seconds instead of milliseconds, demonstrates the issue with test code, and presents a version‑file workaround to reliably detect updates.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Detecting File Changes in Java and Bypassing the JDK‑8177809 Bug

Background

In some scenarios a program must detect when a file is modified and reload its content. A simple approach is to poll the file’s last‑modified timestamp and compare it with the previous value.

Initial implementation

The basic idea is to run a thread that periodically calls File.lastModified() (which returns a millisecond value) and reloads the file when the timestamp changes.

public class FileWatchDemo {
    /** last update time */
    public static long LAST_TIME = 0L;

    public static void main(String[] args) throws IOException {
        String fileName = "/Users/zzs/temp/1.txt";
        createFile(fileName);
        // demo: two checks
        for (int i = 0; i < 2; i++) {
            long timestamp = readLastModified(fileName);
            if (timestamp != LAST_TIME) {
                System.out.println("文件已被更新:" + timestamp);
                LAST_TIME = timestamp;
                // reload file content here
            } else {
                System.out.println("文件未更新");
            }
        }
    }

    public static void createFile(String fileName) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            boolean result = file.createNewFile();
            System.out.println("创建文件:" + result);
        }
    }

    public static long readLastModified(String fileName) {
        File file = new File(fileName);
        return file.lastModified();
    }
}

Running the demo prints a message when the file is first created and a second message when no change is detected. The approach has two drawbacks:

Polling introduces latency; changes are not detected in real time.

If two modifications occur within the same millisecond, the second change may be missed because the timestamp granularity is only milliseconds.

JDK bug

On certain builds of Java 8 and Java 9 the method File.lastModified() incorrectly returns seconds instead of milliseconds, leaving the last three digits always zero. This is tracked as Bug ID JDK‑8177809 (URL: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8177809).

Verification code:

public class FileReadDemo {
    public static void main(String[] args) throws IOException, InterruptedException {
        String fileName = "/Users/zzs/temp/1.txt";
        createFile(fileName);
        for (int i = 0; i < 10; i++) {
            writeToFile(fileName);
            long timestamp = readLastModified(fileName);
            System.out.println("文件修改时间:" + timestamp);
            Thread.sleep(100);
        }
    }
    // createFile, writeToFile, readLastModified omitted for brevity
}

On a buggy JDK the output shows identical timestamps for several iterations, e.g.:

文件修改时间:1653558619000
文件修改时间:1653558619000
文件修改时间:1653558619000
文件修改时间:1653558619000
文件修改时间:1653558619000
文件修改时间:1653558619000
文件修改时间:1653558620000
文件修改时间:1653558620000
文件修改时间:1653558620000
文件修改时间:1653558620000

Only two of the ten modifications are detected, magnifying the second drawback of the polling approach.

Updated solution

Because many projects still run on Java 8, replacing the JDK is not practical. A reliable alternative is to maintain a separate version indicator—either a monotonically increasing number or an MD5 hash of the file content. The indicator is written whenever the target file is updated; the watcher reads the indicator and reloads the file only when the version differs.

Demo using a version file (incremental integer):

public class FileReadVersionDemo {
    public static int version = 0;

    public static void main(String[] args) throws IOException, InterruptedException {
        String fileName = "/Users/zzs/temp/1.txt";
        String versionName = "/Users/zzs/temp/version.txt";
        createFile(fileName);
        createFile(versionName);
        for (int i = 1; i < 10; i++) {
            writeToFile(fileName);
            writeToFile(versionName, i);
            int fileVersion = Integer.parseInt(readOneLineFromFile(versionName));
            if (version == fileVersion) {
                System.out.println("版本未变更");
            } else {
                System.out.println("版本已变化,进行业务处理");
                version = fileVersion;
            }
            Thread.sleep(100);
        }
    }

    public static void createFile(String fileName) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            boolean result = file.createNewFile();
            System.out.println("创建文件:" + result);
        }
    }

    public static void writeToFile(String fileName) throws IOException {
        writeToFile(fileName, new Random().nextInt());
    }

    public static void writeToFile(String fileName, int value) throws IOException {
        FileWriter fw = new FileWriter(fileName);
        fw.write(String.valueOf(value));
        fw.close();
    }

    public static String readOneLineFromFile(String fileName) {
        File file = new File(fileName);
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            return br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Running this program prints “版本已变化,进行业务处理” on every iteration, confirming that each modification is detected.

Conclusion

The article shows how a naïve polling implementation for file change detection can fail on certain JDK versions due to a bug that reduces timestamp precision to seconds. Replacing the timestamp check with an explicit version indicator (numeric counter or hash) provides reliable detection without depending on the JDK’s lastModified behavior.

JDK bug illustration
JDK bug illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavafile I/OFile MonitoringJDK bug
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.