为什么我的对象被 IntelliJ IDEA 悄悄的修改了?
背景
最近,在复习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) {
ConcurrentLinkedQueue<String> 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
预览特性(Settings>>Build,Execution,Deployment>>Debugger>>Data Views>>Java>>Enable '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,手动哭脸
为什么我的对象被 IntelliJ IDEA 悄悄的修改了?的更多相关文章
- javascript里面的数组,json对象,动态添加,修改,删除示例
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify Chinesization cool decoration
安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify ...
- 解决Intellij Idea下修改jsp页面不自动更新
解决Intellij Idea下修改jsp页面不自动更新 On frame deactivation:被设置成了Do nothing 解决办法:改为Update resources(更新资源)或者Up ...
- intellij idea 15 修改基础配置加载路径
一.概述 intellij idea 15 默认配置的启动加载路径是"C:\Users\Administrator.IntelliJIdea15",这样会导致占用C盘的空间越来越多 ...
- Cookie对象工具包,对象添加,获取,修改-亲测可用
先来了解下Cookie 和 Session对象的概念吧. 首先,Cookie是客户端缓存技术,大小一般为4kb左右,主要存储一些比较小的信息,常用的例子有用户名和密码,且是不安全的: Session是 ...
- 关于给javascript对象添加、删除、修改对象的属性
以下是自己总结的几种方法 利用动态特性 function Person(){}; var person = new Person(); person.name = 'yy'; person.gende ...
- Intellij idea 中修改java web代码 ,网页不同步
问题可能出在 Intellij idea 没有将源码保存在本地,浏览器访问了缓存而没有访问最新文件 用命令行查看了源码,同步了 接着禁止浏览器缓存,网页同步了 打开火狐浏览器 输入 about:c ...
- 在Intellij IDEA中修改模板中user变量名称
在Intellij IDEA中的注释模板中的${user}名称是根据当前操作系统的登录名来取的,有时候登录名称和我们实际的user名称并不相同. 修改方法如下: 方法一:可以在settings的fil ...
- IntelliJ全家桶修改terminal字体的方法
IntelliJ IDEA 设置Terminal 窗口字体大小 我在Setting中查看了所有和Terminal字样有关的设置,都没有找到设置字体大小的方法,原来Terminal也只需要设置Conso ...
随机推荐
- Java并发包——线程通信
Java并发包——线程通信 摘要:本文主要学习了Java并发包里有关线程通信的一些知识. 部分内容来自以下博客: https://www.cnblogs.com/skywang12345/p/3496 ...
- SVG :可缩放矢量图形(Scalable Vector Graphics)。
SVG 意为可缩放矢量图形(Scalable Vector Graphics). SVG 使用 XML 格式定义图像. SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失 SVG 使用 XML ...
- 又见古老的Typosquatting攻击:这次入侵Npm窃取开发者身份凭证
有些攻击方式虽然听起来很幼稚,但有时候却也可以生效,比如typosquatting攻击——我们上次看到这种攻击是在去年6月份,这本身也是种很古老的攻击方式. 所谓的typosquatting,主要是通 ...
- POJ3977 Subset 折半枚举
题目大意是给定N个数的集合,从这个集合中找到一个非空子集,使得该子集元素和的绝对值最小.假设有多个答案,输出元素个数最少的那个. N最多为35,假设直接枚举显然是不行的. 可是假设我们将这些数分成两半 ...
- LintCode 近期公共祖先
中等 近期公共祖先 查看执行结果 34% 通过 给定一棵二叉树,找到两个节点的近期公共父节点(LCA). 近期公共祖先是两个节点的公共的祖先节点且具有最大深度. 您在真实的面试中是否遇到过这个题? Y ...
- pat(A) 1063. Set Similarity(STL)
代码: #include<cstdio> #include<cstring> #include<set> using namespace std; set<i ...
- ps图片怎样实现渐变
首先我先将一副图片展示给大家: 我所做的效果是想把图片做成渐变.而不改变中间图片的颜色效果. 接下来我来说明一下我的所做思路. 首先将图片中间部分选择出来.然后复制成一个图层. 详细操作是用魔棒进行反 ...
- 字符识别OCR研究一(模板匹配&BP神经网络训练)
摘 要 在MATLAB环境下利用USB摄像头採集字符图像.读取一帧保存为图像.然后对读取保存的字符图像,灰度化.二值化,在此基础上做倾斜矫正.对矫正的图像进行滤波平滑处理,然后对字符区域进行提取切割出 ...
- Robot Framework 初学者上手资料
首先要声明一下这是从http://www.cnblogs.com/yufeihlf/p/5949984.html拷贝的. 在这里只是自己的一个笔记,方便日后添加.修改内容. 总结下Robot Fram ...
- YTU 2697: 血型统计
2697: 血型统计 时间限制: 1 Sec 内存限制: 128 MB 提交: 405 解决: 164 题目描述 黑猫警长在犯罪现场发现了一些血迹,现已经委托检验机构确定了血型,需要统计各种血型的 ...