Eclipse默认使用的rt.jar是不带调试信息的,所以在调试时看不到局部变量。本文介绍如何实现在Ecipse调试Java程序能查看局部变量,即重新编译jdk源码包,使其带有调试信息(用-g参数),再加入到Eclipse中。
步骤1:查看javac版本
查看所使用机器的javac版本和JAVA_HOME,相关命令如下:
$ javac -version javac 1.7.0_79 $ echo $JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64/ #也可以在~/.profile文件查看 export JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64/"
步骤2:下载源码文件src.zip
我机器上,/usr/lib/jvm/java-7-openjdk-amd64/src.zip是一个链接文件,链接至上一层目录的/openjdk-7/src.zip,如下:
lrwxrwxrwx 1 root root 20 oct. 22 10:07 src.zip -> ../openjdk-7/src.zip
但该文件压根就不存在,用命令sudo find / -name src.zip查找,也找不到scr.zip。自己到Java官网下载相关的jdk,解压后,即可看到src.zip。比如下载jdk7,在这里下载jdk-7u79-linux-x64.tar.gz,解压后得到jdk1.7.0_79/,在该目录下即可看到src.zip。
PS: 强烈建议下载相关的版本,我有一次不小心下成jdk8,用jdk1.7编1.8的代码,报了很多错,详情见后面。
步骤3:选择文件编译
在$JAVA_HOME 目录下创建文件夹jdk_src,将下载好的src.zip拷贝到jdk_src/,解压,命令如下:
jdk1.7.0_79$ sudo mv src.zip /usr/lib/jvm/java-7-openjdk-amd64/jdk_src/ jdk1.7.0_79$ cd /usr/lib/jvm/java-7-openjdk-amd64//jdk_src/ jdk_src$ sudo unzip src.zip
删除文件夹com, launcher, sunw,只保留文件夹java, javax, org,否则会提示如下错误:
jdk_src/com/sun/image/codec/jpeg/JPEGCodec.java:19: error: package sun.awt.image.codec does not exist import sun.awt.image.codec.JPEGImageDecoderImpl; ^ jdk_src/com/sun/image/codec/jpeg/JPEGCodec.java:20: error: package sun.awt.image.codec does not exist import sun.awt.image.codec.JPEGImageEncoderImpl; ^
从jdk_src/目录下,选择要编译的文件,并将文件名清单存储在文件filelist.txt,命令如下:
sudo find jdk_src/ -name “*.java” > filelist.txt
在JAVA_HOME目录下创建文件夹jdc_debug,然后运行如下命令,编译jdk源码,使class文件带调试信息:
javac -sourcepath ./jdk_src/ -cp jre/lib/rt.jar -d ./jdk_debug/ -g @filelist.txt > log.txt 2>&1 # 2>&1, 1表示stdout, 2表示stderr,2>&1表示将stderr重定向到stdout, # 而stdout又重定向到log.txt,这样错误信息也能保存在log.txt文件里
不幸的是,提示如下错误:
jdk_src/javax/swing/MenuSelectionManager.java:66: error: cannot find symbol
Object o = context.get(SwingUtilities2.MENU_SELECTION_MANAGER_LISTENER_KEY);
^
symbol: variable MENU_SELECTION_MANAGER_LISTENER_KEY
location: class SwingUtilities2
出乎意料的是,在整个源码包,都找不到文件SwingUtilities2.java,也找不到有定义MENU_SELECTION_MANAGER_LISTENER_KEY的地方。
我的解决办法是:先忽略这个错误,接着下面步骤,实践表明,几乎不影响调试时查看局部变量。
步骤4:打包成rt_debug.jar
进入jdc_debug,运行如下命令:
jdk_debug# jar cf0 rt_debug.jar * //jar cf0 jar-file dir-name, creating an uncompressed JAR file jdk_debug# mv rt_debug.jar ../jre/lib/ //将jdc_debug移到jre/lib/目录下
步骤5:将rt_debug.jar添加到Eclipse
Window->Preferences -> Java -> Installed JREs -> 选中java-7-openjdk-amd64 -> Edit -> Add External JARs,将rt_debug.jar加进去。
这样调试起来方便多了,今天下午用该配置好的Eclipse找到了一个很隐蔽的逻辑错误:-)
遇到问题
用jdk1.7编译1.8版本的源代码,提示如下错误:
[parsing started RegularFileObject[jdk_src/java/security/KeyStore.java]] jdk_src/java/security/KeyStore.java:419: error: illegal start of type public default Set<Attribute> getAttributes() { ^
这是因为default关键词是jdk1.8新增的。所以源码包最好下跟jdk版本相符。
参考资料:
[1]stackoverflow: debug jdk source can’t watch variable what it is
[2]debug jdk source can’t watch variable what it is
[3]博文:解决Debug JDK source 无法查看局部变量的问题方案
[4]Recompiling the Java runtime library with debug symbols
微信赞赏
支付宝赞赏