ClassNotFoundException被神奇地取消选中

时间:2015-11-20 09:44:52

标签: java exception

我的主要工作线程如下所示:

public final class Worker
implements Runnable {

    @Override
    public void run() {
        try {
            _run();
        }
        catch (RuntimeException e) {
            // Cleanup carefully
        }
    }

    private void _run() {
        // do work here
    }
}

想象一下,当Thread.UncaughtExceptionHandler报告未被捕获的java.lang.ClassNotFoundException实例时,我会感到惊讶。

(根本原因是另一个问题:我们在运行时期间在开发环境中覆盖了JAR文件。)

在我的书中,这看起来像Sneaky Throw。为什么这个异常不是RuntimeException?

示例堆栈跟踪(已消毒):

Caused by: java.lang.ClassNotFoundException: xyz
        at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 10 more
Caused by: java.util.zip.ZipException: error reading zip file
        at java.util.zip.ZipFile.read(Native Method)
        at java.util.zip.ZipFile.access$1400(ZipFile.java:61)
        at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:717)
        at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:420)
        at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
        at java.util.jar.Manifest$FastInputStream.fill(Manifest.java:441)
        at java.util.jar.Manifest$FastInputStream.readLine(Manifest.java:375)
        at java.util.jar.Manifest$FastInputStream.readLine(Manifest.java:409)
        at java.util.jar.Attributes.read(Attributes.java:376)
        at java.util.jar.Manifest.read(Manifest.java:199)
        at java.util.jar.Manifest.<init>(Manifest.java:69)
        at java.util.jar.JarFile.getManifestFromReference(JarFile.java:199)
        at java.util.jar.JarFile.getManifest(JarFile.java:180)
        at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:780)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:422)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
        ... 16 more

3 个答案:

答案 0 :(得分:2)

为什么这个异常不是RuntimeException?

这是java.lang.ClassNotFoundException

层次结构
java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.ReflectiveOperationException
     java.lang.ClassNotFoundException

如您所见,它没有以任何方式扩展RuntimeException,具有此层次结构

java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.RuntimeException

如果你想抓住他们两个; catch Exception

如果你想抓住所有人; catch Throwable

finally,如果您想了解有关层次结构继承的更多信息,可以从这里开始:Inheritance - Java doc

答案 1 :(得分:0)

你说得对,ClassNotFoundException不是RuntimeException,但你的代码不需要捕获它,因为虚拟机是试图加载所有需要的类的。

如果你的代码试图通过类加载器加载一个类,你必须捕获ClassNotFound,就像这样

package a;

public class B {

    public void testLoadClass() {

        try {
            ClassLoader.getSystemClassLoader().loadClass("java.util.ArrayList");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

我认为成为Checked异常的事实是正确的,以便在编译时知道非现有的类。通过这种方式,您可以控制流程代码。如果该异常不是已检查的异常,则会在编译时丢失代码控制。这只是一种意见

答案 2 :(得分:0)

RuntimeException确实是意料之外的例外。 (例如NullPointerExceptionIndexOutOfBoundsException),通常由错误引起。只有你不需要编写代码来弥补潜在的错误,这才有意义。

相比之下,检查异常(例如FileNotFoundException)更有可能发生。因此,您需要覆盖(捕获)它,或者您需要明确表示您没有覆盖它(通过添加throws子句)。

所以,真正的问题是,ClassCastException(或任何其他ReflectiveOperationExeption)应该涵盖的内容。

我认为这是有争议的。过去几年一直有关于使用已检查例外的讨论。所以意见目前不同。

相关问题