java项目中相同jar的不同版本谁先引入谁先加载
第一种解决办法:
进行版本之间的整合
第二种解决办法:
目前只在java项目中成功,J2EE项目中没成功,所以本次J2EE项目根据java文件所要引入的高版本的jar,直接通过将import的类重新根据class文件编写
报错如下
Exception in thread "main" java.lang.SecurityException: class "org.xxx.xxx"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:943) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:657) at java.lang.ClassLoader.defineClass(ClassLoader.java:785) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:791) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at cn.csg.soa.isc.interceptor.Sm3Utils.hash(Sm3Utils.java:52) at cn.csg.soa.isc.interceptor.Sm3Utils.encrypt(Sm3Utils.java:36) at cn.csg.soa.isc.interceptor.Sm3Utils.main(Sm3Utils.java:105)
很明显是有相同的package,而项目在引入包名下的类时出错(类加载时由于有相同的包路径,jvm根据加载顺序后遇到的相同包路径下的文件不进行加载,所以当项目需要引入后面这个jar包内容时会出错)
两个冲突的jar我们称为jarA和jarB
解决办法:将需要引入的jarA包引入项目内,并且在项目名如(test)下创建文件MANIFEST.MF,内容如下,然后进行打包成jarC
测试办法:将两个有冲突的jar包和新打好的jarC包引入项目中,(如果只引入新打好的jarC包会出错,至少需要引入新打好的jarC和之前引入的jarA),三个引入测试是否还会出错
Manifest-Version: 1.0 Class-Path: ../lib/xxx.jar
第三种解决办法:
引入一个版本的jar包,另一个jar包如果不能进行整合,可以将需要引入的类编写进入项目来替代需要引入的包
第四种解决办法:
自定义类加载类,根据jar包所在的位置加载进入,但是不能将jar放在像WEB-INF/lib这个下面,不然会造成冲突
1 package com.qf.jf; 2 import java.lang.reflect.Method; 3 import java.net.MalformedURLException; 4 import java.net.URL; 5 import java.net.URLClassLoader; 6 public class CustomClassLoader extends ClassLoader{ 7 8 @Override 9 public Class<?> loadClass(String name) throws ClassNotFoundException { 10 return super.loadClass(name); 11 } 12 13 public void test() throws Exception { 14 URLClassLoader clsLoader=null; 15 try { 16 clsLoader = URLClassLoader.newInstance(new URL[] {new URL("file:/C:/XXX/X.1.57.jar")}); 17 } catch (MalformedURLException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 Class byteUtils=null; 22 Class sm3Digest=null; 23 try { 24 25 byteUtils = clsLoader.loadClass("包名+类名");//比如:org.qf.Test 26 sm3Digest = clsLoader.loadClass("xxx.xx"); 27 } catch (ClassNotFoundException e) { 28 e.printStackTrace(); 29 } 30 //获取类实例化对象,以便在之后的使用中运用同一个实例 31 Object clazz=sm3Digest.newInstance(); 32 33 Method sm3Method=sm3Digest.getMethod("update", byte[].class,int.class,int.class); 34 sm3Method.invoke(clazz,srcData,0, srcData.length);//此处是一个void方法,如有返回值接收就行38 51 } 52 58 59 public static void main(String[] args)throws Exception { 60 new CustomClassLoader().test(); 61 } 62 63 }