DEBUG 怪诞之背后的秘密

发布于 2022-09-22 00:32:07 字数 3361 浏览 201 评论 0

缘起

昨天接到同事高禹的报告,说 eql 从0.0.72升级到0.0.96版本后,原来可以用的代码,有一处不能用了,但是如果把参数名从 table 改为 table1,那就没问题。凭直觉感觉这应该是一个很有意思的 BUG,我就他那边把出 BUG 的 SQL 和代码都要过来了,先添加一个 新的测试用例。然后我就直接RUN这个测试用例,发现果然不通过。很纳闷,开始单点调试(DEBUG)看看,但是结果竟然反转了,竟然能通过了。多次试验皆如此。有意思有意思,简直百思不得其解了。

重现

随着对代码更进一步的跟踪与分析,我逐渐发现了原因了。为了简单的重现原因,我截了两个图,第一张图是加了两个断点跑的图,结果是v1和v2相等的,都是同样的一串内容。如下:

第二张图是去掉了第一个断点,只保留第二个断点,结果是v1和v2完全是不一样的东西。如下:

匹夫无罪,怀璧(Map 动态代理)其罪

到底是为什么呢?从两张图上的右下角的 console 输出差别可以看出来,在 debug 断点时,IDE 为了展示变量的概要信息,其实是做了一些调用的。在第一张图停在第一个断点的时候,IDE 其实在背后调用了 Map.isEmpty 和 Map.size 方法,然后才是被调试程序调用了 Map.get 方法。而在第二张图只有一个断点的时候,IDE 在 Map.get 方法调用之前,并没有调用 Map.isEmpty 和 Map.size 方法。

问题是,这个 Map 不是普通的 Map,是一个 JAVA 的动态代理,如下:

所以,这个代理实现上有缺陷,取 map 中属性为 table 的值时,又去找了名字为 table 的属性,结果 HashMap 中刚好有这个属性,于是取出来了,v1 的值就成了 HashMap$Node 类型了(见下图),导致了问题的存在,所以改成 table1 就没这个问题,但是如果使用 entrySet 肯定有问题。

问题定位了,修复起来就简单得多,只需要在 if 判断 Map 类型之外,取属性/方法的时候 加一个 else 就行了。

为什么要用动态代理

当初为什么要做一个动态代理呢,其实这个跟 eql 的参数传递实现有关系。一开始是并没有这个动态代理的,直到某一天,生产环境上老是报告空指针异常,然后异常的堆栈就指向了 eql 的内部实现。我一查,都是使用 JavaBean 传递参数遭遇问题,因为 JavaBean 里面有一些属性并没有被 sql 用到,却调用 get 方法,导致空指针异常。比如下面这样:

public class Person {
      // ...
      public String getName() {
             return name;
      }
      public String getImage() {
             throw new NullPointerException();
      }
}
-- [findPersonByName]
SELECT NAME,SEX,EMAIL,ADDRESS FROM PERSON WHERE NAME = #name#

eql 的使用者感觉很无奈,sql 里面只用到了 name,并没有使用 image,为什么要调用 image 方法呢。确实是这样子,刚开始时,我是为了省事,把 Bean 的所有属性都转换成 Map 使用了,而不会管这个属性在 sql 中有没有实际使用到。(注:JavaBean 的 getter/setter 方法应该只是简单的 get 和 set,抛出异常是违反约定的)。所以为了避免这种无用的调用,我就开挂了 Map 的动态代理,只有等真正需要读取属性的时候,才去调用(Map 就用 get 取,JavaBean 用 getter 或者 filed 取)。然后这就种下了本次问题的因了。

总结

Debug 断点模式下,IDE 为了展示堆栈上变量的信息,经常会调用一些方法,比如 toString() 方法,比如 Map.isEmpty,Map.size 等等。这些方法一般情况下都不会有问题,所以 DEBUG 与非 DEBUG 行为上一般都是一致的。但是在某些特殊情况下,却可能产生不一致的行为,比如本案所示,比如当初我在跟踪 druid 的 sql 解析代码时,就发现 IDE 的 DEBUG 窗口的一些变量直接就报告了空指针异常,然后我发现原来作者对变量的 toString() 方法实现没有特别考虑和测试。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文