其他分享
首页 > 其他分享> > 写一个正确的状态机有多难

写一个正确的状态机有多难

作者:互联网

最近给JDK修了一个存在3年的bug。故事的起因是这样的,我们的一个测试在Windows下会莫名其妙地卡住,但是如果稍微把项目文件夹改个名字,增加或者减少一个字符(比如说从gradle改成gradle1或者gradl),这个测试就如丝般顺滑。

俗话说,能重现的bug都是好bug。一番调试之后,发现问题似乎出在JDK本身。

故事要从Argument File说起,这玩意的中文名是啥我也不知道,就不翻译了。大家都知道,Java世界里的一切最终都会变成java命令行的调用。在Windows上,大概长这样:

java -Xmx2g -cp "C:\1.jar;C:\2.jar" Main doSomething

如果你有一个很大的应用,引用了成百上千个jar包,那么你的classpath可能会特别长,长到几十K都装不下。然而,Windows万分悲痛地告诉你,不好意思,我的命令行长度是有限制的,不能超过8191个字符。

你:……

1

以前,大家对此的解决方案一般是,创建一个空jar包,然后把这个巨型的classpath写到manifest文件里,然后引用这个空jar包即可:https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html 。Bazel就是这么干的

JDK 9之后,官方给了一个解决方案:Argument Files

简而言之,你不是有个巨型无敌长的classpath么?不用直接传到命令行里了,先把这个巨型的参数-cp "C:\1.jar;C:\2.jar;...;C:\10000.jar"写到一个文件里,比如说叫classpath.txt,然后直接用java @classpath.txt ...就行了,java命令会自动帮你展开。要注意的是,不仅是classpath,任何被java接受的参数都可以用这种方式传递。

坏就坏在Argument File的处理上。我一步一步研究上面遇到的那个诡异bug,最终找到了一个可以复现的样例。在特定情况下,Argument File的读取会出现问题。比如说,如果你有一个Argument File,内容是:

-cp ".;C:\app.jar" Main

我们假定Main类存在于app.jar中,因此一切正常。接下来,我们逐渐向双引号中增加.;

-cp ".;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;C:\app.jar" Main

你会发现,当这个文件增长到一定长度(大约4100字节)时候,突然,java告诉你:

大专栏

标签:java,正确,jar,classpath,Argument,状态机,多难,cp,bug
来源: https://www.cnblogs.com/liuzhongrong/p/12371560.html