跟踪调试JDK源码时遇到的问题及解决方法
目录
- 问题描述
- 解决思路
- 在IntelliJ IDEA中调试JDK源码
- 在eclipse中调试JDK源码
- 总结
问题描述
最近在研究MyBatis的缓存机制,需要回顾一下HashMap的实现原理。于是在IntelliJ IDEA中单步跟踪调试HashMap的put(K key, V value)方法,不曾想执行到断点处时,单步调试(Step Into
)无法进入到HashMap的put(K key, V value)方法内部,而是直接跳过了,效果跟Step Over
是一样的。
已经确认不是快捷键冲突导致的问题,但是始终无法Step Into
跟踪。
解决思路
一开始我以为是IntelliJ IDEA本身不支持单步调试JDK源码(现在觉得这种想法简直是幼稚),于是就切换到eclipse中调试,但是在eclipse中调试时发现跟踪到HashMap内部的put(K key, V value)方法内部时,无法查看局部变量的值。于是Google之,原来是因为JDK源码在编译时已经去掉了调试信息,解决方法是重新编译JDK源码。虽然问题解决了,但是心里总是觉得哪里不对劲,毕竟IntelliJ IDEA这么高级的IDE,不可能不支持跟踪调试JDK源码(因为JDK源码跟我们自己写的JAVA程序并没有本质上的差别),于是继续Google之,发现有人遇到同样的问题。其实很简单,因为IntelliJ IDEA默认在调试选项中关闭了对JDK源码的调试支持,打开即可。虽然这个问题本身没有技术含量,但是我相信遇到的人应该不少(如果去跟踪JDK源码实现的话)。因此,我想把如何在IntelliJ IDEA单步跟踪调试JDK源码以及在eclipse中调试JDK源码时无法查看局部变量值的解决方法进行一个系统性的总结,希望能对看这篇文章的人有用。
在IntelliJ IDEA中调试JDK源码
在IntelliJ IDEA中默认是无法单步跟踪调试JDK源码的,这是因为默认关闭了对JDK源码的调试支持,只需要打开即可。设置路径:"File" -> "Settings" -> "Build,Execution,Deployment" -> "Debugger" -> "Stepping",在右边的设置窗口可以看到这么一项:"Do not step into the classes",其中就包含了JDK源码包,如下图所示:
正如在截图中的文字说明,如果希望在IntelliJ IDEA中单步调试JDK源码,只需要在"Do not step into the classes"选项中取消对应的Java包名复选框按钮勾选即可。不清楚IntelliJ IDEA为什么要做这个默认限制?
在eclipse中调试JDK源码
在eclipse中单步调试JDK源码时会发现,无法显示局部变量值,这对于跟踪调试是非常不方便的。原因是JDK源码在编译时去掉了调试信息,如果需要能够查看局部变量信息,必须手动重新编译JDK源码,增加对调试信息的支持。如下文字是根据文章调试JDK源码,无法追踪显示局部变量的解决方案实践整理而得。
在Windows系统上,重新编译JDK源码步骤如下:
1.进入到JDK根目录下,解压源码包(src.zip)在当前目录,如下入所示:
完成JDK源码包解压之后,进入到刚刚解压的src目录下,删除java,javax和org之外的其他目录。
一个小插曲: 实际上,只需要编译src目录下的java,javax和org目录下的java文件即可,在编译之前需要删除其他目录。如果全部编译,中途也会出错,无法正常编译成功。
2.打开Windows控制台,进入到JDK根目录,使用dir
命令列出刚刚解压出的src目录中所有java文件绝对路径清单,并保存到指定文件。
> dir D:\sun\jdk-8u121\src\*.java /s /b /x > filelist.txt
在这里使用了dir
命令的“/s”,“/b”,"/x"参数将src目录下的所有java文件的绝对路径保存到文件filelist.txt中。
3.重新编译JDK源码,加入调试信息。
首先,进入到JDK根目录下,创建jdk_debug目录,用于保存编译后的class文件。
其次,打开Windows控制台,进入到JDK根目录路径下,执行JDK源码编译。
> javac -J-Xms16m -J-Xmx1024m -sourcepath src -cp jre\lib\rt.jar -d jdk_debug -g @filelist.txt >>log.txt 2>&1
命令大致解释如下:编译刚刚在src目录下列在filelist中的java类到jdk_debug目录下,并把输出日志打在log.txt文件中。
这里需要注意: 我们需要用当前版本的jdk去编译,不要跨版本编译(eg.1.7去编译1.8的jdk)。
根据机器性能和编译java文件数量的多少所耗费的时间不同。
4.打开Windows控制台,进入到JDK根目录下的jdk_debug路径下,打包该目录下刚刚编译的class文件到rt_debug.jar。
> jar cf0 rt_debug.jar *
5.把这个生成的rt_debug.jar包复制到JDK_HOME\jre\lib\endorsed。如果没有endorsed目录,自己创建一下。
6.再去尝试调试源码,发现局部变量可以追踪了。
总结
对于Java的集成开发环境,IntelliJ IDEA的功能还是比eclipse强大很多。比如,在eclipse下无法查看JDK的某些源码,但是IntelliJ IDEA会自动反编译为Java源码,这对于调试是非常有帮助的。
【参考】
[1]. https://blog.csdn.net/daerzei/article/details/79717717 IDEA调试JDK源码的详细过程
转载于:https://www.cnblogs.com/nuccch/p/9100209.html
跟踪调试JDK源码时遇到的问题及解决方法相关推荐
- 调试JDK源码-ConcurrentHashMap实现原理
调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hash ...
- 调试JDK源码-一步一步看HashMap怎么Hash和扩容
调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hash ...
- 设置Eclipse可以Debug模式调试JDK源码,并显示局部变量的值
最近突然萌发了研究JDK源码的想法,所以就想到了在自己常用的Eclipse上可以调试JDK源码. 整个设置过程也很简单: 首先你要安装好JDK(我的JDK安装路径根目录是D:\Java\jdk-8u9 ...
- 调试JDK源码-Hashtable实现原理以及线程安全的原因
调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hash ...
- 调试JDK源码-HashSet实现原理
调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hash ...
- 通过CLion 调试JDK源码
通过CLion 调试JDK源码 0. 简述 0.1 使用环境: 宿主机操作系统:Windows 10 专业版 虚拟机软件:VMware® Workstation 16 Pro 虚拟机操作系统:[ubu ...
- Android 源码编译及常见错误及解决方法
Android 源码编译及常见错误及解决方法 参考文章: (1)Android 源码编译及常见错误及解决方法 (2)https://www.cnblogs.com/kyyblabla/p/360393 ...
- 云帆教育大数据分享-Flume-0.9.4源码编译及一些编译出错解决方法
Flume-0.9.4源码编译及一些编译出错解决方法 由于需要在Flume里面加入一些我需要的代码,这时候就需要重新编译Flume代码,因为在编译Flume源码的时候出现了很多问题,所以写出这篇博客, ...
- php iconv 空格,PHP_PHP中iconv函数转码时截断字符问题的解决方法,iconv是转换编码的,但是在中 - phpStudy...
PHP中iconv函数转码时截断字符问题的解决方法 iconv是转换编码的,但是在中文转码时候出现显示不全问题. iconv("UTF-8","GB2312//IGNOR ...
最新文章
- 负载均衡,会话保持,session同步
- 影响国家安全的四项新兴技术
- c语言链表容易犯的错误,急求大牛啊这个容易的链表到底在哪出错了
- 时间序列数据库的秘密(3)——加载和分布式计算
- exfat linux 驱动_(实例)Linux 内核添加exfat驱动
- 对于Mybatis在C#.Net中个人使用的总结(一) Mybatis 的结果映射
- Java core 包_feilong-core 让Java开发更简便的工具包
- 浅谈equals与==
- 补码,反码,原码的范围总结
- 运维之我的docker-不要在给你的docker安装ssh server
- python万年历代码_利用python实现万年历
- Microsoft Lync2013客户端下载
- 廉价的新iPhoneSE会吸引哪些用户换机?
- 累次积分怎么计算_什么是累次积分
- python 声音基频f0_如何得到一个曲子的基频?
- Sushi的MISO:不断扩展的DeFi边界
- 测试Java测试Java测试Java
- Xftp安装或卸载报1605和1628问题
- python 换页符_Python用什么方法可以将换行符分割成多行?
- 拉结尔派遣任务辅助介绍 拉结尔快速升级脚本挂机工具
热门文章
- WinCE5.0如何安装.NET3.5
- 水仙花数(类型:一级、C++)
- 使用Go语言+Protobuf协议完成一个多人聊天室
- iptables中关于limit和limit-burst的解释
- 发掘VS2005 SP1 (一)
- 01【在线日志分析】之Flume-1.7.0源码编译导入eclipse
- SQL Server 2012 中的 Service Broker功能的一些改进或增强
- Oracle10g数据库归档与非归档模式下的备份与恢复
- VS.NET 学习方法论——我的VS.NET学习之旅
- 右下角android sdk content loader 加载很慢的解决方法