App下載

以前偶然發(fā)現(xiàn)的 Java Bug(JDK 9及之前仍未修復(fù))

猿友 2020-09-05 16:59:37 瀏覽數(shù) (2455)
反饋

文章轉(zhuǎn)載自公眾號(hào):叨叨軟件測(cè)試 作者: 蔣李恒

背景

15年在中信銀行做持續(xù)集成時(shí),由于當(dāng)時(shí)的項(xiàng)目是基于三方采購(gòu)的 Java 配置開(kāi)發(fā)平臺(tái)做的,平臺(tái)自己基于 Ant 插件實(shí)現(xiàn)了增量和熱部署。

其中有幾個(gè)項(xiàng)目在持續(xù)集成部署時(shí),經(jīng)常發(fā)現(xiàn) Linux 平臺(tái)部署成功后(Windows 不會(huì)出現(xiàn),Linux 也是偶發(fā)現(xiàn)象),新版本代碼并沒(méi)有生效(反編譯 class)。

起初我是在本地 windows 上跟蹤調(diào)試基于 Ant 插件的代碼,但始終重現(xiàn)不了(最后測(cè)試發(fā)現(xiàn) Windows 無(wú)此 Bug)。

后來(lái),通過(guò)分析代碼邏輯,其中有段邏輯是通過(guò)文件的最后修改時(shí)間(File.lastModified())來(lái)判斷要不要覆蓋部署的,最后通過(guò)單測(cè)發(fā)現(xiàn),是由于 JavaFile.lastModified() 方法在 WindowsLinux/Unix平臺(tái)獲取的精度不一樣導(dǎo)致的,Windows 精度為毫秒,而 Linux/Unix 只能到秒(JDK Bug:JDK-8177809)。

所以也解釋了,為什么是偶發(fā)現(xiàn)象,文件修改時(shí)間如果判斷的兩個(gè)值正好跨秒時(shí),部署就是成功的,否則失敗。

Bug 重現(xiàn)

測(cè)試代碼:FileTest.java

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;


public class FileTest {
    private static final long LM = 1599276952718L;


    public static void main(String[] args) throws IOException {
        // java版本號(hào)
        System.out.println("Java Version:" + System.getProperty("java.version"));


        File f = new File("test.txt");
        f.createNewFile();


        // 設(shè)置最后修改時(shí)間
        f.setLastModified(LM);


        // 獲取修改時(shí)間,存在 bug
        System.out.printf("Test f.lastModified [%s]: %b\n",
f.lastModified(), f.lastModified() == LM);
        // 格式化輸出,正確不存在 bug
        System.out.printf("Test f.lastModified DateFormat [%s]\n",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.sss").format(f.lastModified()));


        // Files.getLastModifiedTime() 獲取修改時(shí)間,同樣存在 bug
        System.out.printf("Test Files.getLastModifiedTime [%s]: %b\n",
Files.getLastModifiedTime(f.toPath()).toMillis(),
(Files.getLastModifiedTime(f.toPath()).toMillis() == LM));
        // 格式化輸出,正確不存在 bug
        System.out.printf("Test Files.getLastModifiedTime DateFormat [%s]\n",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.sss").format(f.lastModified()));


        f.delete();
    }
}

命令行下編譯、執(zhí)行:

# 編譯執(zhí)行
$ javac FileTest.java && java FileTest 

Windows 執(zhí)行結(jié)果

Windows 平臺(tái)不存在此 Bug。

# 編譯執(zhí)行
$ javac FileTest.java && java FileTest
Java Version:1.8.0_202
Test f.lastModified [1599276952718]: true
Test f.lastModified DateFormat [2020-09-05 11:35:52.052]
Test Files.getLastModifiedTime [1599276952718]: true
Test Files.getLastModifiedTime DateFormat [2020-09-05 11:35:52.052]

Mac 執(zhí)行結(jié)果

JDK 8 最新版本,目前仍然沒(méi)有修復(fù)該問(wèn)題。

# 編譯執(zhí)行
$ javac FileTest.java && java FileTest
Java Version:1.8.0_261
Test f.lastModified [1599276952000]: false
Test f.lastModified DateFormat [2020-09-05 11:35:52.052]
Test Files.getLastModifiedTime [1599276952000]: false
Test Files.getLastModifiedTime DateFormat [2020-09-05 11:35:52.052]

Linux 執(zhí)行結(jié)果

# 編譯執(zhí)行
$ javac FileTest.java && java FileTest
Java Version:1.8.0_171
Test f.lastModified [1599276952000]: false
Test f.lastModified DateFormat [2020-09-05 11:35:52.052]
Test Files.getLastModifiedTime [1599276952000]: false
Test Files.getLastModifiedTime DateFormat [2020-09-05 11:35:52.052]

官方 Bug 鏈接

JDK10 已修復(fù),但是之前版本目前仍然未修復(fù)。

  • bugs.openjdk.java.net/browse/JDK-8177809

以上就是W3Cschool編程獅關(guān)于以前偶然發(fā)現(xiàn)的 Java Bug(JDK 9及之前仍未修復(fù))的相關(guān)介紹了,希望對(duì)大家有所幫助。

0 人點(diǎn)贊