记一次造成java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError的操作及解决
Posted 扫地增
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次造成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所在的位置的classCustomClassLoader
(用户自定义类加载器)
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.NoClassDefFoundError
和java.lang.ClassNotFoundException
的原因及情况,希望能帮到大家如下:
NoClassDefFoundError
可能出现的情况
- 一种情况就是因为静态变量加载不到原因
- 工程里没有将jar添加到classpath,maven项目的,需要根据项目情况排查
ClassNotfoundException
java开发中经常遇到java.lang.ClassNotfoundException异常,ClassNotfoundException异常一般就是编译时找不到类,Console台就会输出异常信息。一般情况下,我们都会rebuild或者clean
一下工程,让项目重新编译一遍。
以上是关于记一次造成java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError的操作及解决的主要内容,如果未能解决你的问题,请参考以下文章
记一次线上故障--HashMap在多线程条件下运行造成CPU 100%
记一次线上故障--HashMap在多线程条件下运行造成CPU 100%