博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别
阅读量:5859 次
发布时间:2019-06-19

本文共 2245 字,大约阅读时间需要 7 分钟。

 

  以前一直没有注意过这个问题,前两天机缘巧合上网查了一下,然后自己测试验证了一下。虽然网上说法很多,但是关于NoClassDefFoundError并没有给出一个样例,所以一直无法理解,索性自己验证了一下,收获还不少。

  ClassNotFoundException

  ClassNotFoundException这个错误,比较常见也好理解。

  原因:就是找不到指定的class。

  常见的场景就是:

  1 调用class的forName方法时,找不到指定的类

  2 ClassLoader 中的 findSystemClass() 方法时,找不到指定的类

  3 ClassLoader 中的 loadClass() 方法时,找不到指定的类

  开发者平时会有这样一种使用方法,类似JDBC加载驱动!

1 package test321; 2  3 public class test { 4  public static void main(String[] args) { 5   try { 6    Class.forName("test321.hello"); 7   } catch (ClassNotFoundException e) { 8    e.printStackTrace(); 9   }10  }11 }

  此时,程序会到当前的目录中寻找指定位置test321.hello这个class。

  并且这个类也是可以正常执行的。

  但是,我们修改一下加载的类名,这样显然是找不到指定的类的。

1 package test321; 2  3 public class test { 4  public static void main(String[] args) { 5   try { 6    Class.forName("test321.hello1"); 7   } catch (ClassNotFoundException e) { 8    e.printStackTrace(); 9   }10  }11 }

  此时就会报错!

报错!java.lang.ClassNotFoundException: test321.hello1 at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:190) at test321.test.main(test.java:6)

  原因就是找不到指定的string对应的class文件。

  NoClassDefFoundError

  这个就比较奇葩了,查找其他的资料是说,通过了编译,但是使用的时候,比如new的时候会出错。

  通过查找资料,搜集到如下的场景:

  1 类依赖的class或者jar不存在

  2 类文件存在,但是存在不同的域中

  3 大小写问题,javac编译的时候是无视大小的,很有可能你编译出来的class文件就与想要的不一样!这个没有做验证。

  

  针对上面的第二点,做了个关于包名的验证:

  另一种情况就是由于你通过了编译,但是这个类是有包名的,因此在编译时需要指定classpath,在使用的时候需要加上包名才可以。

  下面做了一个小例子!

  在没有包名的情况下,我们看一下正常情况是什么样子的。

1 public class test {2  public static void main(String[] args) {3   System.out.println("test");4  }5 }

  而如果这个类中包含包名,那么按照上面的方法编译,使用时就会报错!

1 package ccc;2 3 public class test {4  public static void main(String[] args) {5   System.out.println("test");6  }7 }

  很明显,报错信息中指出了包的信息!那么怎么办呢?

  在编译时,加上【   -d .   】这样可以把当前的目录加入到classpath中。

  在使用时,加上包名就可以了!

  也就是说,这个含有包名的类,编译时,需要指定classpath的路径,并且使用的时候指定包名全路径,才可以。

 

转载地址:http://dwljx.baihongyu.com/

你可能感兴趣的文章
如何解决动态IP环境下服务器搭建问题
查看>>
重新回顾九大排序算法
查看>>
UML类图几种关系的总结
查看>>
折腾Java设计模式之命令模式
查看>>
【Qt笔记】画刷和画笔
查看>>
mysql中Explain语法
查看>>
★智能广告:用户在哪儿广告就去哪儿?
查看>>
算法之【牛顿迭代法】
查看>>
社会地位即服务, Status as a Service (二): 社交网络的投资回报率 (ROI)
查看>>
精通CSS滤镜(filter)(实例解析)
查看>>
Kafka 1.0.0安装和配置--Linux篇
查看>>
小熊猫学木匠,无序到有序的代价!
查看>>
关于Keytool创建服务器自签名证书
查看>>
如何详细设置SUN/IBM JVM的GC日志输出(转)
查看>>
python3.x异常处理(X)-------------官方文档的异常类型
查看>>
springboot git maven jenkins 实现自动化部署
查看>>
VIM使用系列:使用VIM进行项目开发的准备工作
查看>>
踢开绊脚石:微服务难点之服务调用的解决方案
查看>>
JS前台数据校验(常用)留底备份
查看>>
android国际化
查看>>