[讨论] 为什么有时候调试代码的时候看不到变量的值。
xgj1988
2011-04-26
现在有以下情况,我想跟一下SUN JDK的某个地方的代码想看看。但跟踪之后不能查看代码的情况。我用的是eclipse .但是有些代码又能查看到。不知道怎么回事。
下面是图。 不知道我说的这个问题和 http://hllvm.group.iteye.com/group/topic/25725 这个问题是不是有一定的关系。。希望大家帮讲解下。 |
|
RednaxelaFX
2011-04-26
哈哈,昨天我做培训的时候还说过这个…
跟另外那帖没什么关系。这个问题很简单,就是你要调试的类的Class文件里没有包含LocalVariableTable属性表。在用Java源码编译器编译Java源码得到Class文件的时候,传-g参数就会有符号信息了。 如果你遇到看不到局部变量信息的类你手上有源码的话,就加上-g再编译一遍吧 |
|
xgj1988
2011-04-26
RednaxelaFX 写道 哈哈,昨天我做培训的时候还说过这个…
跟另外那帖没什么关系。这个问题很简单,就是你要调试的类的Class文件里没有包含LocalVariableTable属性表。在用Java源码编译器编译Java源码得到Class文件的时候,传-g参数就会有符号信息了。 如果你遇到看不到局部变量信息的类你手上有源码的话,就加上-g再编译一遍吧 eclipse 查看源代码是根据 LocalVariableTable 属性表查看的?那你的意思是我要把JDK的源代码重新编译一份啊? |
|
xgj1988
2011-04-26
而且为什么有的源代码他有 localvariable table 信息,有的没有呢?
|
|
IcyFenix
2011-04-26
原因撒迦说了,没有生成LocalVariableTable属性。这时候jdwp能在上下文找到变量的值,可是它不认识变量的名字啊,我来做个step by step就看的很清楚了。
代码: public class A { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class B { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class T { public static void main(String[] args) { A.foo(1, "2", new Object()); B.foo(1, "2", new Object()); } } 编译: D:\Test>javac -g:lines A.java D:\Test>javac -g B.java 调试: |
|
xgj1988
2011-04-26
IcyFenix 写道 原因撒迦说了,没有生成LocalVariableTable属性。这时候jdwp能在上下文找到变量的值,可是它不认识变量的名字啊,我来做个step by step就看的很清楚了。
代码: public class A { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class B { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class T { public static void main(String[] args) { A.foo(1, "2", new Object()); B.foo(1, "2", new Object()); } } 编译: D:\Test>javac -g:lines A.java D:\Test>javac -g B.java 调试: 我感觉有问题。下面我依次写出来: 1:你开的开发开发环境是eclipse 吗?如果是的话,你先用命令行把代码编译了,然后再拷贝到eclipse里面吗? 2:如果你是按照上面的说法做的,那么我就可以得出,eclipse默认编译项目的时候都带有-g这个参数,不然我们自己调试自己的源代码的时候也会找不到LocalVariableTable而导致不能查看。 3:如果第二条我的假设成立,那么eclipse肯定有一个全局执行java命名的配置文件,那么这个文件在哪里?如何看? 4:就是你的回答还没有帮我解决的一点问题就是,为什么同一个rt.jar有些代码调试的时候有localvariableTable,而有的没有。难道sun的伙计不是全部编译的,而是一个文件一个文件编译的?再编译的时候可能忘了用-g(当然了,也有可能,因为可能早版本的java源代码不需要编译,所以就没编译,所以就没有localvariabletable,至于新版本新加的类可能有些也有localvariabletable,有些无。我想测试一下才能下结论) 5:就是谢谢你的热心回答。 |
|
xgj1988
2011-04-26
还有一点。你的图片是怎么发出来的,我发图片是先放到blog里上传,然后再贴地址,但是看到你为了帮我解决这个问题,贴了两个图,应该不是用这么麻烦的方式吧,是不是javaeye有其他功能,可以快速贴图的。
如果你是贴图的方式和我一样。那么我真的万分感动。 |
|
IcyFenix
2011-04-26
不用javac,用ecj当然也可以,Eclipse里面也可以设置是否要生成LocalVariableTable属性,我写那2行命令行只是为了让你看清楚一些。
eclipse的设置在这里(Add variable attributes to generated class files那个复选框): rt.jar里面是否都带有调试信息,我没有逐个类验证,不过我想当然地、不负责任地、拍个脑袋地说:应该是吧。你截图中的是equniox里面的类,不是rt.jar的。 贴图……圈子貌似是没有贴图功能,呃,是不方便。我是在博客的草稿箱放了一个稿件,专业用来上传图片的。 |
|
RednaxelaFX
2011-04-26
Sun的JDK里,product的rt.jar是只有LineNumberTable没有LocalVariableTable的。也就是说跟不加-g或者加上-g:lines一样。
圈子的帖不能直接贴图这个我也觉得很奇怪… xgj1988 写道 2:如果你是按照上面的说法做的,那么我就可以得出,eclipse默认编译项目的时候都带有-g这个参数,不然我们自己调试自己的源代码的时候也会找不到LocalVariableTable而导致不能查看。
对的,Eclipse默认就是会让编译器带上调试信息的。配置的位置在上面IcyFenix的截图里有了。 xgj1988 写道 3:如果第二条我的假设成立,那么eclipse肯定有一个全局执行java命名的配置文件,那么这个文件在哪里?如何看?
你做了一个错误的假设:Eclipse不是用javac来编译Java源码的,而是用它自己的编译器,名字叫ECJ。同样支持-g参数。配置的位置参考上一点。 xgj1988 写道 4:就是你的回答还没有帮我解决的一点问题就是,为什么同一个rt.jar有些代码调试的时候有localvariableTable,而有的没有。
是都没有吧… j2se/make/common/Defs.gmk # Any debug build should include all debug info inside the classfiles ifeq ($(VARIANT), DBG) DEBUG_CLASSFILES = true endif ifeq ($(DEBUG_CLASSFILES),true) JAVACFLAGS_COMMON += -g endif JAVACFLAGS = $(JAVACFLAGS_COMMON) $(OTHER_JAVACFLAGS) JAVAC_CMD = $(JAVAC) $(JIT_OPTION) $(JAVACFLAGS) $(LANGUAGE_VERSION) $(CLASS_VERSION) 在debug build里才有-g。 |
|
xgj1988
2011-04-26
你们的回答很精彩。我先一一说明一下:
1:我刚才根据LcyFenix给的图。逐步关闭上面的复选框,然后在调试确实有问题。而且如果把add line number attributes to generated class files 关闭之后,就不能下断点了(并不是不能调试,因为调试不仅仅包括下短点,个人理解根据JPDA的定义来看说的话。),所以我们的调试不会运行。 2:我把add variable attributes to generated class file 关闭之后,可以调试源代码,但是出现a can't be resolved ,注意,这里可能是我在最开始就没表述清楚,我这里说的不can't be resolved是我在eclipse里面用watch和inspect试图的时候就会can't be resolved ,但是在variables里面会显示出他的值,但是这样又有一个新问题。也就是a,b,c变量名变成了arg0,arg1,arg2这样的形式。所以可能IcyFenix也没太懂我的意思。 例子用的是IcyFenix的 public class A { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class B { public static void foo(int a, String b, Object c) { System.out.println(a + b + c); } } public class T { public static void main(String[] args) { A.foo(1, "2", new Object()); B.foo(1, "2", new Object()); } } 所以问题就是: 1:为什么variable下面可以看到a,b,c的信息,但是在watch和inspect就不行了? 2:就是RednaxelaFX给的最后的东西不太明白是什么。哈哈 引用 j2se/make/common/Defs.gmk
Makefile代码 # Any debug build should include all debug info inside the classfiles ifeq ($(VARIANT), DBG) DEBUG_CLASSFILES = true endif ifeq ($(DEBUG_CLASSFILES),true) JAVACFLAGS_COMMON += -g endif JAVACFLAGS = $(JAVACFLAGS_COMMON) $(OTHER_JAVACFLAGS) JAVAC_CMD = $(JAVAC) $(JIT_OPTION) $(JAVACFLAGS) $(LANGUAGE_VERSION) $(CLASS_VERSION) 在debug build里才有-g。 |
相关讨论
相关资源推荐
- 误操作导致debug状态下没有变量值,debug状态下代码后面不显示变量值
- clion在调试时在代码处自动显示变量值
- keil debug如何在watch直接修改变量值_KEIL 调试经验总结
- eclipse打断点调试进入到class文件中,不显示变量值的解决办法汇总
- Visual Studio在Release模式下开启debug调试,编译器提示变量已被优化掉,因而不可用
- Delphi在调试的时候查看变量的值
- Pycharm debug时变量值显示不出或显示不完全
- eclipse在debug模式下鼠标移动到变量上不显示值的问题
- 为什么要学习C++软件调试技术?掌握调试技术都有哪些好处?
- VS2019调试查看变量_你很可能需要知道这个调试小技巧