What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException?

前端 未结 15 2345
忘了有多久
忘了有多久 2020-11-21 05:27

What is the difference between NoClassDefFoundError and ClassNotFoundException?

What causes them to be thrown? How can they be resolved?

15条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-21 06:13

    A NoClassDefFoundError (NCDFE) happens when your code runs "new Y()" and it can't find the Y class.

    It may simply be that Y is missing from your class loader like the other comments suggest, but it could be that the Y class isn't signed or has an invalid signature, or that Y is loaded by a different classloader not visible to your code, or even that Y depends on Z which couldn't be loaded for any of the above reasons.

    If this happens, then the JVM will remember the result of loading X (NCDFE) and it will simply throw a new NCDFE every time you ask for Y without telling you why:

    class a {
      static class b {}
      public static void main(String args[]) {
        System.out.println("First attempt new b():");
        try {new b(); } catch(Throwable t) {t.printStackTrace();}
        System.out.println("\nSecond attempt new b():");
        try {new b(); } catch(Throwable t) {t.printStackTrace();}
      }
    }
    

    save this as a.java somewhere

    The code simply tries to instantiate a new "b" class twice, other than that, it doesn't have any bugs, and it doesn't do anything.

    Compile the code with javac a.java, Then run a by invoking java -cp . a -- it should just print out two lines of text, and it should run fine without errors.

    Then delete the "a$b.class" file (or fill it with garbage, or copy a.class over it) to simulate the missing or corrupted class. Here's what happens:

    First attempt new b():
    java.lang.NoClassDefFoundError: a$b
        at a.main(a.java:5)
    Caused by: java.lang.ClassNotFoundException: a$b
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
        ... 1 more
    
    Second attempt new b():
    java.lang.NoClassDefFoundError: a$b
        at a.main(a.java:7)
    

    The first invocation results in a ClassNotFoundException (thrown by the class loader when it can't find the class), which must be wrapped in an unchecked NoClassDefFoundError, since the code in question (new b()) should just work.

    The second attempt will of course fail too, but as you can see the wrapped exception is no more, because the ClassLoader seems to remember failed class loaders. You see only the NCDFE with absolutely no clue as to what really happened.

    So if you ever see a NCDFE with no root cause, you need to see if you can track back to the very first time the class was loaded to find the cause of the error.

提交回复
热议问题