转自:http://www.iteye.com/topic/679030
引子
先说一下为什么写这一篇小文章,最近不少同事是在问一个问题,为什么Ant编译出的代码在日志里的出错异常栈看不到行号信息,每次如果在定位问题,都需要用eclipse重新将相应的jar包编译一下,再放到问题环境上重现一下,这样再看日志才可以。而且使用ant生成的包就算是远程调试也不可用,断点总是打不上。
一般的开发都会有一套持续集成的环境,用作每日构建,用ant或是其他工具,开发人员一般用Eclipse或其他的IDE做开发,所以经常会遇见上面的问题。
原因
ant的javac任务里有对debug信息输出的设置,不过默认是不输出。
javac中设置调试信息级别的选项为-g,其详细含义如下,英文太简单,偶会详细介绍一下:
-gGenerate all debugging information, including local variables. By default, only line number and source file information is generated.在Class文件中生成所有调试信息。也就是将会包含下面介绍的3类调试信息的所有。
-g:noneDo not generate any debugging information.Class文件中不包含任何调试信息,这个是Ant在编译时默认使用的。
-g:{keyword list}Generate only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are: sourceSource file debugging informationClass文件中固定长度的SourceFile属性,编译时如果选择了生成此属性,则会将它写到Class文件中。它用来提供产生Class文件的源文件名称。如果不生成此属性,那么在调试时就会提示“Source not found.”。
有图有真像,我们用Eclipse来演示一下此调试开关的作用,帮助大家理解。先设置一下eclipse编译时的选项,关闭Source file属性开关,编译选项的修改只针对此测试用的工程,所以在我们测试的工程右键->properties,在弹出的对话框中,按下图进行选择:图1(给这个图命个名,后面还会用到) 上图中,1处表示单独调整本工程的编译选项,2处的最后一行则是是否生成Source file调试信息的开关,这里我们按上图去选中,则生成Class文件中不会有源文件的名称。下一步,在Eclipse对应的工程中建立一个简单的Main.java用于测试,可以看出在Main.java文件中,我们还有另一个类Test,对于Test类来说,如果在生成Test.class文件没有Source file属性,那调试器就无法知道Test.class实际是对应的源文件是Main.java,那么我们把断点打在Test类的sayHello方法的第一行,调试时会发生什么?
- public class Main {
- public static void main(String[] args) {
- Test t = new Test();
- t.sayHello();
- }
- }
- class Test
- {
- public Test() {
- }
- public void sayHello()
- {
- <span style="color: #ff0000;">int a = 10; // 断点将打在此行</span>
- int b = a++;
- System.out.println("b:" + b);
- String hello = "Test say";
- hello += " hello";
- System.out.println(hello);
- }
- }
好了,我们在Eclipse中启动调试Main.java,你将会得到下图中的信息:是的,找不到源文件。现在你应该已经理解这个调试选项的含义了。
linesLine number debugging information将源文件中的行号信息写到Class文件中,此属性用于在Class文件中生成方法字节码流偏移量和源代码行号之间的映射关系。就像我们引子中所看到的,打印出的异常栈中看不到行号,就是因为生成Class中没有此属性导致,而远程调试时打不上断点也是这个原因。同样的,我们在Eclipse中测试此调试选项的含义,其设置位置跟Source file属性在同一个界面,也在我们图1中设置,图1位置2的第2行,就是此选项,去选中此项,其他选项均选中,重新编译。还是用上面的Main.java来调试,看一下,会出现什么。是的,出错了,断点无法插入成功,提示信息也很明确,让我们修改编译选项以便生成调试信息。 varsLocal variable debugging informationLocal variable属性建立了方法的栈帧中局部变量部分内容与源代码中局部变量名称和描述符之间的映射关系。简单一点说,如果没有此属性的信息,那我们在调试时将无法看到变量值。我们还是在Eclipse中去掉此编译选项,不要我讲,你应该已经知道在哪里了,还是图1中的位置2,第一行就是此属性的开关,同样去选而打开其他编译开关,重新编译。再来调试一下我们的Main.java,想通过“Watch”,“Inspect”查看变量b的值,或是hello的值,你将会得到如下信息: “b cannot be resolved”或是“hello cannot be resolved”。是呀无法被解析,因为无法找到栈帧中的变量与源码中变量名之间的对应关系,无法将此运行时的信息和我们代码关联引来。
以上javac选项英文描述出自:javac - Java programming language compiler,本文只关注调试信息相关选项,其他可自行参考。
OK,算是介绍完了,相信大家对这几个参数的含义应该也理解了。
另外在最后想说一下:Eclipse编译使用编译器并不是jdk自带的javac,而是Eclipse JDT自己的编译器。虽然本文的演示是用的Eclipse,但对于javac生成类文件时的调试信息选项的含义和用法也是一样的,Eclipse的JDT编译器和javac是兼容的。
如果想了解Eclipes的JDT编译器和javac编译器的不同可以参考以下文档:
这里介绍了一个小例子,说明这两个编译器间的差别。
Java Compiler - Eclipse compiler vs. Sun compiler
这个是Eclipse的帮助里的东东,介绍Eclipse的JDT编译器的使用,(当然你可以通过本地Eclipse的帮助查看)
http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm
这里面的编译方法偶在本地试过了,很好用,你也可以试式用JDT的编译器编译个文件试一试。Eclipse 3.5的示例用法如下:
D:\Program Files\eclipse\plugins>java -jar org.eclipse.jdt.core_3.5.2.v_981_R35x.jar -d F:\Study\eclipsepro\Study\src\eclipse -g F:\Study\eclipsepro\Study\src\*.java
还有一个参考资料就是《深入java虚拟机》,纸件的,没法贴链接了。嘿嘿
相关推荐
python库。 资源全名:javac-parser-0.1.0.tar.gz
java运行依赖jar包
java jar包,亲测试可用 安全,可以对其进行数字签名,只让能够识别数字签名的用户使用里面的东西。 加快下载速度; 压缩,使文件变小,与ZIP压缩机制完全相同。 包封装。能够让JAR包里面的文件依赖于统一版本的...
分析如下:Ant的debug和debuglevel参数会去调用JDK的javac -g参数, 而-g参数又包含3个选项, -g:{lines,vars,source},分别代表编译时向字节码中写入行号、方法局部变量信息、关联源代码信息。 这里主要说说-g:var...
javac-source-code-reading:javac源码调试
javac源码系列。。。。。。。。。。。。。。。。。。。。。。。。。。。
javac-jdk.rar
javac-shaded-9+181-r4173-1.pom maven访问不了,将其下载后打入本地包即可使用
java原始路径lein-javac-resources Leiningen插件可用于:java-source-paths资源文件。 该插件旨在用于具有遗留Java代码库的项目,其中资源文件与Java源文件一起放置。 用法 将插件包括在project.clj的:plugins矢量中...
java jar包,亲测试可用 安全,可以对其进行数字签名,只让能够识别数字签名的用户使用里面的东西。 加快下载速度; 压缩,使文件变小,与ZIP压缩机制完全相同。 包封装。能够让JAR包里面的文件依赖于统一版本的...
Java毕业设计源码-基于JavajavaC语言试题生成与考试系统(源代码)(IT计算机专业Java源代码资料).zipJava毕业设计源码-基于JavajavaC语言试题生成与考试系统(源代码)(IT计算机专业Java源代码资料).zipJava毕业设计...
功能-javac 一个Javac插件,用于提取要插入机器学习模型的... javac -cp extractor/target/features-javac-extractor-1.0.0-SNAPSHOT-jar-with-dependencies.jar -Xplugin:FeaturePlugin T.java 步骤4:生成.dot文件
NULL 博文链接:https://qn-lf.iteye.com/blog/990975
当我们编辑了一个Java源文件保存时,是以操作系统默认的字符编码保存的(Windows xp默认字符集是GBK)。这篇文章主要介绍了javac -encoding 用法详解,非常具有实用价值。
java编译的javac.jar
java运行依赖jar包
java运行依赖jar包
periodic-jobs.zip,周期性作业的简单调度程序。需要spring。周期性作业的简单计划程序
2) 调试编译方式:javac -g A.java 3) 代码编译方式:javac -g:none A.java 案例如下:类A public class A{ public static void main(String args[]){ for(int i=0;i<100000;...