给IDEA道个歉,这不是它的BUG,而是反编译插件的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 之间的关系。

只不过我在初始化提交的文件头中看到了一个网站,我以为这里面会有一些线索什么的:

于是我就那么随手一点。好家伙,我是万万没想到,变成不可描述的赌博网站了。

你也不用专门去找了,没啥看的,特别简陋的网站,一眼就是钓鱼网站。

好了,看到这里我想问你一个问题:你知道了这些有什么卵用呢?

是的,没有任何卵用。

那么恭喜你…

真没什么用

我也不知道这是我写的第几个没有什么用处的知识点了。反正我记得应该不少了吧?

于是我决定要不盘点一下吧?

大概就是说用 Redisson 加锁的时候,之前的 Lua 脚本中用的是 hset 之后用的是 hincrby:

这是我两年多前写的文章了,那个时候经验还不够丰富。

比如现在让我再次回到这个地方,我一看就觉得有故事:为什么平白无故的会把这个地方从 hset 修改为 hincrby 呢?

巧了,刚好我手上有 Redisson 的源码,打开看一眼:

果然是因为有 BUG 才从 hset 修改为 hincrby 的。

找到对应链接,浅看一眼:

https://github.com/redisson/redisson/issues/2551

从标题上看,是说解锁的时候抛出异常说 value 不是 integer 类型。

但是从他给的测试用例来说,和 integer 没有任何关系。

这个 issues 里面有很长的关于这个问题的讨论,有兴趣可以自己去看一下。

我只贴个结论,就是把 lock 的脚本从 hset 修改为 hincrby:

还是怪自己太年轻,错过了一个素材,没有看到事物的本质。

全片就是介绍了 IdentityHashMap 这个玩意,IdentityHashMap 的核心点在于 System.identityHashCode 方法。

然后我又画了很多图来说明 identityHashMap 的存储套路: key 的下一个位置,就是这个 key 的 value 值。它的数据结构不是数组加链表,就完完全全是一个数组。

但是说真的,我在工作中还真没有用过这个玩意。都是 HashMap 直接一把梭。

所以,目前为止,真没什么用。

是从《深入理解Java虚拟机》书里面的一段代码讲起,引出了一个叫做 Monitor Ctrl-Break 的线程。

这个线程是 idea 特有的线程,通过 javaagent 的方式运行起来,对于我们来说完全无感知。

但是当 idea 直接 Run 起来的时候,它又会被作为活跃线程,所以下面的代码就是有问题的。

因为除了主线程之外,还有一个 Monitor Ctrl-Break 线程:

//&#x7B49;&#x5F85;&#x6240;&#x6709;&#x7D2F;&#x52A0;&#x7EBF;&#x7A0B;&#x90FD;&#x7ED3;&#x675F;<br><span class="hljs-keyword">while</span>(Thread.activeCount()>1)<br>&#xA0;&#xA0;&#xA0;&#xA0;Thread.yield();

当时我还费了老大的劲儿搞了这个动图,不知道还有没有人记得:

确实是一个非常冷的知识点,没啥用处,但是还记得我探索这个问题的时候,从一头雾水到逐渐清晰的过程,是一个很美妙的感受。

没有查阅任何资料,就是通过自己平时的小积累和大胆的猜测最终找到了问题的答案。

虽然好像对于实际工作中的帮助不大,所以我把它归属于没有什么卵用的知识点。

但是,这种偏门的事情,你知道了之后,以后万一用上了,那一定是一个非常装逼的场面。

这是一个关于安全点机制带来的长时间睡眠问题。

看到这个案例的时候我想到了之前在书上也看到过相关的例子,当时想的是:这玩意学它干啥啊,我写业务代码而已,肯定是遇不到这样的问题呀。

实际情况是,我确实没有遇到。但是我也确实看到了,我们的监控机制中,有专门针对 safepoint 相关的监控,以及我看到的很多问题排查文章,都会提到这个排查的方向。

以前觉得没啥用的知识点,以后说不定就用上了。

主要是关于使用 volatile ,又使用了输出语句的时候,导致实验结论和预期的不符合,从而引出的各种奇奇怪怪的问题。

比如这个文章中说到的 final 关键字在其中起到的作用。

额,这个知识点吧,确实用处不大。

但是,我在各个技术群里面经常看到大家验证 volatile 特效的时候会踩到加入输出语句的坑。

我都会先问一句:是不是初学者?

如果是的话就别折腾了,也别深究了,这玩意,水很深,你把握不住。

额,这个你看题目就知道…

文章很短,主要是回答了下面这个问题:

结论就是:一回事。

关于 hashCode 的值和对象内存地址之间的关系,据说这是一道面试题,我去翻了一下源码。

hashCode 的值和对象内存地址之间的关系就是:没有关系。

这篇文章是在回答读者的一个问题: Java 的异常是如何抛出来的?

答案藏在字节码中,所以随着这条路找到了 jvm 规范。

而在规范中意外发现一个方法的代码长度,从字节码的层面来说是有限制的。

冷知识,用处不大。

就是看《深入理解 JVM 虚拟机》(第三版)这本书的时候发现其中一段描述有点意思:

于是我去挖了一下。

额…

当时挖的津津有味,但是现在其实我已经忘记了文章里面写的是什么了。

仔细看了一遍,发现,嗯,确实没有骗你,确实是用处不大的知识点

在并发加事务的双重 buff 下,修改事务的隔离级别为串行化。

不是卧龙凤雏,想不出这么绝的方案。

确实属于没有用的范围。

线程池动态调整的时候需要一个自定义队列。

而这个队列,一般来说就是把 LinkedBlockingQueue 简单的修改一下,但是 put 方法也需要进行对应的修改。

但但是线程池里面并没有用队列的 put 方法,而是用的 offer 方法。

这是我之前写的时候完全没有考虑的到的问题,是和一个大佬探讨的时候,大佬给我分享的。

如果只是把场景限定为线程池使用,那么不会有什么问题。但是既然都自定义了,就应该把各个方法都维护好。

用处不是特别大,毕竟用动态调整的方案的人并不多,主要是拿捏一波细节。

反正以后只要碰到时间不对劲的问题,不管它是有多奇葩,多不可思议,想都不用想,十有八九都是时区问题。

朝这个方向找方案就对了。

这篇文章里面有一段描述我写了很长,在那段描述里面,你知道了看门狗的生日是 7 月 4 日,也知道了它有好几个曾用名…

盘点的差不多就是这些了,我记得应该是还有的,但是我实在是想不起来了。

想起来了又怎么样呢?

是的,想起来了也没有什么用。

Original: https://www.cnblogs.com/thisiswhy/p/16308961.html
Author: why技术
Title: 给IDEA道个歉,这不是它的BUG,而是反编译插件的BUG。

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/571097/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring第一个程序

    1、利用Maven导入jar包 2、编写一个实体类 3、编写Spring文件 (beans.xml) 4、测试 1、利用Maven导入jar包 org.springframewor…

    Java 2023年6月5日
    078
  • 事件的监听与发布

    有些时候,我们希望某件事情发生的时候能够触发一个事件,让这个事件帮我们做些事情。比如,在晚上十一点到晚上十二点这段时间,假如还有人在使用我们的软件,我们就触发一个事件播放一首美妙的…

    Java 2023年6月5日
    075
  • CSS

    一、入门基础 1.1、语法 ​ 选择器{ ​ 声明1; ​ 声明2; ​ } Title h1{ width: 180px; color: aqua; } 我是标题 建议这种规范 …

    Java 2023年6月8日
    069
  • Spring基于注解配置AOP

    D:\Java\IdeaProjects\JavaProj\SpringHelloWorld\src\aop.xml <context:component-scan base…

    Java 2023年5月30日
    072
  • 若依系统部分页签点击后刷新页面问题

    问题: ruoyi系统部分页签点击后会刷新页面,但是一部分页签点击后不会刷新页面。 背景: ruoyi前后端分离项目,后端Springboot,前端vue。 解决: 官方文档 同时…

    Java 2023年6月14日
    087
  • 【数据结构】了解KMP算法和部分匹配值、以及next函数值

    最近生活发生了很多变化,没变的是自己还是咸鱼一条,害~~ 1、什么是 KMP 算法 KMP算法是一种改进的字符串匹配算法。 2、KMP算法的思想 KMP算法的关键是利用匹配失败后的…

    Java 2023年6月5日
    099
  • Java Native Interface Specification—Contents

    http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html Original: https…

    Java 2023年5月29日
    0100
  • 多线程编程总结:四、乐观锁、悲观锁、自旋锁

    在多线程编程里面我们经常会锁的使用,实际上在这个过程中,我们的锁主要分为悲观锁和乐观锁,用他们来实现多线程的并发编程控制。 悲观锁: 我们悲观的认为这一段代码或者是数据会发生资源抢…

    Java 2023年5月30日
    071
  • classpath总结

    classpath表示类(.class文件)的路径,在dos环境下使用时有如下情况: 第一种情况,未命名包时(不加package): 在e盘建个demo的文件夹,在demo下建立a…

    Java 2023年6月5日
    0105
  • jce_policy安装【java密码扩展无限制权限策略文件安装】| 异常: java.security.InvalidKeyException: Illegal key size

    异常原因:如果密钥大于128, 会抛出java.security.InvalidKeyException: Illegal key size 异常. 因为密钥长度是受限制的, ja…

    Java 2023年5月29日
    087
  • Eclipse Java EE 创建 Dynamic Web Project

    1. 创建一个web工程,此处用eclipse创建(如果对创建web工程很熟悉,可以不看的,本文目的是做一个记录) 1) 打开新建工程对话框,选择Dynamic web Proje…

    Java 2023年5月29日
    0102
  • NLP学习 资料总结

    NLP目前应用于7个重要领域:1.句法语义分析:对于给定的句子,进行分词、词性标记、命名实体识别和链接、句法分析、语义角色识别和多义词消歧。2.信息抽取:从给定文本中抽取重要信息。…

    Java 2023年6月8日
    0111
  • Ubunt 使用Virtualbox虚拟机NAT无法上网解决办法

    我的Ubuntu安装了一个Centos虚拟机,为了SSH和上外网的方便,使用了NAT+host Only方式,实现内网+外网,但是安装好的Centos不能连接外网,很是无语,只能G…

    Java 2023年5月30日
    061
  • spring 使用异步任务

    1.说明 在springboot 中使用 @Async 实现异步任务处理,下面介绍一下如何实现这个。 2.实现代码 2.1 增加@EnableAsync @EnableAsync …

    Java 2023年5月30日
    081
  • Spring源码学习笔记3——根据BeanDefinition实例化Bean的前置准备

    一丶前言 笔记1和笔记2中我们分析了如何根据xml和注解加载生成BeanDefinition,并注册到BeanFactory,接下载便是Bean的加载,在加载之前会进行一些前置准备…

    Java 2023年6月14日
    068
  • 解决在nginx+php环境下$_SERVER[‘PHP_SELF’]获取不到值的问题

    公司的一个商城项目,然后配置完参数,本来应该可以跑起来的,最近做了一次服务器迁移,打开后台发现浏览器提示重定向次数过多 追踪代码调试,发现是$_SERVER[‘PHP_…

    Java 2023年5月30日
    059
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球