java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别
以前一直没有注意过这个问题,前两天机缘巧合上网查了一下,然后自己测试验证了一下。虽然网上说法很多,但是关于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的路径,并且使用的时候指定包名全路径,才可以。
参考资料
1 http://blog.csdn.net/magister_feng/article/details/7459151
2 http://www.blogjava.net/leekiang/archive/2007/04/26/113810.html
3 http://blog.sina.com.cn/s/blog_65c507190100hzs0.html
- 工作组模式下专用队列(Private Queue)如何引用远程队列路径
- haproxy反向代理环境部署(http和https代理)
- 网站速度优化模块HttpCompressionModule
- mysql启动后随即关闭问题解决(ibdata1文件损坏导致)
- webvirtmgr-重命名kvm虚拟机的名称
- Lucene 2.0最基本的入门代码
- 网站每日PV/IP统计/总带宽/URL统计脚本分享(依据网站访问日志)
- 查看服务器系统资源(cpu,内容)利用率前几位的进程的方法
- 腾讯云平台部总经理陈磊:大数据背后的技术支撑
- DataSet与Xml相互转化
- SqlTransaction事务使用示例
- nginx的web缓存服务环境部署记录
- nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录
- [转自blueidea]像table一样布局div Ⅰ
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- ES系列之原来ES的聚合统计不准确啊
- fastjson远程代码执行漏洞问题分析
- 数据库连接池的原理没你想得这么复杂
- 你真的会用volatile吗
- 你真的了解LinkedBlockingQueue的put,add和offer的区别吗
- 关于Java使用groupingBy分组数据乱序问题
- 详解 java CompletableFuture
- 从一个问题来解释下什么是mysql的可重复读
- 每个人都用得到的频数分布直方图
- 利用箱线图巧剔异常值
- dubbo服务接口设计的几个建议
- 使用kafka连接器迁移mysql数据到ElasticSearch
- 这可能是讲雪花算法最全的文章
- 带你了解控制线程执行顺序的几种方法
- 一文说透访问者模式