zoukankan      html  css  js  c++  java
  • NoClassDefFoundError vs ClassNotFoundException

    我们先来认识一下Error 和Exception, 两个都是Throwable类的直接子类。  Javadoc 很好的说明了Error类: 

    An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.

    抛出Error时,程序就是出现了严重的错误,程序会立即终止运行。我们来看一下Error的一些子类和它们在javadoc中的说明:

    1. AnnotationFormatError - Thrown when the annotation parser attempts to read an annotation from a class file and determines that the annotation is malformed.
    2. AssertionError - Thrown to indicate that an assertion has failed.
    3. LinkageError - Subclasses of LinkageError indicate that a class has some dependency on another class; however, the latter class has incompatibly changed after the compilation of the former class.
    4. VirtualMachineError - Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating.

    Throwable的子类 主要分三种类别

    1. Error -  一些严重问题导致的,大多数程序此时应该crash 而不是试图去handle的错误
    2. Unchecked Exception (aka RuntimeException) - 经常出现的编程错误比如 NullPointerException 或者非法参数. 这个Throwable类别中,程序有时可以处理该种错误 或者 从中恢复-- 或者 至少可以catch Thread的run方法,记录相应日志,并继续执行。
    3. Checked Exception (aka Everything else) -  应用程序应当能够catch这里异常,并做一些有意义的事情。

    有了上述基本认识以后,我们回到正题~

    在辨析两者的不同前,让我们先看看两者有什么相同点:

    1. 两者都是运行时错误,都是找不到某一个类
    2. 两者都跟java classpath有关

    现在看看有什么不同:

    1. ClassNotFoundException 是在运行时由于调用 Class.forName() or ClassLoader.loadClass() or ClassLoader.findSystemClass()而找不到相应的类引起的。 NoClassDefFoundError 是由于相应的类在编译时出现,并使应用通过了编译和链接,而在运行时无法使用造成的。简单来说,前者是因为显式加载相应类失败造成的,后者是因为调用某类的方法或访问某类的域,隐式加载类失败造成的。
    2. ClassNotFoundException 是java.lang.Exception的子类,必须在源码中提供明确的处理方式(再次throw 或者 catch)。而NoClassDefFoundError 是继承自java.lang.LinkageError的Error子类。
    3. 如果你在java中用了两个ClassLoader,那么当一个ClassLoader试图去访问另一个ClassLoader加载的类时,jvm会抛出ClassNotFoundException。

     可能造成 NoClassDefFoundError 的原因有很多:

    1. 最常见的就是Class 在java classpath 中找不到。(可以通过打印字符串System.getProperty("java.class.path")来查看当前jvm使用的classpath)
    2. 你可能使用的是jar命令在运行程序,而class在manifest文件的Class Path 属性中没定义
    3. 启动脚本override了环境变量ClassPath
    4. 也可能是一个类依赖的native library不可用

    举个我自己的栗子: 

    #!/bin/bash
    
    BIN_DIR=../MatchSnapshots/bin
    
    export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 
    
    export PATH=$JAVA_HOME/bin:$PATH
    
    java  -cp $BIN_DIR:$JAVA_HOME/lib/tools.jar 
        edu.umd.MatchSnapshots.Main 
        some other options

    源码是使用了com.sun.tools.hat.internal.parser.Reader类,在Eclipse中buildpath里添加了tools.jar以后编译通过并可以运行。在command line下,却抛出了NoClassDefFoundError,使用-cp选项添加了tools.jar就没这个问题了。

    参考文章:

    Difference between ClassNotFoundException vs NoClassDefFoundError in Java
    How to resolve java.lang.ClassNotFoundException in Java

    Differences betweeen Exception and Error

  • 相关阅读:
    第四次实践作业
    第三次实践作业
    第二次实践作业
    第一次实践作业
    第02组 Beta版本演示
    第02组 Beta冲刺(4/4)
    大数据应用技术课程实践--选题与实践方案
    15 手写数字识别-小数据集
    14 深度学习-卷积
    13 垃圾邮件分类2
  • 原文地址:https://www.cnblogs.com/ridox/p/3624309.html
Copyright © 2011-2022 走看看