Unknown Source的出现及解决

1. Unknown Source的出现背景

昨天在公司写了一段代码,很简单,就是测试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这个头痛的问题。那么这个东西到底如何而来?
 

2. 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的日志操作类源码包会对这个理解更有帮助。

3. 为什么自己写的代码显示代码行数,而JDK类库显示Unknown Source

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

4. 如果我们非要对jdk的类库如rt.jar进行跟踪调试怎么办?

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


5. 如果我们想debug其他没有源代码的class文件呢?

 其实,也不难,利用jad等反编译工具编译出源码后,在进行调试。不过前提是该class文件有调试信息。
PS:在网上看到了一些打印堆栈异常信息的代码,发现有的竟然打印出了jdk源码的所在行数。如
at java.lang.Thread.dumpStack(Thread.java:1206)等。我觉得很好奇,原因可能是重新编译了jdk的源码或者可能用的不同的ide或者不同版本的jdk吧。这个尚需考证。如果有懂的童鞋,可以和我交流

java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) select * from usertable where UserName='汪汪队'and Password='1012' Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at DBConn.DataBaseManager.getResult(DataBaseManager.java:31) at Forms.UserLogin.actionPerformed(UserLogin.java:76) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$500(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)这个报错怎么解决
06-09
<think>好的,我现在需要解决用户在Maven安装过程中遇到的UnsupportedClassVersionError问题,具体是版本52.0,这涉及到Java版本不兼容。首先,我得回忆一下这个错误通常是什么原因引起的。根据引用[2],这通常是因为编译时使用的Java版本高于运行时环境。版本52.0对应的是Java 8,所以如果出现这个错误,说明用户可能在用低于Java 8的版本来运行编译后的类文件。 接下来,我需要考虑用户的具体情况。用户是在Maven安装过程中遇到这个问题,可能是Maven构建时使用的Java版本和项目所需的版本不一致。可能的解决方案包括检查并统一Java版本,或者调整Maven的配置来指定正确的Java版本。 首先,用户需要确认当前系统中安装的Java版本。可以通过命令行输入java -version和javac -version来查看运行时和编译时的版本。如果两者不一致,或者低于Java 8,就需要升级到Java 8或更高版本。 然后,检查Maven的配置,确保它使用了正确的Java版本。有时候即使系统安装了新版本,Maven可能仍然指向旧的JAVA_HOME。需要检查环境变量JAVA_HOME是否指向正确的JDK路径。此外,Maven的配置文件settings.xml里是否有指定特定的JDK版本?或者,在项目的pom.xml中,是否配置了maven-compiler-plugin来指定source和target的Java版本?如果没有,用户需要添加相应的配置,强制Maven使用正确的版本进行编译。 另外,引用[4]中提到修改配置文件中的jvm参数,可能用户还需要检查Maven运行时的JVM参数是否合适,但这种情况相对少见,主要还是版本匹配的问题。 用户可能遇到的问题还有,比如在IDE中(如Eclipse)配置了不同的JRE,导致Maven构建时使用了IDE设置的Java版本,而不是系统环境变量中的。这时候需要检查IDE中的Java编译设置,确保和项目要求的版本一致。引用[3]提到导入Maven项目到Eclipse时出现的错误,可能与项目配置和IDE设置有关,所以用户需要确认IDE中的JDK配置是否正确。 总结下来,解决方案的步骤应该是: 1. 检查并统一Java环境版本,确保至少Java 8。 2. 配置Maven使用正确的JDK版本,通过环境变量或pom.xml中的插件设置。 3. 验证IDE(如果使用的话)中的Java配置是否一致。 可能还需要指导用户如何修改pom.xml中的maven-compiler-plugin,添加类似以下配置: ```xml <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> ``` 这样即使系统中有更高版本的JDK,Maven也会用指定的版本编译,避免版本不匹配的问题。 同时,提醒用户在修改配置后,执行mvn clean install重新构建项目,看是否问题解决。如果用户的环境变量设置有问题,可能需要重新启动命令行或IDE使新配置生效。 此外,如果用户有多个JDK版本,可能需要使用工具如Jenv或手动切换JAVA_HOME来管理不同项目的JDK版本,避免混淆。 最后,需要确保所有相关工具(如Maven、IDE)都指向同一版本的JDK,这样才能彻底解决版本冲突的问题。</think>要解决Maven安装过程中因Java版本不兼容导致的`UnsupportedClassVersionError`(错误代码52.0),需通过以下步骤调整环境配置和项目设置: --- ### 一、问题根源分析 错误信息`Unsupported major.minor version 52.0`表示:**.class文件是使用Java 8(版本号52)编译的,但当前运行时环境使用低于Java 8的版本** [^2]。常见场景包括: 1. 系统安装的JDK版本低于Java 8 2. Maven未正确配置编译版本 3. IDE(如Eclipse)中JDK路径指向旧版本 --- ### 二、解决方案 #### 步骤1:统一Java版本 1. **检查当前Java版本**: ```bash java -version # 查看运行时版本 javac -version # 查看编译时版本 ``` 若输出显示版本低于1.8(如1.7或更低),需升级到Java 8或更高。 2. **设置环境变量**: - 修改`JAVA_HOME`指向Java 8的安装路径(例如:`C:\Program Files\Java\jdk1.8.0_291`) - 将`%JAVA_HOME%\bin`添加到系统`PATH`变量中 - 重启命令行或IDE以生效 #### 步骤2:配置Maven编译版本 在项目根目录的`pom.xml`中添加`maven-compiler-plugin`插件配置: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <!-- 指定源码兼容版本 --> <target>1.8</target> <!-- 指定生成的.class文件版本 --> </configuration> </plugin> </plugins> </build> ``` #### 步骤3:验证IDE配置 如果使用Eclipse或IntelliJ: 1. **检查默认JDK**: - Eclipse:`Window > Preferences > Java > Installed JREs` - IntelliJ:`File > Project Structure > SDKs` - 确保选中Java 8或更高版本 2. **更新Maven项目**: 在IDE中执行`Maven Update Project`(Eclipse右键项目 > Maven > Update Project) --- ### 三、扩展优化 - **多版本JDK管理**:使用工具如`jenv`(Mac/Linux)或手动切换`JAVA_HOME`管理多版本。 - **构建命令指定版本**:临时指定版本编译: ```bash mvn clean install -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8 ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值