前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >常见加载类错误分析

常见加载类错误分析

作者头像
MickyInvQ
发布于 2020-09-27 09:16:58
发布于 2020-09-27 09:16:58
1.2K00
代码可运行
举报
文章被收录于专栏:InvQ的专栏InvQ的专栏
运行总次数:0
代码可运行

在执行 Java程序时经常会碰到ClassNotFoundException和NoClassDefFoundError两个异常,它们都和类加载有关,下面详细分一下这两个异常的原因。

ClassNotFoundException

ClassNotFoundException恐怕时Java程序员经常碰到的异常,尤其是初学者来说,简直是让人崩溃,明明那个类就在那里,为啥就是找不到呢?无数个Java程序员都是这样问过自己。 这个异常通常发生在显式加载类的时候,例如用如下方式调用加载一个类时就报这个错了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class NotfoundException {
    public static void main(String[] args) {
        try {
            Class.forName("NotfoundException");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

显式加载通常由如下方式:

  • 通过类Class中的forName()方法
  • 通过类ClassLoader中的loadclass()方法
  • 通过类ClassLoader中的findSystemClass()方法 出现这类错误也很好理解,就是当JVM要加载指定文件的字节码到内存时,并没由找到这个类对应的字节码,也就是说这个字节码.class文件不存在。解决方法就是检测在当前的classpath目录下有没有指定的文件存在,如果不知道classpath路径,就可以通过如下命令获取:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
this.getClass().getClassLoader().getResource("").toString()

NoClassDefFoundError

NoClassDefFoundError是另一个经常遇到的异常,这个异常在第一次使用命令执行Java类时很可能会碰到,如下面这种情况

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java -cp example.jar Examper

在这个jar包里面只有一个类,这个类时net.xx.Exmple ,可能让你感到郁闷的是,命名这个jar包里面有这个类为啥会报这个错呢? 这是因为你在命令行中没有加类的包名,正确的写法是这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java cp example.jar net.xx.Example

在JVM的规范中描述了出现NoClassDefFoundError可能的情况就是使用new关键字、属性引用某个类、继承了某个接口或者类,以及方法的某个参数中引用了某个类,这个是出发JVM隐式加载这些类时发现这些类不存在的异常。

解决这个错误的方法就是确保这个类引用的类都在当前的classpath下面

UnsatisfiedLinkError

这个异常倒不是很常见,但是出错的话,通常是在JVM启动的时候,如果一不小心将在JVM的某个lib删除了,可能就会报这个错误了,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package test;

public class NolibException {
    public native void nativeMethod();
    static {
        System.loadLibrary("Nolib");
    }

    public static void main(String[] args) {
        new  NolibException().nativeMethod();
    }
}

这个错误通常时在解析native标识的方法时JVM找不到对应的本机库文件时出现,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java.lang.UnsatisfiedLinkError: no Nolib in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at test.NolibException.<clinit>(NolibException.java:6)
Exception in thread "main" 
Process finished with exit code 1

ClassCastException

这个错误也很常见,通常在程序中出现强制类型转换时出现这个错误,如下面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package test;

import java.util.HashMap;
import java.util.Map;

public  class CastException {
    public static Map map = new HashMap(){{
        put("a","2");
    }};

    public static void main(String[] args) {
        Integer integer = (Integer) map.get("a");
        System.out.println(integer);
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at test.CastException.main(CastException.java:12)

JVM在做类型转换时会按照如下规则进行检查

  • 对于普通对象,对象必须时目标类的实例或目标类的子类的实例。如果目标是是接口,那么会把它当作实现了接口的一个子类。
  • 对于数组类型,目标类必须是数组类型或java.lang.Object、java.lang.Cloneable、java.io.Serializele 如果不满足上面的规则,JVM就会报这个错误。要避免这个错误有两种方式:
  • 容器类型中现实的指明这个容器所包含的对象类型,如在上面的map中可以写为public static Map<String,Integer> map = new HashMap<String, Integer>(){{ put("a",2); }};,这样运行就可以没问题。
  • 先通过instanceof检查是不是目标类型,然后再进行强制类型转换。

ExceptionInInitializerError

这个错误在JVM规范中是这样定义的:

  • 如果Java 虚拟机试图创建类ExceptionInInitializerError的新实例,但是因为出现Out-Of-Memory-Error而无法创建新实例,那么就抛出OutOfMemoryError对象作为代替。
  • 如果初始化器抛出一些Excepton,而且Exception类不是Error或者它的某个子类,那么就会创建ExceptioinInInitializerError类的一个新实例,并用Exception作为参数,用这个实例代替Excepiton。

将上面的代码例子稍微改一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package test;

import java.util.HashMap;
import java.util.Map;

public  class CastException {
    public static Map<String,Integer> map = new HashMap<String, Integer>(){{
        map.put("a",2);
    }};

    public static void main(String[] args) {
        Integer integer = (Integer) map.get("a");
        System.out.println(integer);
    }
}

这段代码在执行时报错如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java.lang.ExceptionInInitializerError

在初始化这个类时,给静态属性map赋值时出现了异常导致抛出错误ExceptionInInitializerError

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/04/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
23种设计模式之工厂模式(Java语言实现)
工厂模式属于创建型模式,设计思路是定义一个接口表示一个类型,再定义多个属于该类型的实现类实现接口中的方法。
静谧星空TEL
2021/04/27
2830
23种设计模式之工厂模式(Java语言实现)
java中如何靠interrupt来停止stop一个线程
ThreadMark_to_win mt = new ThreadMark_to_win();
马克java社区
2021/04/09
3880
java中如何靠interrupt来停止stop一个线程
java中类中多个Synchronized方法
下面给出一个例子,说明一个class中有两个方法synchronized的情况。它们互相阻挡的用法和上面的“一个方法有synchronized”的情况是一样的。
马克java社区
2021/04/23
9040
java中类中多个Synchronized方法
java中什么是线程不安全给出一个例子
System.out.println(Thread.currentThread().getName()
马克java社区
2021/04/20
3620
java中什么是线程不安全给出一个例子
java中异常(Exception)的定义,意义和用法。举例
System.out.println("马克-to-win:inside try");
马克java社区
2021/04/06
5200
java中异常(Exception)的定义,意义和用法。举例
java中请给一个Abstract类实现接口的实例!
马克-to-win:如果实现某接口的类是abstract类,则它可以不实现该接口所有的方法。但其非abstract的子类中必须拥有所有抽象方法的实在的方法体;(当然它abstract爹的也算作是它的)
马克java社区
2021/03/30
1.1K0
java中请给一个Abstract类实现接口的实例!
java中给出一个主线程要join子线程的例子
下面给出了一个join和interrupt互动的例子,还是主线程要join子线程。
马克java社区
2021/04/09
4690
java中给出一个主线程要join子线程的例子
java中如何能把一个字符串转成日期对象
当我们想根据输入字符串得到一个日期对象时我们不知道,应该以什么格式写这个字符串,才能被系统正确解析,一种聪明的做法是,马克-to-win,我们先 把日期对象根据我们的格式打印出来,之后照打印出来的样子,一丝不差的写这个字符串,这个字符串必定能被系统正确解析。下面这个例子,就是先把日期对象根 据我们的格式打印出来。之后才涉及到解析。
马克java社区
2021/03/22
6370
java中如何能把一个字符串转成日期对象
java中的方法(method)到底怎么用?给个例子
更多请看:https://blog.csdn.net/qq_44639795/article/details/103145051
马克java社区
2021/03/09
6190
java中的方法(method)到底怎么用?给个例子
java中Arrays有什么用,举例说明?
/*public static boolean equals(int[] a1, int[] a2)
马克java社区
2021/04/30
4010
java中Arrays有什么用,举例说明?
java中请给出一个抽象类,可以继承实体类的例子
System.out.println("Turn steering wheel");
马克java社区
2021/03/29
7060
java中请给出一个抽象类,可以继承实体类的例子
java中StringBuffer的用法
StringBuffer:String类同等的类,它允许字符串改变(原因见上一段所说)。Overall, this avoids creating many temporary (临时)strings, in other words, without StringBuffer, you must create many temporary strings.  StringBuffer的内部实现原理:马克-to-win,Every string buffer(缓存) has a capacity(容量). As long as the length of the character sequence contained in the string buffer does not exceed(超过) the capacity, it is not necessary to allocate(分配) a new internal buffer array. If the internal buffer overflows(满后溢出), it is automatically made larger.附带一句:从JDK5开始引入StringBuilder类,它是简易的StringBuffer,速度更快,但线程不安全
马克java社区
2021/03/22
5300
java中StringBuffer的用法
java中Timer的概念是什么举一个例子
Timer 是一个线程工具。它方便线程来调度任务马克-to-win在后台执行。可能会安排任务为一次性执行,或定期重复执行,下面给出例子:
马克java社区
2021/04/26
3710
java中Timer的概念是什么举一个例子
java中instanceof是怎么用的, 干什么使的,举例
instanceof是java中固有的关键字, 就像main, public一样,用法:aa instanceof AA 就是问aa是不是AA的一个实例, 是的话,就返回真。马 克 - t o   - w i n:当用instance of测试时,马克-to-win:子类的指针是一个instance of父类, 返回值为真,见以下的例子。
马克java社区
2021/03/29
3990
java中instanceof是怎么用的, 干什么使的,举例
java中泛型有什么用,举例说明
从jdk1.5以后,java用<>来限制存入集合容器的对象的类型必须是<>中规定好的。
马克java社区
2021/04/30
2780
java中泛型有什么用,举例说明
java中StringTokenizer的用法
/*用缺省分隔符空格把a这个字符串分开来, 之后把结果放在StringTokenizer类型的st_Mark_to_win中,即使空很多个格也没问题,这为我们io那章,自己发明自己的j+语言,奠定了坚实的基础*/
马克java社区
2021/03/22
7460
java中StringTokenizer的用法
java中Vector有什么用,举例说明
马克-to-win:Vector和ArrayList很类似,前面讲了二者的区别,就在于同步的问题上,Vector的使用是非常简单的:先创建一个,再用addElement()置入对象,以后用elementAt()取得那些对象
马克java社区
2021/04/27
4400
java中Vector有什么用,举例说明
java中TreeMap有什么用,举例说明
马克-to-win:TreeSet是按升序顺序输出的。TreeMap也是按升序输出,但是和它的区别就是TreeSet存储的是单个元素,而TreeMap存储的是一个一个的键值对。
马克java社区
2021/04/30
6480
java中什么是Interface接口, 请给个实例!
先直接上大白话:马克-to-win:接口就是灰常灰常抽象的抽象类,我们可以就像用抽象类一样用接口,只不过,interface抽象到不能再抽象了,以至于里面不能有任何方法的实现, 只能都是空方法。紧接着来个例子:
马克java社区
2021/03/30
4680
java中什么是Interface接口, 请给个实例!
java中String类的用法
String不像int或float, 它是参考类型。final类型, 不能被继承,String is a Reference Type,Defined in java.lang package
马克java社区
2021/03/17
5150
java中String类的用法
推荐阅读
相关推荐
23种设计模式之工厂模式(Java语言实现)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文