这篇文章主要介绍了Java中的Bug分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中的Bug分析文章都会有所收获,下面我们一起来看看吧。

背景

15年在中信银行做持续集成时,由于当时的项目是基于三方采购的 Java 配置开发平台做的,平台自己基于 Ant 插件实现了增量和热部署。

其中有几个项目在持续集成部署时,经常发现 Linux 平台部署成功后(Windows 不会出现,Linux 也是偶发现象),新版本代码并没有生效(反编译 class)。

起初我是在本地 windows 上跟踪调试基于 Ant 插件的代码,但始终重现不了(最后测试发现 Windows 无此 Bug)。

后来,通过分析代码逻辑,其中有段逻辑是通过文件的最后修改时间(File.lastModified())来判断要不要覆盖部署的,最后通过单测发现,是由于 JavaFile.lastModified() 方法在 WindowsLinux/Unix平台获取的精度不一样导致的,Windows 精度为毫秒,而 Linux/Unix 只能到秒(JDK Bug:JDK-8177809)。

所以也解释了,为什么是偶发现象,文件修改时间如果判断的两个值正好跨秒时,部署就是成功的,否则失败。

Bug 重现

测试代码:FileTest.java

importjava.io.File;importjava.io.IOException;importjava.nio.file.Files;importjava.text.SimpleDateFormat;publicclassFileTest{privatestaticfinallongLM=1599276952718L;publicstaticvoidmain(String[]args)throwsIOException{//java版本号System.out.println("JavaVersion:"+System.getProperty("java.version"));Filef=newFile("test.txt");f.createNewFile();//设置最后修改时间f.setLastModified(LM);//获取修改时间,存在bugSystem.out.printf("Testf.lastModified[%s]:%b\n",f.lastModified(),f.lastModified()==LM);//格式化输出,正确不存在bugSystem.out.printf("Testf.lastModifiedDateFormat[%s]\n",newSimpleDateFormat("yyyy-MM-ddHH:mm:ss.sss").format(f.lastModified()));//Files.getLastModifiedTime()获取修改时间,同样存在bugSystem.out.printf("TestFiles.getLastModifiedTime[%s]:%b\n",Files.getLastModifiedTime(f.toPath()).toMillis(),(Files.getLastModifiedTime(f.toPath()).toMillis()==LM));//格式化输出,正确不存在bugSystem.out.printf("TestFiles.getLastModifiedTimeDateFormat[%s]\n",newSimpleDateFormat("yyyy-MM-ddHH:mm:ss.sss").format(f.lastModified()));f.delete();}}

命令行下编译、执行:

#编译执行$javacFileTest.java&&javaFileTestWindows 执行结果

Windows 平台不存在此 Bug。

#编译执行$javacFileTest.java&&javaFileTestJavaVersion:1.8.0_202Testf.lastModified[1599276952718]:trueTestf.lastModifiedDateFormat[2020-09-0511:35:52.052]TestFiles.getLastModifiedTime[1599276952718]:trueTestFiles.getLastModifiedTimeDateFormat[2020-09-0511:35:52.052]Mac 执行结果

JDK 8 最新版本,目前仍然没有修复该问题。

#编译执行$javacFileTest.java&&javaFileTestJavaVersion:1.8.0_261Testf.lastModified[1599276952000]:falseTestf.lastModifiedDateFormat[2020-09-0511:35:52.052]TestFiles.getLastModifiedTime[1599276952000]:falseTestFiles.getLastModifiedTimeDateFormat[2020-09-0511:35:52.052]Linux 执行结果

#编译执行$javacFileTest.java&&javaFileTestJavaVersion:1.8.0_171Testf.lastModified[1599276952000]:falseTestf.lastModifiedDateFormat[2020-09-0511:35:52.052]TestFiles.getLastModifiedTime[1599276952000]:falseTestFiles.getLastModifiedTimeDateFormat[2020-09-0511:35:52.052]

关于“Java中的Bug分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java中的Bug分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。