你好呀,我是歪歪。
上周我不是发了《我怀疑这是IDEA的BUG,但是我翻遍全网没找到证据!》这篇文章吗。
主要描述了在 IDEA 里面反编译后的 class 文件中有这样的代码片段:
很明显,这玩意就是一个语法错误。
但是当我用其他的编译器打开之后,显示又是正常的。于是我当时就断然的下了一个结论:这是 IDEA 的 BUG。
其实写那篇文章的时候我就在想,这应该是 IDEA 使用的反编译器的 BUG,但是 IDEA 使用的是什么反编译器,工作原理是什么,这一块东西就触及到我知识的盲区了。
我实在是追不下去了。
反正我是在 IDEA 里面才能复现这个 BUG,那就先把锅甩给 IDEA 吧。
但是文章发布之后,有这样的一个评论:
我一看到这个评论,我就知道,排查问题的新方向来了。
FernFlower
直接冲向 github 对应的仓库:
https://github.com/fesh0r/fernflower
在网上搜到的都是这个上面这个仓库,但是你注意看这个仓库的右边的说明:
第一个单词 unofficial,就是非官方的意思。
也就是说这个仓库是“好事之人”为了更好的研究 IDEA 的反编译器,搞出来的一个镜像仓库。
虽然说的是非官方,但是项目维护人员其实都是同一批人。所以这个镜像和官方仓库中的是一模一样的,就直接看这个仓库了。
首先进入这个仓库,我就习惯性的想往 issue 里面钻,但是我发现它没有 issue。
后来才发现它的 README.md 文件第一段就写了:
请将您的错误报告和改进建议发送到这个链接:
https://youtrack.jetbrains.com/issues/IDEA
这个链接点过去,就是 jetbrains 产品的 issues 区域,
众所周知,jetbrains 旗下的产品特别的多,所以我可以只选择 IDEA 相关的:
那么我应该搜索什么关键字呢?
我也不知道,于是我试着搜了一下这个,你别说还真有意外收获:
早在 2 年前,就有人提出了这个问题:
而且除了我们说的类型不匹配的错误外,他还提出了另外一个值得优化的地方:
你看这个 result 是不是被声明了两次,是不是应该被优化一下?
我其实当时也发现这个问题了,但是本着又不是不能用的精神,也就没去深究。没想到歪打正着,在这里又遇到了。那就顺便看看到底啥情况。
所以我顺着这里的这个链接:
找到了这个 pr:
https://github.com/JetBrains/intellij-community/pull/1538
然后我看了一下这次 pr 对应的代码提交。
看了一眼我就直接关闭了。
因为我发现这玩意完全就是超了个大纲,根本看不懂:
既然代码看不懂个,换个思路,反正他说解决了,那么我就看看是哪个版本解决的不就行了吗?
回去一看发现是 2022.1 版本解决的,而我现在的版本是 2021.3:
刚好,那就趁着这个验证的机会升级一波 IDEA。
果然,我升级到 2022.1 版本之后,再次查看 class 文件,变成了这样:
这个算是意外收获,也侧面证明了这类问题确实应该是从 IDEA 的反编译器的角度下手。
我们现在回到类型不匹配的这个错误中来:
官方在前面的链接中,并没有说明这个问题解决了,但是又给我指了一条路。
我顺着这条路,来到了这个链接:
https://youtrack.jetbrains.com/issue/IDEA-203794/Decompiling-bug
从上面的测试用例中可以看出来,当 int 的值比较大的时候,即使它没有被使用,也不会被优化为 true。
那么这个“比较大”的边界是什么呢,或者说分界点是什么呢?
我也不知道,于是我采取了二分策略,找到了边界值:
32767,就是这个边界值。
那么这个值难道有什么特殊含义吗?
我也不知道,于是搜了一下,才发现原来是 short 的边界值:
好吧,short 这玩意着实用的不多,不眼熟也很正常的嘛。
但是它和编译器把这个范围内的、未使用的 int 类型的值变为 true 之间有什么关系呢?
这个我真不知道,因为这个 BUG 官方也没有给解决,也没有给答复。
这个问题最早可以追溯到 2018 年:
但是这个 BUG 下面并没有任何人给任何回复。
时隔四年,在这个问题下是一个程序员和另外一个程序员的一次擦肩而过和无功而返。
虽然我还是没找到具体的触发 BUG 的代码,但是目前足以说明, 下面这个图片中的问题并不是 IDEA 的 BUG,而是 IDEA 的反编译器插件 Fernflower 的 BUG:
另外,其实我做了一次挣扎,我在 Fernflower 的 README.md 文件中看到了这一句描述:
将 int 1 解释为 boolean true,目的是为了解决编译器的 BUG。
我并不知道这个和我的问题有没有相关度,但是我还是试着去找了一下对应代码提交的地方。
我开始想的谁提交的相关的代码,可能在提交的 commit 信息里面会有蛛丝马迹。
但是没有。
我找到了代码对应的地方:
但是这行代码从 2014 年第一次提交的时候就是存在的。也就是说作者在最开始的时候就考虑到了 0 和 true 之间的关系。
只不过我在初始化提交的文件头中看到了一个网站,我以为这里面会有一些线索什么的:
于是我就那么随手一点。好家伙,我是万万没想到,变成不可描述的赌博网站了。
你也不用专门去找了,没啥看的,特别简陋的网站,一眼就是钓鱼网站。
好了,看到这里我想问你一个问题:你知道了这些有什么卵用呢?
是的,没有任何卵用。
那么恭喜你...