使用URLClassLoader加载不同Jar包中的相同包名相同类名的类
开发中会遇到这种情况,使用一项功能需要依赖jar,然而一段时间后这些包升级,包名和类名均不变的情况下功能发生变化。旧的jar依然需要使用,而新功能却需要使用新升级的jar。这时如果依赖两个包,使用时会造成冲突。因此需要进行jar隔离。有很多的隔离框架可以使用,如jarlinks。本文将演示通过URLClassLoader加载器来进行隔离的基本方法,而实应用中的的一些隔离框架中也会看到此种方式的使用。
首先原有系统内部依赖version782.jar包,并用到该包中的RequestHead类。而此时又希望用到version713.jar包中的RequestHead类。直接增加maven依赖会产生冲突,这里通过URLClassLoader进行加载。
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.serializer.SerializerFeature
import xxx.RequestHead
import org.apache.commons.codec.binary.Hex
import java.io.File
import java.lang.reflect.Method
import java.net.URL
import java.net.URLClassLoader
public class ClassLoadTest {
public static void main(String[] args) throws Exception {
URL url = new File("/version713.jar").toURI().toURL()
// 创建URLClassLoader,并设置父加载器为null,这样通过加载器加载
// 类时就不会通过父加载器去通过classpath中加载version782.jar
// 中的RequestHead
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, null)
// 加载version713.jar包中的RequestHead类
Class<?> clz = urlClassLoader.loadClass("xxx.RequestHead")
// 加载序列化工具类,由于要通过反射调用ProtoBufferCore中的方法
// 而且需要指定Class参数,这个参数需要与ProtoBufferCore使用相同
// 的类加载器,因此后续加载参数CtripBusinessBean
Class<?> pb = urlClassLoader.loadClass("xxx.ProtoBufferCore")
// 加载参数CtripBusinessBean,调用ProtoBufferCore方法时使用
Class<?> ctripBizBean = urlClassLoader.loadClass("xxx.CtripBusinessBean")
RequestHead head782 = new RequestHead()
Object head713 = clz.newInstance()
Object pbObject = pb.newInstance()
System.out.println(pbObject)
System.out.println(JSON.toJSONString(head713, SerializerFeature.WriteNullStringAsEmpty))
System.out.println(JSON.toJSONString(head782, SerializerFeature.WriteNullStringAsEmpty))
clz.getField("appId").set(head713,"999111")
// 这里进行方法调用时,执行参数上文中加载的ctripBizBean,
// 这样才能保证正确调用
Method toByteArrayMethod = pb.getMethod("toByteArray",ctripBizBean)
String hex = Hex.encodeHexString((byte[]) toByteArrayMethod.invoke(pbObject,head713))
System.out.println(hex)
java虚拟机规范5.3节
使用URLClassLoader加载不同Jar包中的相同包名相同类名的类开发中会遇到这种情况,使用一项功能需要依赖jar,然而一段时间后这些包升级,包名和类名均不变的情况下功能发生变化。旧的jar依然需要使用,而新功能却需要使用新升级的jar。这时如果依赖两个包,使用时会造成冲突。因此需要进行jar隔离。有很多的隔离框架可以使用,如jarlinks。本文将演示通过URLClassLoader加...
以下是代码实验public class Test { public static void main(String[] args) throws Exception{ //当前Test类所在目录(包)的a.txt
System.out.println(Test.class.getResource("a.txt"));
//当前项目的根目录的a.txt
然后 之前呢, 也碰到了一些 依赖的相关问题
1.异常:Class net.sf.cglib.core.DebuggingClassWriter overrides final method visit
2.tomcat启动内存堆栈溢出ASN1EncodableVector,DEREncodableVector循环依赖
然而 这些问题都需要确定一些事情, 才能够继续...
public class MyClassLoader {
public static final String WEB_ROOT = System.getProperty("user.dir") +
File.separat