美文网首页
记一次类加载机制导致的问题

记一次类加载机制导致的问题

作者: 麦芽maiya | 来源:发表于2021-01-26 22:40 被阅读0次

    一.问题描述:

    因业务需要同阿里菜鸟平台联调接口,引入阿里link开发的基础包(阿里没有将该包上传仓库,估计是由于其代码包不是稳定版,所以嫌管理麻烦,就私发给客户的开发人员了)。

    项目pom文件中使用<systemPath>依赖后,本地开发完成也能正常运行,于是乎打包成jar包后上传服务器,通过命令行jar包运行命令启动发现异常报错,于是乎开启troubleshooting模式。

    二.现象

    启动报错:

    ∆ nested exception is java.lang.NoClassDefFoundError: com/taobao/pac/sdk/cp/ReceiveListener

    ∆ Caused by: java.lang.NoClassDefFoundError: javax/servlet/http/HttpServlet

    三.排查解决

    1.com/taobao/pac/sdk/cp/ReceiveListener NoClassDefFoundError问题

    初步怀疑是阿里所给的三方包没有在mvn打包到自己工程的jar包,于是jar xvf解压jar包,果不其然在BOOT-INF/lib/目录没有找到pac.sdk.cp-xxx.jar

    于是利索的将pac.sdk.cp-xxx.jar放到服务器java的$JAVA_HOME/jre/lib/ext目录,重启后遇到第二个问题。

    2. javax/servlet/http/HttpServlet java.lang.NoClassDefFoundError问题

    mvn dependency:tree -Dverbose项目依赖树打出来确定是有tomcat-embed-core:jar:8.5.14

    [INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.3.RELEASE:compile[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.14:compile[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.14:compile[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.14:compile[INFO] |  |    \- (org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.14:compile - omitted for duplicate)

    于是怀疑自己工程应用包没有第三方包导致的,决定将菜鸟的三方jar包直接打进来应用jar包里。

    重启后依然是出现第二个错误,怀疑人生了吧。。。

    没错,这里就是本文的重点,Java类加载机制的双亲委派模型。其实解决这个问题已经接近尾声了,只要删掉刚才放到$JAVA_HOME/jre/lib/ext目录下的pac.sdk.cp-xxx.jar即可。

    四.总结

    首先了解下Java中内置了三种类型类加载器:

    1.Bootstrap ClassLoader – 它加载JDK的内部类,典型的有rt.jar和其他核心类;

    2.Extensions ClassLoader – 它加载JDK扩展目录的类,通常是$JAVA_HOME/lib/ext目录;

    3.System ClassLoader – 它加载当前classpath的类,可以在调用程序是命令行指定-cp或者-classpath命令来设置。

    双亲委派模型中除了启动类加载器之外其余都需要有自己的父类加载器

    当一个类收到了类加载请求时: 自己不会首先加载,而是委派给父加载器进行加载,每个层次的加载器都是这样。

    所以最终每个加载请求都会经过启动类加载器。只有当父类加载返回不能加载时子加载器才会进行加载。

    双亲委派的好处 : 由于每个类加载都会经过最顶层的启动类加载器,比如 java.lang.Object这样的类在各个类加载器下都是同一个类(只有当两个类是由同一个类加载器加载的才有意义,这两个类才相等。)

    如果没有双亲委派模型,由各个类加载器自行加载的话。当用户自己编写了一个 java.lang.Object类,那样系统中就会出现多个 Object,这样 Java 程序中最基本的行为都无法保证,程序会变的非常混乱。

    现在知道真相了吧!pac.sdk.cp-xxx.jar优先被Extensions ClassLoader加载,而System ClassLoader并没有加载,所以javax/servlet/http/HttpServlet会出现NoClassDefFoundError。

    作者:mitsuii

    链接:https://www.jianshu.com/p/ff1005987537

    相关文章

      网友评论

          本文标题:记一次类加载机制导致的问题

          本文链接:https://www.haomeiwen.com/subject/jgnnzktx.html