目录

问题描述

最近在研究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源码的详细过程

跟踪调试JDK源码时遇到的问题及解决方法的更多相关文章

  1. vs2010查看quartz.net 2.1.2的源码时其中一报错的解决方法

    问题: 使用vs2010查看quartz.net 2.1.2的源码时,报错: ..\Quartz.NET-2.1.2\server\Quartz.Server\Quartz.Server.2010.c ...

  2. 调试JDK源码时,不能查看变量的值

    前几天本来想以debug模式看一下JDK的源码,进入调试模式时才发现,根本看不到方法里面变量值的情况.为什么呢?JDK现在的版本中,编译过后,去除了里面的调试信息.解决办法是,编译那些类,使其带有调试 ...

  3. eclipse调试jdk源码

    摘要 介绍使用eclipse调试jdk源码 java是一门开源的程序设计语言,喜欢研究源码的java开发者总会忍不住debug一下jdk源码.虽然官方的jdk自带了源码包src.zip,然而在debu ...

  4. eclipse如何debug调试jdk源码(任何源码)并显示局部变量

    最近要看struts2源码 仿照了一下查看jdk源码的方式 首先你要有strtus2的jar包和源码,在struts官网上下载时,选择full版本,里面会有src也就是源码了. jar导入项目,保证可 ...

  5. 解决debug到jdk源码时不能查看变量值的问题

    目录 如何跟踪jdk源码 1. 编译源码 2. 关联源码 3. 大功告成 如何跟踪jdk源码 看到这个标题大概大家都会在心里想谁还跟踪个源码呀,在eclipse中打个断点,以debug的方式运行,然后 ...

  6. 设置Eclipse可以Debug模式调试JDK源码,并显示局部变量的值

    最近突然萌发了研究JDK源码的想法,所以就想到了在自己常用的Eclipse上可以调试JDK源码. 整个设置过程也很简单: 首先你要安装好JDK(我的JDK安装路径根目录是D:\Java\jdk-8u9 ...

  7. 源码编译apache报错的解决方法

    源码编译apache报错的解决方法   问题介绍 在源码编译安装httpd时,./configure执行无错误,到make时就报错,在网络上搜索了很多文章,很多方法如换apr-util的低版本并不能很 ...

  8. JDK源码重新编译——支持eclipse调试JDK源码--转载

    最近在研究jdk源码,发现debug时无法查看源码里的变量值. 因为sun提供的jdk并不能查看运行中的局部变量,需要重新编译一下rt.jar. 下面这六步是编译jdk的具体步骤: Step 1:   ...

  9. eclipse无法断点调试JDK源码的问题

    最近换了新版的eclipse,在jdk源码里面,打断点发现无法进入源码调试,程序直接跳过,已查资料发现自己eclipse配置的是jre环境的. 此处要配成jdk目录才有效 打开preferences, ...

随机推荐

  1. OpenGL实例:三角形

    OpenGL实例:三角形 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 更多请查看:计算机图形学 1. 三角形的旋转 #include <GL/ ...

  2. 算法"新"名词

    这个“新”是对于自己而言. 最近几天接触到很多新的名词,如: 回溯法(backtracking):以前知道,但很少用 动态规划(dynamic programming):序列型.矩阵型.区间型.背包等 ...

  3. Linux Mysql 每天定时备份

    1.创建脚本 dbback.sh,内容如下: #!/bin/bash mysqldump -uroot -p123456 hexin>/work/db_back/hexin_$(date +%Y ...

  4. 同步锁Synchronized与Lock的区别?

    synchronized与Lock两者区别: 1:Lock是一个接口,而Synchronized是关键字. 2:Synchronized会自动释放锁,而Lock必须手动释放锁. 3:Lock可以让等待 ...

  5. 【English EMail】Compensation Planning Memo

    Data Foundation  数据基础 [faʊnˈdeʃən] Interesting newsletter for data foundation practice. Annual Code ...

  6. idea怎么配置spring

    前提基础: 1.idea软件并JDK成功能用 2.有tacate,并会导入. 3.了解jsp和mvc基本结构 详细介绍: https://www.cnblogs.com/wormday/p/84356 ...

  7. Golang 入门 : 切片(slice)

    切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...

  8. 关于B树B+树的详细解释——绝对精彩

    B树是一种完全平衡树,B+树是B树的升级版,使用更多.B树和B+树存在的目的是如何提高磁盘文件的访问(如数据库)效率. 关于B树和B+树的一篇比较好的文章: https://www.cnblogs.c ...

  9. 使用.net core搭建文件服务器

    标题之所以带上.net core,而不是.net就是由于两者在类库的使用以及部署环境有很大的差别,所以特此说明. 长话短说,直接开始! 1.新建一个.net core项目,版本是2.0,为了方便就建一 ...

  10. Python——入门 | 常用python实现

    一.冒泡排序 list = [56,12,1,8,354,10,100,34,56,7,23,456,234,-58] def MP_paixu(): for i in range(len(list) ...