NoClassDefFoundError && ClassNotFoundException

两种错误都是涉及类加载问题,类层次结构如下:

NoClassDefFoundError是系统错误,ClassNotFoundException是系统异常,可以捕获。 NoClassDefFoundError发生在对Class原始文件解析通过类的全限定名在类路径下无法找到相关类的定义时;ClassNotFoundException发生在通过调用Class.forName()、类加载器的loadClass/findClass在程序中自定义加载类时。

  • 注: 以下测试代码文件夹层次结构: *

下面为NoClassDefFoundError测试程序,TestReference.java程序内引用google.guava包里的第三方类。在编译时将第三方的guava-23.0.jar加入到classpath里,编译通过,运行时不加classpath,然后程序就会抛出NoClassDefFoundError,通过异常堆栈可以看出,底层也是通过loadClass来尝试加载引用的类的。

1import com.google.common.base.*; 2import com.google.common.collect.*; 3import java.util.*; 4public class TestReference{ 5 public static void main(String[] args){ 6 Map<String,String> a = Maps.newHashMap(); 7 } 8} 9 10 11 12javac -cp guava-23.0.jar TestReference.java 13// 编译OK 14java TestReference 15// 报错: 16// Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/col 17// lect/Maps 18// at TestReference.main(TestReference.java:6) 19// Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps 20// at java.net.URLClassLoader.findClass(Unknown Source) 21// at java.lang.ClassLoader.loadClass(Unknown Source) 22// at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) 23// at java.lang.ClassLoader.loadClass(Unknown Source) 24// ... 1 more 25java TestReference -cp .;guava-23.0.jar 26// 执行OK

通过研究Class文件结构可以得出以下结论: 当Java程序运行时,JVM加载TestReference.class文件,解析出methodRef下code属性里的代码内容,通过代码里写的类短名称加上import的空间定位引用类的全限定名,然后通过全限定名在类路径下加载相关的类,当没有找到时抛出该错误。这个错误是JVM抛出。

下面是ClassNotFoundException示例代码,ClassNotFoundException代码里通过Class.forName("") 加载google.guava的类:

1public class TestClassForname{ 2 public static void main(String[] args) throws Exception{ 3 Class a = Class.forName("com.google.common.collect.Maps"); 4 } 5} 6 7 8 9javac TestClassForname.java 10// 编译OK 11java TestClassForname 12// Exception in thread "main" java.lang.ClassNotFoundException: com.google.common.c 13// ollect.Maps 14// at java.net.URLClassLoader.findClass(Unknown Source) 15// at java.lang.ClassLoader.loadClass(Unknown Source) 16// at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) 17// at java.lang.ClassLoader.loadClass(Unknown Source) 18// at java.lang.Class.forName0(Native Method) 19// at java.lang.Class.forName(Unknown Source) 20// at TestClassForname.main(TestClassForname.java:4)

ClassNotFoundException这个异常的定义就是没有加载到类就抛出这个异常,上面说的NoClassDefFoundError底层也是通过抛出这个异常触发的,只不过JVM会在上面场合下通过捕获ClassNotFoundException然后转而抛出NoClassDefFoundError错误。

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java的fail-fast机制究竟是什么?

failfast机制快速失败模块的职责是检测错误,然后让系统的下一个最高级别处理错误。一旦发生异常,直接停止并上报。尽最大努力去抛出异常。这样做的好处是可以预先识别出一些错误情况,但是它同样也可能会为我们带来一些问题。集合类的failfast机制当多个线程对部分集合进行结构上的改变操作,有可能会产生failfast机制,这时候会抛出ConcurrentM

SpringBoot整合Redis乱码原因及解决方案

问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa

SpringBoot整合Redis乱码原因及解决方案

问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa

Java 的Throwable、error、exception的区别

1.  什么是异常?异常本质上是程序上的错误,包括程序逻辑错误和系统错误。比如使用空的引用(NullPointerException)、数组下标越界(IndexOutOfBoundsException)、内存溢出错误等。Throwable类是Java语言中所有错误或异常的超类。有两个重要的子类:Exception(异常)和Error(错误),

Exception、Thorow、Throws、TryCatch

一、异常 概述:  异常指的是不正常,指的是程序中出现了某种问题       java中,所有问题都可以使用一个类来表示,这个类叫做Throwable  Throwable:       Throwawble是java中所有异常和错误的父类      Error: 表示错误,指的是不可挽回的严重问题