我有一个不知道是好还是不好的习惯,搞不懂的一些玩意儿,喜欢调试然后单步执行看这玩意儿到底是怎么运行的.
今天看到正则表达式的时候,appendReplacement()这个方法怎么也看不明白它是怎么工作的,于是想调试源码单步执行,然后watch几个关键的变量看看.
刚开始的时候,eclipse里调试模,单步,发现没有办法进入方法内. 用google百度了一下,发现是JRE配置的问题. 使用jre是不可以的,需要使用jdk的环境.(之前真的没有注意到这一点)
于是window->Preferences->Java->Installed JREs 添加换到jdk_xxx.
这里注意一下源码是不是正确的,如果不对的话Source Attachment哪里手动改一下.
然后Project的BuildPath里remove掉jre的环境,换成刚添加jdk_xxx
然后再调试的时候就可以进入到jdk提供的方法体内了.
之后又出现一个问题,折腾了我快两个小时(折腾的时间长的一个重要原因是,今天我"嘿嘿嘿那啥墙"的VPS不知道怎么了,google半天打不开...).
不得不说一下,微信就是一个扯闲篇的地方,前不久加了某某论坛的一个群,大家平时除了扯淡就是调戏女群主,问了一个正经问题,没人搭理...
添加监视变量之后,发现无论怎么执行,jdk方法体内的变量都一直是"cannot be resolved to a variable". 当然这个问题最常见的原因就是变量超出作用域. 但是,很明显,这里不是...
由于谷歌一直打不开,只能百度了一下,可以说百度今天终于靠谱一回,一下就查到问题原因了,是因为官方jdk在打包的时候,为了控制体积有意去掉了一些用于debug的信息,有人说是LocalVariableTable这个表被移除了,所以无法从上下文中获取足够的信息来监控变量.
想重新得到这个表可以使用javac -g来重新编译源码.
还查到一个常识问题...
eclipse并不是使用javac来编译的,而是使用自己的编译器EJC. EJC也可以得到javac -g的效果,需要勾选Add variable attributes to generated class files这个复选框. 具体位置看这个图:
但是现在的问题,自己的代码调试的时候没问题. jdk提供的方法还是不行啊. 于是十分不情愿的去查怎么重新编译jdk源码.
查到一个貌似很牛的办法:http://www.cnblogs.com/davidwang456/p/3790550.html
但是尝试了很多次都不成功(试之前一定记得备份一下rt.jar...)
恰好这个时候又看到一篇博客...
这个简单很多了,
直接把src.zip解压,eclipse里新建一个工程,把java和javax这两个源码文件夹复制到新工程里,build一下. 然后把对应的class文件覆盖回rt.jar...
遇到一个问题,源码拖进来之后一片飘红,各种报错. 大概看了一下,都是因为调用了com.sun这个package里的内容. 不管他,把这个直接改成warning保证build成功就可以了. 因为之后还是会放到原来的地方.package路径,调用的内容都没有变,我们只是重新编译添加了一些信息而已.
Windows -> Preferences -> Java -> Compiler -> Errors/Warnings -> Deprecated and trstricted API -> Forbidden reference ->改成warning
之后检查一下还有没error的文件,有的话直接删除掉.
我的eclipse几乎都是默认配置,是自动build的,所以源码一拖进来,内容太多,直接电脑干死了.
等编译完成后,找到JAVA_HOME\jre\lib\rt.jar文件,用解压缩软件打开,找到工程对应目录bin下的对应的文件夹,拖进去覆盖原先的java和javax. 然后重启eclipse.
目前来看,调试的时候,监控变量是正常的. 程序跑起来也没有其他问题.
刚开始用1.6这样搞的时候,classloader老是报错. 后来在1.8上试了一下是可以的.
先用着,以后万一有问题,应该也是很严重到一眼就能看出来的.
这里觉得oracle有点拧巴了,既然都放到jdk里了,肯定都是开发人员在用.何必还阉割调试需要的信息呢. 估计也很少有人闲到去调试jdk源码...但是感觉debug单步执行,是学习的一个好办法呀. 至少比死抠源码来的直观.