`
Hunk_Gou
  • 浏览: 2850 次
社区版块
存档分类
最新评论

关于debug出现unknown source的原理和解决

 
阅读更多
      最近发现在开发调试的时候,突然发现自己的log中出现unknown source,后来发现以前测试都是用eclipse的自带工具编译的,现在改成用ANT来build就没有。去网上找了一下资料,原来是javac引起的。
      因为当通过javac编译时,默认相当于指定-g:source,lines,这样编译出来的class文件中会包含源代码和行号信息;而通过ant编译时,默认相当于指定-g:none,这样编译出来的class文件会比较小,但是不包含任何调试信息,所以出错的时候就会打印出上面的错误堆栈信息。
      自然想到是修改ANT中的javac的debug的参数。
<javac srcdir="${src.dir}" destdir="${dist.classes.dir}" classpathref="compile.classpath" debug="true" debuglevel="lines,vars,source"/>
不过还是不行,打印出来的log还是有unknown source的问题。后来仔细去看了一下build下的class的中的class,发现并没有重新编译,把里面的class删除重新编译一次,run ok!!!

      下面是看到一个关于unknown source出现的原理,在网上看到的http://www.blogjava.net/landon/archive/2011/02/27/345265.html
引用

Unknown Source,顾名思义,就是未知的源文件。因为我们最终解释运行的是class文件,所以出现这个问题的原因很简单,就是class文件中没有源文件的相关调试信息。那为什么class文件会没有调试信息呢?答案更简单,当然是我们在用javac命令进行编译的时候没有指定调试信息呗。因为现在很多人都习惯用eclipse等一些现成的ide进行编写代码,所以很少人熟悉jdk自己的javac,java,jdb等一些命令的详细参数(jdk的一些命令和eclipse自带的一些命令可能不同)。哈哈,不过如果你经常在linux下玩java的话,命令肯定会非常熟悉。那么让我们看看javac的一些重要参数:
    -g-Generate all debugging information, including local variables. By default, only line number and source file information is generated.在class文件中生成所有调试信息,包括局部变量的信息。默认的话,只写入源码的行号和源文件信息。
    -g:none-Do not generate any debugging information.不生成任何调试信息。
    -g:(lines,vars,source)-只生成部分调试信息(源码行号,变量,源文件信息)。那我们在分别介绍下lines,vars,source的含义。
         lines:将源文件中的行号信息写到Class文件中,此属性用于在Class文件中生成方法字节码流偏移量和源代码行号之间的映射关系。如果我们不指定此属性的话,我们将在堆栈异常信息中看不到打印的行号。
         vars:Local variable属性建立了方法的栈帧中局部变量部分内容与源代码中局部变量名称和描述符之间的映射关系。有了这个属性,调试时,我们才可以看到变量的值。
         source:编译时指定了这个属性,会把源文件的属性信息如源文件名称写入class文件。
     说了这么多,初学者可能会迷糊,为什么编译要指定这些调试信息呢?哈哈,如果编译不指定这些调试信息的话,你怎么调试呢?如果你不指定行号信息的话,你在ide中都无法插入断点。这些调试信息在我们调试程序的时候非常重要。不过这些编译选项通常在ide中如eclipse中早已默认了。有的人可能还不相信,打开eclipse,依次打开菜单选项:Window->Preferences->Java->Compiler,可以看到页面的下方有一个Classfile Generation,默认是四个选项都选的。
    那这个Unknown Source到底是编译的时候没有指定哪一项呢?经过测试,我发现是javac编译的时候没有没有指定source选项,必定出Unknown Source这个问题。
     PS1:linux下,很多人用ant进行javac任务编译,查看堆栈异常时也经常会遇到Unknown Source的问题。ant编译时,默认相当于指定-g:none,及不生成任何调试信息的。所以如果要看到日志分析中的源码和行号信息时,要更改build.xml中的dubug属性。
    PS2:我觉得看看Log4j的日志操作类源码包会对这个理解更有帮助。

    B.刚开始的代码引子中,为什么自己写的代码会有堆栈异常的代码行数显示,而jdk的类库(rt.jar-Runtime Java Archive)代码会出现Unknown Source?
    答案很简单,因为我们直接用的是jdk直接编译好的class文件。而rt.jar源码编译打包的时候,是没有将调试信息放入class文件的。所以才会显示Unknown Source。其实,道理很简单,sun的类库正常的情况下肯定不会有bug的,之前肯定都是调试过很多遍的,所以没有必要再加入调试信息,你只负责用就行了。所以,出现Unknown Source很正常。
     PS:其实,我觉得这和软件的开发版本差不多。版本一般都有dubug版本和release版本。debug版本就是包含调试信息的。不过正式发行后,肯定不包含调试信息的。因为如果包含调试信息的话,可能版本占用空间会很大,而且根本就无需调试信息。

    C.如果我们非要对jdk的类库如rt.jar进行跟踪调试怎么办?
     因为rt.jar编译打包的时候,是不包含调试信息的。如果你只是想看看调用的过程,你只需要在eclipse中rt.jar下的Source attachment指定jdk安装目录的src.zip即可。不过如果你想跟踪jdk类库的变量值的时候,这样就不行了。除非,只有一种办法,你重新编译一下src.zip,指定好编译参数,然后用新编译好的rt.jar覆盖掉原来的rt.jar。这样就完全ok了。

    D.如果我们想debug其他没有源代码的class文件呢?
     其实,也不难,利用jad等反编译工具编译出源码后,在进行调试。不过前提是该class文件有调试信息。

     PS:在网上看到了一些打印堆栈异常信息的代码,发现有的竟然打印出了jdk源码的所在行数。如
at java.lang.Thread.dumpStack(Thread.java:1206)等。我觉得很好奇,原因可能是重新编译了jdk的源码或者可能用的不同的ide或者不同版本的jdk吧。这个尚需考证。如果有懂的童鞋,可以和我交流。
分享到:
评论

相关推荐

    可视化vtk中jawt.dll错误解决方案

    ### 可视化vtk中jawt.dll错误解决方案 #### 一、问题背景 在使用VTK(Visualization Toolkit)进行三维图形处理与可视...通过以上资料的学习和实践,可以帮助开发者更好地理解和解决在实际项目中遇到的各种技术难题。

    c-log-master.zip_OPENSOURCE_open_

    1. 日志级别:c-log-master通常支持多个日志级别,如DEBUG、INFO、WARN、ERROR和FATAL等,开发者可以根据需要设置不同的日志输出级别,以过滤不必要或过于详尽的信息。 2. 日志格式化:库提供灵活的格式化选项,...

    编译好的OpenCV3.4.2+Visual Studio2013 contrib+opencv_world版及属性表配置

    Location (extra): D:/software/OpenCV/SourceCode/opencv_contrib-3.4.2/modules Version control (extra): unknown Platform: Timestamp: 2019-04-9 Host: Windows 10.0.16299 AMD64 CMake: 3.12.1 CMake ...

    C++常见错误汇总

    C++常见错误汇总 C++是当前最流行的编程语言之一,但是初学者在学习C++时经常会遇到一些常见错误。本文档汇集了这些常见错误,并提供了解决方法。...了解这些错误的原因和解决方法,可以帮助初学者更好地学习C++。

    Eclipse中常见图标说明

    Eclipse是一款广泛使用的集成开发环境(IDE),尤其在Java...通过了解这些图标,开发者可以在Eclipse环境中更有效地导航、理解和解决问题,提高开发效率。在实际工作中,熟悉这些图标是每个Eclipse用户必备的基础知识。

    使用JPDA进行Java程序远程调试

    总之,使用JPDA进行Java程序的远程调试能够帮助开发者高效地定位和解决问题,无论应用程序运行在哪里,只要配置得当,都能实现远程调试。通过熟练掌握这一技术,可以显著提升开发效率并优化代码质量。

    acpi控制笔记本风扇转速

    Disassembler - fix for error emitted for unknown type for target of scope operator. Now, ignore it and continue. Disassembly of an FADT now verifies the input FADT and reports any errors found. Fix ...

    MyEclipse小图标的含义[参照].pdf

    - **Javadoc Location, Source Attachment, Native Library Location, Output Folder**:分别对应Java文档位置、源代码附件、本地库位置和输出目录。 10. **Code Assist**: - **HTML Tag, Javadoc Tag**:在代码...

    Eclipse图标意义

    * unknown object:未知对象。 Object Adornments Object Adornments图标是Objects图标的修饰,它们用来描述对象的状态或属性。Object Adornments图标有多种形式,每种形式都有其特定的含义: * this Java ...

    编译好的OpenCV3.4.2+Visual Studio2013 contrib版及属性表配置

    Location (extra): D:/software/OpenCV/SourceCode/opencv_contrib-3.4.2/modules Version control (extra): unknown Platform: Timestamp: 2019-04-9 Host: Windows 10.0.16299 AMD64 CMake: 3.12.1 CMake ...

    Android11 静默安装客户端

    使用`adb install -r &lt;apk_path&gt;`命令可以尝试静默安装,但Android 11会提示用户确认安装,除非你使用特定的开发者选项(如`adb shell pm install --force-unknown-source`),但这并不适用于所有设备。 3. **企业...

    Cisco无线AP配置方法

    bridge-group 1 block-unknown-source no bridge-group 1 source-learning no bridge-group 1 unicast-flooding bridge-group 1 spanning-disabled ! interface FastEthernet0 no ip address no ip route-cache ...

    apktool documentation

    In addition to XMLs, resources such as 9 patch images, layouts, strings and much more are correctly decoded to source form. Decoding The decode option on Apktool can be invoked either from d or ...

    c++开源项目标配cmake

    ### C++ 开源项目标配 CMake 的核心知识点详解 ...无论是设置项目的基本属性,还是管理源文件、编译选项、链接库等,CMake 都提供了非常全面且灵活的解决方案。对于 C++ 开发者来说,熟练掌握这些指令是非常重要的。

    eac3to V3.17

    * fixed: CA (Conditional Access) tracks were shown as "Unknown audio track" v3.03 * fixed: MPEG2 1088 to 1080 cropping was still incomplete v3.02 * fixed: VC-1 stream handling was broken * fixed: ...

    CMake用法详解 使用方法说明

    - CMAKE_SOURCE_DIR:表示源码的顶级目录。 - CMAKE_INSTALL_PREFIX:定义项目安装路径的前缀。 - EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH:分别表示可执行文件和库文件的输出路径。 6. 一次配置多次构建 ...

    ap6212a0_a33_sc3817r_服务器验证通过_bt已经通了_wifi需要修改配置_需要再次验证_20170626_1549.7z

    debug.hwui.render_dirty_regions=false #ro.sys.storage_type = emulated \ #for gms #PRODUCT_PROPERTY_OVERRIDES += \ # ro.sys.mutedrm=true \ # ro.adb.secure=1 PRODUCT_PROPERTY_OVERRIDES += \ ro.sf....

    gdb命令速查1

    GDB(GNU Debugger)是Linux环境下用于调试C、C++等程序的强大工具。...了解并熟练使用这些GDB命令和技巧,能显著提高你的调试效率,更好地理解程序的运行状态,解决复杂问题。记得在实际操作中不断练习,以加深记忆。

    uboott移植实验手册及技术文档

    198 cmp r0, r2 /* until source end addreee [r2] */ 199 ble copy_loop 200 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 201 #endif #ifdef CONFIG_S3C2410_NAND_BOOT @ reset NAND mov r1, #NAND_CTL_BASE ...

Global site tag (gtag.js) - Google Analytics