背景
在学习JDK源码的时候,免不了需要调试JDK的源码。
比如:想理解ConcurrentHashMap的put(K k, V v)方法,JDK自带的rt.jar文件是支持断点调试,但是却看不到变量的具体值,对于理解实现非常不方便。
如下:
package org.github.thread; import java.util.concurrent.ConcurrentHashMap; public class Test28 { public static void main(String[] args) { ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); map.put("sdf", "ac"); System.out.println(map); } }
在map.put(“sdf”, “ac”)处增加断点,然后进入put方法里面看具体的执行过程。
有两个比较明显的问题(1)put的参数变量命名也变成了arg0,arg1和arg2(2)变量值也看不到。
步骤
只要是制作一个可调试的rt.jar
(1)创建两个目录d:jdk_src和d:jdk_rt
(2)将src.zip解压到d:jdk_src目录
(3)执行命名dir /B /S /X *.java > filelist.txt 生成filelist.txt文件
要查看一下,自动生成的filelist.txt中是否有内容哦,没有数据的话下面的操作是没用的
(4)把JDK安装目录(复制src.zip的那个目录)下jre/lib下的rt.jar复制到jdk_srcsrc目录下
(5)生成一些可调试的class文件夹
执行命令: javac -J-Xms16m -J-Xmx1024m -sourcepath D:jdk_srcsrc -cp D:jdk_srcsrc
t.jar -d D:jdk_rt -g @filelist.txt > log.txt 2>&1
成功后,jdk_rt文件夹会产生一些可调试的class文件夹,如果没有,请打开jdk_src/log.txt,ctrl+F查找“错误”,并解决。
一般,将报错的java路径及路径对应的文件删除,再执行dir /B /S /X *.java > filelist.txt即可。
(6)将这些文件打包成Jar
执行命令:
jar cf0 rt_debug.jar *
(7)替换原rt.jar为新的rt_debug.jar
备注:如果替换rt.jar运行失败,可以从原rt.jar拷贝相关的class文件到新rt-bubug.jar文件对应的地方。
如:我在替换rt.jar的过程中遇到运行java程序报错Error occurred during initialization of VM java/lang/NoClassDefFoundError: sun/misc/Cleaner
然后打开rt.jar和rt-debug.jar的文件发现,rt-debug.jar里面确实少了sun相关的目录,我就把原来的全部拷贝到新的里面,运行就OK了。
bebug中修改变量的值:当在debug模式下调试到断点时,在“Variables”视图中的“Value”栏中直接修改变量的值,即可。