0

My main worker thread looks like this:

public final class Worker
implements Runnable {

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

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

Imagine my surprise when Thread.UncaughtExceptionHandler reported an uncaught instance of java.lang.ClassNotFoundException, a checked exception.

(The root cause is a different issue: We were overwriting a JAR file in a dev environment during runtime.)

In my book, this looks like a Sneaky Throw. Why is this exception not a RuntimeException?

Sample stacktrace (sanitised):

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
Community
  • 1
  • 1
kevinarpe
  • 20,319
  • 26
  • 127
  • 154

3 Answers3

3

Why is this exception not a RuntimeException?

This is the Hierarchy of java.lang.ClassNotFoundException

java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.ReflectiveOperationException
     java.lang.ClassNotFoundException

As you see it does not extend in any way the RuntimeException, that has this Hierarchy

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

If you like to catch both of them; catch Exception,

if you like to catch all; catch Throwable

and finally, if you like to learn more about hierarchy and inheritance you can start here: Inheritance - Java doc

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
0

You are right, ClassNotFoundException is not a RuntimeException but your code dont need to catch it because is the Virtual machine the one that try to load all the needed classes.

If your code try to load a class through class loader you must catch the ClassNotFound, like this

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();
        }
    }
}

I think the fact to be a Checked exception is ok in order to be aware of non existing classes in compilation time. In this way you can control the flow code. If that exception is not a checked exception, you would lost the code control in compilation time. It´s only an opinion

Francisco Hernandez
  • 2,378
  • 14
  • 18
0

RuntimeExceptions are unexpected exceptions really. (e.g. a NullPointerException or IndexOutOfBoundsException), usually caused by bugs. It only makes sense that you don't need to write code to cover for potential bugs.

In contrast a checked exception (e.g. FileNotFoundException) is more likely to happen. And therefore you either need to cover (catch) it, or you need to make clear that you didn't cover it (by adding a throws clause) .

So, the real question is, is a ClassCastException (or any other ReflectiveOperationExeption) something that you should cover.

I think it is arguable. There has been some discussion about the use of checked exceptions in the last years. So opinions differ at the moment.

bvdb
  • 22,839
  • 10
  • 110
  • 123