记一次造成java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError的操作及解决

1 背景:

笔者在自己编写flink代码并进行本地测试时遇到,报错如下:这个问题明显是说在编译时JVM加载不到类或者找不到类导致的,于是报了java.lang.ClassNotFoundException,而且在运行时JVM加载不到类或者找不到类直接报错java.lang.NoClassDefFoundError

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/flink/api/scala/typeutils/CaseClassTypeInfo
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.myself.function.FunctionTest.main(FunctionTest.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.flink.api.scala.typeutils.CaseClassTypeInfo
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	... 13 more

在这里插入图片描述

2 报错分析

在上边我们提到java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError报错都是因为JVM加载不到类或者找不到类发生异常或者报错,然而两者存在本质区别那就是java.lang.ClassNotFoundException是在编译时报错,java.lang.NoClassDefFoundError是在运行时报错。那么这里我们这个报错是怎么回事呢?
我们先来看java.lang.NoClassDefFoundError报错,看到这个我们和容易想到这和java的JVM类加载机制有关,那么我们就需要了解下JVM的类加载机制双亲委派机制,什么是双亲委派机制呢?说的粗糙点就是java为我们提供了很多的类库,而不同的类库之间存在血缘关系。当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
类加载器又分为:

  • BootstrapClassLoader(启动类加载器)
    c++编写,加载java核心库 java.*,构造ExtClassLoader和AppClassLoader。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作
  • ExtClassLoader(标准扩展类加载器)
    java编写,加载扩展库,如classpath中的jre ,javax.*或者
    java.ext.dir 指定位置中的类,开发者可以直接使用标准扩展类加载器。
  • AppClassLoader(系统类加载器)
    java编写,加载程序所在的目录,如user.dir所在的位置的class
  • CustomClassLoader(用户自定义类加载器)
    java编写,用户自定义的类加载器,可加载指定路径的class文件
    详细的加载过程如图所示:
    在这里插入图片描述
    由上面的过程我们可以发现在程序运行时,他访问了所有的类库之后才会发生这个报错NoClassDefFoundError的报错,这说明我们项目的maven文添加或者maven库出现问题或者访问不到了。那么顺着这个思路我们一路排查先看项目是否配置了相关依赖我们发现,依赖的配置的相当齐全,
    在这里插入图片描述
    那么我们看maven库是否有问题,我们在本地随便找个项目发现maven库正常,那么说明本次的报错显然是maven依赖无法访问造成的,为啥会这样呢?细心的同学已经发现原来我在项目中添加了<scope>provided</scope>这个操作是为了什么呢?这个操作其实是为了在打包到集群时我们不携带本地的flink环境,因为集群上环境已经准备好这个时候问题显然是已经找到。那么怎么解决呢?

3 问题解决

其实很简单,笔者用的是IDEA 如果大家用的其他的编程工具可以自行百度下解决办法,这里就说下我是怎么搞得,熟悉IDEA工具的同学会发现在IDEA的工具栏有一个运行配置。我们在运行前点开
在这里插入图片描述

我们发现在Configuration>>Use classpath of moudle中有一个include dependencies provided scope的选框,这个时候我们把勾选上就完了。
在这里插入图片描述
再来运行我们发现完美解决了问题:
在这里插入图片描述

4 总结

本次报错主要由于操作着急引起,之所以写在这里只为警示自己和为大家解决类似问题提供思路。当然上面分析我们借助对java.lang.NoClassDefFoundError报错的分析就解决了问题,在这了笔者也总结下其他引起java.lang.NoClassDefFoundErrorjava.lang.ClassNotFoundException的原因及情况,希望能帮到大家如下:

  • NoClassDefFoundError可能出现的情况
  1. 一种情况就是因为静态变量加载不到原因
  2. 工程里没有将jar添加到classpath,maven项目的,需要根据项目情况排查
  • ClassNotfoundException
    java开发中经常遇到java.lang.ClassNotfoundException异常,ClassNotfoundException异常一般就是编译时找不到类,Console台就会输出异常信息。一般情况下,我们都会rebuild或者clean一下工程,让项目重新编译一遍。
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扫地增

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值