解决java.lang.NoClassDefFoundError和java.lang.ClasssNotFoundException

              当看到报这个错误的时候,直接就会想到是jar的错误,要不就是引用的版本不正确,要不就是多个jar冲突,要不然就是没有放到运行环境,总之,围绕着jar去解决就对了……

              小编还是执着的调用着各大运营商的接口,以及各种像我们这样的第三方开发平台的接口,有些流量并不是很便宜,但是,既然接口来了,那就调吧……


错误一枚

   

           最近在调用一个网宿科技的接口,用的是httpclient。自己写了一个main程序,在本类中是可以通的,但是正是使用的时候,要实例化这个类就报了上面的错误。

          其实当时并没有特别的担心,因为总感觉是可以解决的,于是和网宿那边技术交流了一下,之后就自己动手开始解决,还是一句jar没有加载到运营环境提醒了我。问题到这里也就顺利的解决了,就是把缺少的jar放到对应的运营环境classpath中就可以了。其实错误也是在开头的时候说的三种情况逐一去排除的。小编还继续学习了一下……

 


NoClassDefFoundError错误发生的原因

                NoClassDefFoundError错误的发生,是因为Java在虚拟机在编译时能找到合适的类,而在运行时不能找到合适的类导致的错误。例如在运行时我们想调用某个类的方法或者访问这个类的静态成员的时候,发现这个类不可用,此时Java虚拟机就会抛出NoClassDefFoundError错误。与ClassNotFoundException的不同在于,这个错误发生只在运行时需要加载对应的类不成功,而不是编译时发生。

            简单总结就是,NoClassDefFoundError发生在编译时对应的类可用,而运行时在Java的classpath路径中,对应的类不可用导致的错误。

              不造为什么这几个错误是一起出来的,但是也是一起解决的。


NoClassDefFoundError和ClassNotFoundException区别

            不造为什么这几个错误是一起出来的,但是也是一起解决的。也是今天才想起要弄清他们两个的关系。尽管他们都与Java classpath有关,但是他们完全不同。NoClassDefFoundError发生在JVM在动态运行时,根据你提供的类名,在classpath中找到对应的类进行加载,但当它找不到这个类时,就发生了java.lang.NoClassDefFoundError的错误,而ClassNotFoundException是在编译的时候在classpath中找不到对应的类而发生的错误。ClassNotFoundException比NoClassDefFoundError容易解决,是因为在编译时我们就知道错误发生,并且完全是由于环境的问题导致。


怎么解决NoClassDefFoundError错误

           根据前文,很明显NoClassDefFoundError的错误是因为在运行时类加载器在classpath下找不到需要加载的类,所以我们需要把对应的类加载到classpath中,或者检查为什么类在classpath中是不可用的,这个发生可能的原因如下:

  1. 对应的Class在java的classpath中不可用
  2. 你可能用jar命令运行你的程序,但类并没有在jar文件的manifest文件中的classpath属性中定义
  3. 可能程序的启动脚本覆盖了原来的classpath环境变量
  4. 因为NoClassDefFoundError是java.lang.LinkageError的一个子类,所以可能由于程序依赖的原生的类库不可用而导致
  5. 检查日志文件中是否有java.lang.ExceptionInInitializerError这样的错误,NoClassDefFoundError有可能是由于静态初始化失败导致的
  6. 如果你工作在J2EE的环境,有多个不同的类加载器,也可能导致NoClassDefFoundError

 

 

一些补充

              由于NoClassDefFoundError是LinkageError的子类,而LinkageError的错误在依赖其他的类时会发生,所以如果你的程序依赖原生的类库和需要的dll不存在时,有可能出现java.lang.NoClassDefFoundError。这种错误也可能抛出java.lang.UnsatisfiedLinkError:no dll in java.library.path Exception Java这样的异常。解决的办法是把依赖的类库和dll跟你的jar包放在一起。

              如果你使用Ant构建脚本来生成jar文件和manifest文件,要确保Ant脚本获取的是正确的classpath值写入到manifest.mf文件.

             Jar文件的权限问题也可能导致NoClassDefFoundError,如果你的程序运行在像linux这样多用户的操作系统种,你需要把你应用相关的资源文件,如Jar文件,类库文件,配置文件的权限单独分配给程序所属用户组,如果你使用了多个用户不同程序共享的jar包时,很容易出现权限问题。比如其他用户应用所属权限的jar包你的程序没有权限访问,会导致java.lang.NoClassDefFoundError的错误。

              基于XML配置的程序也可能导致NoClassDefFoundError的错误。比如大多数Java的框架像Spring,Struts使用xml配置获取对应的bean信息,如果你输入了错误的名称,程序可能会加载其他错误的类而导致NoClassDefFoundError异常。我们在使用SpringMVC框架或者Apache Struts框架,在部署War文件或者EAR文件时就经常会出现Exception in thread “main”java.lang.NoClassDefFoundError。

 

 

        总结来说,类加载器基于三个机制:委托、可见性和单一性,委托机制是指将加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它。可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。现在假设一个User类在WAR文件和EJB-JAR文件都存在,并且被WARClassLoader加载,而WAR ClassLoader是加载EJB-JAR ClassLoader的子ClassLoader。当EJB-JAR中代码引用这个User类时,加载EJB-JAR所有class的Classloader找不到这个类,因为这个类已经被EJB-JARclassloader的子加载器WARclassloader加载。这会导致的结果就是对User类出现NoClassDefFoundError异常,而如果在两个JAR包中这个User类都存在,如果你使用equals方法比较两个类的对象时,会出现ClassCastException的异常,因为两个不同类加载器加载的类无法进行比较。


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值