打jar包 java.lang.NoClassDefFoundError和java.lang.UnsupportedClassVersionError
jar打包遇到的java.lang.NoClassDefFoundError和java.lang.UnsupportedClassVersionError错误2008-11-26 11:52 用java做抓取rss的工具时,遇到两个小小的麻烦,不过最终都还算顺利地解决了,在这里记录下来,希望对遇到同样问题的朋友有所帮助。
一、java.lang.NoClassDefFoundError错误
在eclipse里边用export将java工程导出为jar文件后,刚开始的时候我直接双击jar文件,出现的错误提示是:Could not find the main class.Program will exit.出现这样的错误是我始料未及的,因为以前也用export打包过jar文件,而且我也选定了程序的main class,为什么还会出现找不到main class的错误呢?到处问询,也基本上就是教导如何设定main class的,对我的这种情况根本没有帮助,不过还是从搜索的资料中知道有manifest文件这回事。
其实,正确运行jar文件还是需要在命令行中操作,在命令行下更能看到详细的错误情况所在。jar文件运行的正确命令行格式为:java -jar jarname.jar。具体到我的这个程序,命令行下的情况如下:
C:\Documents and Settings\Administrator\桌面>java -jar rssfetcher.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPul
lParserException
Caused by: java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserExcepti
on
at .URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at .URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
这样一看,错误很明显了,是java.lang.NoClassDefFoundError类型的错误,而且是由于没有找到org.xmlpull.v1.XmlPullParserExcepti
on这个class。这样问题的原因就一下子浮出水面了,原来是这个java工程里边所依赖的几个包在打包时没有同时导出的缘故造成这样的错误。最后,经过一番查证,终于将问题得到了圆满的解决。方案就是:
1、自己写一个manifest.mf文件,将需要的包加进去。基本格式如下:
Manifest-Version: 1.0
Main-Class: RssFetcher
Class-Path: mysql-connector-java-5.0.8-bin.jar xpp3_min-1.1.4c.jar
2、export的最后一步,选择“use existing manifest from workspace”,然后选择自己所写的manifest.mf文件的位置,点击“finish"。
3、这样生成的jar还是会有错误,因为eclipse并没有把程序所依赖的包自动导出,我们需要自己把mysql-connector-java-5.0.8-bin.jar、xpp3_min-1.1.4c.jar这两个包放到和jar程序包同样的文件夹中,然后再用命令行运行该jar,就会发现一切都变得正常了。
二、java.lang.UnsupportedClassVersionError错误
好了,在本地测试jar包成功,然后就是上传到服务器上运行了。不过,在这个时候,又发现了新的问题,shell的时候报错了:
[comdeng]$ java -jar rssfetcher.jar
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at .URLClassLoader.defineClass(URLClassLoader.java:260)
at .URLClassLoader.access$100(URLClassLoader.java:56)
at .URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at .URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
看来是jre的版本问题了,用"java -version"查看一下,发现服务器上jre的版本还停留在1.5.0_02,而我本地的环境已经是1.6..0_07。那么怎么解决版本兼容性的问题呢?很明显,一种就是更新服务器上的java版本,另一个就是降低本地的java版本。服务器上还运行着其他的一些java程序,更新java版本的话怕会带来兼容性的问题,所以,降低本地java版本的做法更加安全。
刚开始我想到的是,在java工程里的Build Path里边把依赖的JRE System Library包换成jre1.5.0的版本,这个可以从http://java.sun.com/products/archive/页面找到。具体修改java工程所以来的jre版本的步骤如下:
1、打开Configure Build Path面板,选择Libraries的选项卡,删除掉原来的jre1.6.0的library。
2、点击”Add Library“,选择“JRE System Library”,点击“Next”,这时候可以看到Workspace Default JRE为1.6的版本,我们需要手动来选择JRE版本。
3、选择“Alternate JRE”,发现可选的只有jre1.6的版本,点击“Installed JREs”,进入到对应的面板,点击“Add”按钮,进入到“Add JRE”的面板,添上jre版本名称,选择jre的路径,“ok”即可。
、再次“ok”,回到“Add Library”的面板,下拉框里边就能选择刚才添加的jre版本了。
java工程依赖的jre版本调到低版本了。不过千万不要以为这样就算把事情解决了,重新export,重新上传到服务器,重新运行,发现提示依然如故,还是存在版本的问题。
原来,我们仅仅改变了jar运行时依赖的jre库的版本问题,但是生成java class的时候所用的环境还是6.0的,所以,我们需要改变java编译器的版本。所以进入到第5部。
5、进入java工程的properties页面,选择“Java Compiler”,会发现默认所用的编译器还是6.0的,我们需要将其改到5.0。勾上“Enable project specific settings”,这样我们对编译器所做的更改就只会应用到当前工程,然后将“Compiler compliance level”调整为5.0,保存设置即可。
通过这样的设置,我们再重新export这个工程,就可以在java 1.5的版本的机器上正确运行了。
















