专栏首页后端开发随笔跟踪调试JDK源码时遇到的问题及解决方法

跟踪调试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源码的详细过程

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 细说JDK日志组件

    如上图所示,JDK日志组件核心元素包括:Logger,Handler,Filter和Formatter,他们的关系如下: --Logger ...

    2Simple
  • Docker实践之03-Dockerfile指令详解

    所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个nginx镜像的容器,再进行修改一样,基础镜像是必须指定的。而FROM就是指定基础...

    2Simple
  • Tomcat vs Jetty vs Undertow性能对比

    Tomcat,Jetty和Undertow是目前比较主流的3款Servlet容器,而且Spring Boot框架还提供了对它们的集成支持(默认使用的是Tomca...

    2Simple
  • python3中的缺省参数和命名参数

    于小勇
  • 中国人口红利消失的产业机会

    联合国《世界人口展望 2019》对未来各国人口增长和人口结构变化进行预测,认为我国的人口增长和变化更接近于使用中等变量预测和低变量预测的中间值的结果。

    庄帅
  • TAF 必修课(二):Reactor多线程模型

    最近看了很多文章和分享,非常受益, 实习所做项目主要用到了TAF,有必要对之前的学习做个梳理和总结,网络线程模型及请求接收过程,必修亦为基础、通用,故取其名。

    serena
  • Android菜鸡字节跳动秋招面筋,面试客户端岗位10天拿offer(已意向书)

    秋招过半,在网上上看了很多大佬的面经,也加了很多交流群,受到了很多朋友的提点,今天终于轮到我来分享面经啦,面试了几家大厂,最后拿到了字节跳动客户端的 offer...

    Android技术干货分享
  • python中序列的排序,包括字典排序、列表排序、升序、降序、逆序

    我们知道python中的内建序列包括字典、列表、元组、字符串等,序列是python中最基本的数据结构。

    刘金玉编程
  • JNI函数加载

    当Java代码中执行Native的代码的时候,首先是通过一定的方法来找到这些native方法。JNI有如下两种注册native方法:

    小蚂蚁与大象
  • AI一分钟 | 小鹏汽车回应前苹果员工窃取商业机密:积极配合相关调查

    今日(7月11日),有外媒报道称,苹果前雇员张晓浪因窃取商业机密罪被美国联邦调查局逮捕并被起,该员工即将加入小鹏汽车。

    AI科技大本营

扫码关注云+社区

领取腾讯云代金券