最近发现Jenkins上跑的一个案例报如下错误
定位日志发现是调用jar里的一个类,而这个类加载的XXX.context.xml配置文件中配置的是连接别的系统的JNDI URL和端口地址,由于junit测试是相对独立的,所以当SRC下面的类引用到这个时,边报异常了,
后来通过修改本地 build-junit.xml中的,增加了一个jar,jar里面的class文件是重写报错的jar里面的类的。
<classpathrefid="master-classpath"/>
<path id="master-classpath">
<filesetfile="${build.ext.dir}/Areplace.jar"/>
<filesetdir="${build.lib.dir}"/>
<filesetfile="${lib.weblogic.jar}"/>
<filesetfile="${weblogic.server.lib}/ojdbc6.jar"/>
</path>
那为什么一开始Eclispe里面Junit是可以执行成功的呢?原因是因为所引用的那个错误的jar位于所测试的类的后面,后来我把用jar调到最上面位置,发现确实是这个原因
见博客https://blog.csdn.net/xrt95050/article/details/4413998
https://blog.csdn.net/hnzmdpan/article/details/78637635
https://blog.csdn.net/lipei1220/article/details/53924799
简单总结下:
Bootstrap classloader---引导类加载器,负责加载Java的核心类,sun.boot.class.path系统属性下的类
本地测试结果:
C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\resources.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\rt.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\sunrsasign.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\jsse.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\jce.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\charsets.jar;C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\classes
extension classloader---扩展类加载器,负责加载jre的扩展目录中jar的类包,这为引入除Java核心类以外的新功能提供了一个标准机制
本地测试结果:
C:\Oracle\Middleware\jdk160_14_R27.6.5-32\jre\lib\ext;C:\windows\Sun\Java\lib\ext
System classLoader –系统类加载器,它负责在JVM启动时,加载来自java工程中指定的CLASSPATH
本地测试结果:
XXworkplace\cfs\lib\ant.jar; XXworkplace\cfs\lib\aop_log.jar;
Extension classloader 是systemclassloader 的parent,而bootstrap classloader 是extension classloader的parent,但它不是一个实际的classloader,
每个classLoader加载Class的过程:
1.检测此CLass是否载入过(即在cache中是否有此Class),如果有的话,则到8
2.如果parent classloader不存在(没有parent,那parent一定是bootstrap了),到4
3.请求parent classloader载入,如果成功到8,不成功到5
4.请求Jvm从bootstrap载入,如果成功到8
5.寻找CLass文件(从与此classloader相关的类路径中寻找),如果找不到则到7
6.从文件中载入class,到8
7.抛出ClassNotFoundException
8.返回class
类的工作机制
查找和导入Class文件
把类的二进制数据合并到JRE中
检查载入Class文件的正确性
给类的静态变量分配存储空间
将符号引用转成直接引用
对类的静态变量,静态代码块进行初始化