J2EE 开发过程中jar包冲突的问题如何排查?

微信用户0305510278

共 2059字,需浏览 5分钟

 ·

2022-08-04 06:36

前言

    我们都知道,J2EE应用程序一般由jar包、class文件和配置文件构成,J2EE应用程序开发完成后,一般打包放到tomcat容器中运行。项目运行过程中,往往会出现某个类找不到(java.lang.ClassNotFoundException),或者或出现类中的某个方法未定义(java.lang.NoSuchMethodException),那么针对这类问题,我们该如何排查呢?要搞清这类问题,我们必须得知道java class的加载机制及原理,尤其是jar包及class的加载顺序。本文针对开发过程中的这类问题,给出以下几点经验分享。


J2EE应用程序运行时所依赖的jar包和class文件有哪些?

  1.  $java_home/lib 目录下的java核心api,这些类通常是由BootstrapClassLoader加载的。

  2. $java_home/lib/ext 目录下的java扩展jar包,这些类通常是由ExtensionClassLoader加载的。

  3. jvm命令java运行参数中指定的 -classpath  或  -Djava.library.path所指的目录下的类与jar包。

  4. 项目路径/WEB-INF/lib下的jar文件,这些类通常是由应用程序ClassLoader加载的。

  5. 项目路径/WEB-INF/classes下的class文件,这些类通常是由应用程序ClassLoader加载的。

  6. $CATALINA_HOME/common下的jar包,这些类是由tomcat自身类加载器加载完成的,tomcat打破了双亲委派类加载机制,自定义了一些类加载器,感兴趣的朋友可以深入学习tomcat原理。

  7. $CATALINA_HOME/server目录下的jar包,加载的过程同上。

  8. $CATALINA_BASE/shared目录下的jar包,加载的过程同上。

jar包和class文件加载的顺序是啥样的?

    按照上面编号进行排序的结果为(加载顺序由早到晚):1->2->3->6->7->8->5->4,从排序结果可知,java环境变量下的jar包或类优先加载,其次为tomcat目录下的,最后为项目路径下的,这里要说明的是,假如项目路径WEB-INF/class下如果有一个class文件与项目WEB-INF/lib 某一个jar包中的class文件包名类名都相同时,那么优先加载WEB-INF/class下的那个。


 jar包冲突问题排查(仔细看,很重要哦!)  

    我们在做J2EE应用程序开发时,经常会遇见找不到某个类或方法的问题,这些问题的根源还是在于应用程序运行时,依赖的jar包不存在或jar包中的类有冲突。现在java应用程序开发时,一般都基于 maven管理依赖的jar包,能很好的解决上面说的问题,但是,对于一些隐藏问题,maven是很难发现的。举个例子,项目路径/WEB-INF/lib目录下有个b.jar,b.jar中有一个com.demo.A类,A类中有m1,m2,m3三个方法。项目开发完成后提交给测试进行验证,发现异常信息,错误日志提示找不到A类中的m3方法,这个时候是不是陷入了恐慌的状态?明明是有m3方法的呀,为何找不到,郁闷...,对于这种问题,如果是一个新手或者经验不足的老鸟,估计要耗费大量的时间来排查,并且结果会不尽人意。那么,该怎么去解决?


    首先还是要了解jar及class文件的加载原理,为何会出现上面的现象,原因就在于jvm当前加载的那个A类不是你b.jar包中的那个A类,那么你的疑问来了,我项目中的那个期望的A类为何没被加载?答案就是你期望的那个A类被顶替了。

    其次,我们知道问题的原因了,A类为何被顶替?原因在于jvm在加载项目中的A类前,已经加载了WEB-INF/lib 下另外一个a.jar包中同样包名下的A类,然而这个A类中只有m1,m2两个方法,所以项目运行时就找不到m3方法了。需要说明的是,a.jar和b.jar都属于同一个ClassLoader加载的,所以先加载的a.jar中的A类,b.jar中的A类就不加载了,如果a.jar和b.jar用不同的ClassLoader进行加载,那么就不会出现这种现象,会存在两个同样包名下名字相同的A类,但这两个A类是相互隔离的。关于ClassLoader的工作原理及隔离机制,大家可以看下《深入理解java虚拟机》这本书。

总结

    总之,jar包冲突的问题如何解决,还是得深入了解jvm类加载原理。另外在java的学习过程中,不能忽视了jvm原理的学习,熟练掌握jvm原理对程序的性能优化有很大的帮助,同时处理一些疑难问题也轻而易举。本文只代表作者的观点,如果不对的地方,可以在评论区留言,我们一起学习探讨,另外,后续还会给大家分享一些开发过程中遇到的一些问题及解决方法,喜欢的朋友们可以加关注哦!

浏览 24
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报