`

Unknown Source的出现及解决

    博客分类:
  • J2EE
阅读更多
http://www.2cto.com/kf/201103/84667.html
昨天在公司写了一段代码,很简单,就是测试Thread的dumpStack方法的使用。因为Thread的dumpStack方法不是很常用,但它对于如果想看看谁在运行时调用方法还是非常有帮助的。回到正题,看输出结果:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Unknown Source)
at Common.getInfo(TestDumpStack.java:21)
at TestDumpStack.main(TestDumpStack.java:7)
    大家可以看到在输出的第二行,显示的是at java.lang.Thread.dumpStack(Unknown Source)。为什么自己写的代码就显示出了源码文件的名字及所在行数,而jdk的类库就显示出了Unknown Source?
    相信很多人在调试代码,用log工具打印堆栈异常信息,查看代码所在行的相关调试信息时,经常会遇到Unknown Source这个头痛的问题。那么这个东西到底如何而来?
    A.Unknown Source从哪来?

     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吧。这个尚需考证。
分享到:
评论

相关推荐

    java开发常遇问题和解决

    以下是一些常见的Java开发问题及其解决方案: 1. **内存溢出(Out of Memory)** - 原因:分配给JVM的内存不足,对象创建过多,或者大量数据驻留在堆内存中。 - 解决方案:检查代码中是否有无用的大对象,使用...

    解决XP不能用JDBC不能连接数据库的问题

    at java.sql.DriverManager.getConnection(Unknown Source) at java.sql.DriverManager.getConnection(Unknown Source) ``` 该错误通常出现在尝试建立与数据库服务器之间的套接字连接失败时。这可能是因为驱动程序...

    Android错误解决方法大集合

    如果网络连接正常但仍出现该错误,则需要检查 Manifest 文件的设置。 二、Failed to install *.apk on device 'emulator-5554': timeout 错误 该错误是由于模拟器未关闭或非法关闭所致,解决方法是删除 C:...

    ODI代理找不到驱动

    at oracle.odi.core.datasource.support.DefaultDataSourceManager.createAndConfigureDataSourceProvider(Unknown Source) at oracle.odi.core.datasource.support.DefaultDataSourceManager$1.create(Unknown ...

    Eclipse常见问题及解决方法

    Eclipse常见问题及解决方法 Eclipse是Java开发中最流行的IDE之一,但是在使用过程中总是会遇到一些问题,以下是解决Eclipse常见问题的方法。 1. 如何将建立 Eclipse 的快捷方式? 在桌面单击右键选择新建启动器,...

    android 使用poi读取高版本excel

    android 使用poi读取高版本excel, 解决以下这两个错误 java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/stream/XMLEventFactory; at org.apache.poi.openxml4j.opc.internal.marshallers....

    spket_1.6.18破解补丁

    spket_1.6.18破解补丁,解决在设置默认以spket打开编辑js文件时出现一下错误,且不能智能提示。 An internal error occurred during: "Loading Context". !STACK 0 java.lang.NullPointerException at ...

    echarts-liquidfill.js

    echarts-liquidfill.js文件,做水球图用的,官方的api

    Aspose.Words20210415.rar

    3. **优化的内存管理**:减少在处理损坏文档时可能出现的内存泄漏或性能问题。 4. **修复已知漏洞**:可能修复了导致文档加载失败的安全漏洞。 这个特定的更新对于依赖Aspose.Words的开发者来说至关重要,因为它...

    SuperBackspace宏

    《SuperBackspace宏:解决Source Insight中删除“半个汉字”问题》 在编程的世界里,高效和精确是程序员追求的两大核心目标。Source Insight作为一款备受程序员喜爱的源代码查看和编辑工具,以其强大的语法高亮、...

    解决服务器环境2个PHP版本不统一问题 php -v和phpinfo不同版本.docx

    source /etc/profile ``` 这将使得系统读取新的配置文件。 三、解决PHPWarning: Module SourceGuardian already loaded in Unknown on line 0错误 在执行上述命令后,可能会出现以下错误: ``` ...

    《完美世界国际版》综合架设

    常见问题问答主要涉及到一些常见的问题和解决方法,例如如何解决错误原因、如何解决登录问题等。 客户端补丁制作 客户端补丁制作主要涉及到客户端的修改和补丁制作,例如如何修改客户端、如何制作补丁等。 客户端...

    maven3.6.3资源包

    at org.jetbrains.idea.maven.server.embedder.CustomModelValidator.(Unknown Source) while locating org.jetbrains.idea.maven.server.embedder.CustomModelValidator at ClassRealm[maven.ext, parent: ...

    MySQL数据库导出与导入及常见错误解决.docx

    MySQL数据库的管理和维护是数据库管理员日常工作的重要组成部分,其中包括数据的导出与导入操作。这两个步骤在数据库迁移、备份、恢复和测试环境中尤为关键。...同时,了解并解决可能出现的错误,能有效提高工作效率。

    Keil+C编译器常见警告与错误信息的解决方法[参照].pdf

    19. UNKNOWN CONTROL – 所选的控制参数不认识。 解决方法:检查控制参数是否正确,检查命令行参数是否正确。 通过了解这些常见的警告和错误信息,可以帮助开发者更好地使用Keil+C编译器,提高编译效率和改进编程...

    hadoop.dll

    at java.lang.ProcessBuilder.start(Unknown Source) at org.apache.hadoop.util.Shell.runCommand(Shell.java:482) 2:window10操作系统下面。hadoop-2.6.4版本,解决上面这个问题的必须两个文件。详细见博客:...

Global site tag (gtag.js) - Google Analytics