爱心互助网站开发,广州做外贸网站的公司简介,中国电子建设公司网站,天津seo公司排名背景 最近#xff0c;在复习JUC的时候调试了一把ConcurrentLinkedQueue的offer方法#xff0c;意外的发现Idea在debug模式下竟然会 “自动修改” 已经创建的Java对象#xff0c;当时觉得这个现象很是奇怪#xff0c;现在把问题的原因以及解决过程记录下来#xff0c;希望你…背景 最近在复习JUC的时候调试了一把ConcurrentLinkedQueue的offer方法意外的发现Idea在debug模式下竟然会 “自动修改” 已经创建的Java对象当时觉得这个现象很是奇怪现在把问题的原因以及解决过程记录下来希望你在调试的时候不要踩坑。 调试代码 调试的代码很简单就是多次调用offer方法然后观察ConcurrentLinkedQueue的head和tail属性。 import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;public class ConcurrentLinkedQueueTest {public static void main(String[] args) {ConcurrentLinkedQueueString queue new ConcurrentLinkedQueue();print(queue);queue.offer(aaa);print(queue);queue.offer(bbb);print(queue);queue.offer(ccc);print(queue);}/*** 打印并发队列head属性的identityHashCode* param queue*/private static void print(ConcurrentLinkedQueue queue) {Field field null;boolean isAccessible false;try {field ConcurrentLinkedQueue.class.getDeclaredField(head);isAccessible field.isAccessible();if (!isAccessible) {field.setAccessible(true);}System.out.println(head: System.identityHashCode(field.get(queue)));} catch (Exception e) {e.printStackTrace();} finally {field.setAccessible(isAccessible);}}
} 调试过程 上述代码在Idea中debug模式下head属性会无缘无故的被修改run模式下正常debug模式下关闭所有断点也正常检查ConcurrentLinkedQueue的源码发现head属性只有在构造器和反序列化的readObject共3处地方才会被直接赋值不是cas修改我也仔细检查了offer方法确实没有修改head的地方。而Idea在debug时把head属性修改为第一次offer的Node节点这个现象就很奇怪了。 在run模式下的输出结果多次调用offer方法head属性都是同一个对象debug模式下关闭所有断点也是同样的效果在offer方法中断点然后debug并单步调试Step over在offer方法中断点然后debug并直接运行到下一个断点Resume program 由上可见在debug进入offer方法之后head属性确实被修改了对象已经不是同一个而且这不是偶尔出现而是一直可以复现的Step over和Resume program也表现出了修改head属性不同的时机这让人很费解。 更费解的是就算不在offer方法体里断点在main方法中断点也会出现head被修改的现象。 转战到Eclipse同样的环境同样的操作在run和debug模式下都不会出现head被修改的情况分析 了解到Idea在debug模式下默认开启了toString预览特性SettingsBuild,Execution,DeploymentDebuggerData ViewsJavaEnable toString() object view可是调用toString方法也不至于把对象本身都修改了啊也专门看了下ConcurrentLinkedQueue的内部类Node并没有复写toString方法事后回顾当时在这里疏忽了下文会再介绍但还是关掉特性再测试一遍然而还是同样的结果head属性任然被悄悄的修改了。第二天来到公司在同事的环境IntelliJ IDEA 2019.1上验证了下还是同样的问题排除Idea版本的因素。 郁闷了一会儿就向网友提问了链接不久就得到了IntelliJ IDEA的产品经理yole的回复他的意思还是Idea 的 Data Views 的 toString 在作怪上文已经说过关掉toString特性还是有这个问题但是他给了我一个重要的思路就是在debug模式下ConcurrentLinkedQueue的对象也会被调用toString方法的在队列的toString方法中会获取队列的迭代器而创建迭代器时会调用first方法first方法里就会cas修改head属性。之前确实没考虑到队列本身的toString方法而是去看Node是否重写了toString手动哭脸? 这里需要注意的是尽管关掉toString特性上面问题还是存在原因就在于ConcurrentLinkedQueue是一个CollectionData Views 还有一个选项“Enable alternative view for Collections classes” 平时没注意...所以也会在debug时造成队列迭代器的遍历。把这个特性也一并关掉则上面的问题就不会再出现了。 总结 之前看到有网友在调试低版本的fastjson的反序列化时也遇到过Idea toString的问题虽然这可能不会影响程序的正常执行但是作为开发人员在debug时完全可能会遇到这种被Idea挖坑的情况。对于Data views特性我目前也持保留态度如果不是特别依赖就直接关掉吧。 参考https://blog.csdn.net/dajiangqingzhou/article/details/78676459https://www.cnblogs.com/oldtrafford/p/8612089.html 转载于:https://www.cnblogs.com/ocean234/p/10779784.html