如何使用 ClassLoader 隔离不同版本的 jar 包?

众所周知,因为classloader的隔离机制,一个jvm进程可以同时加载两个同名的class,但是如何使用这两个class呢。只能通过拿到class的引用,反射调用吗?

问题背景:系统A接入多家渠道,需要用到渠道的SDK,但是各个渠道的SDK都依赖了相同的加解密class,例如 org.apache.Cipher,但是版本都不一样。如何让这些SDK在一个JVM进程中无障碍使用。

场景和stackeroverflow这个问题一样:Java Classloader - how to reference different versions of a jar


回答:

这时候 URLClassLoader 就派上用场了。下面是一个例子

public class ChannelCipherManager implements Closeable {

private final Map<String, URLClassLoader> cipherClassLoaders = new HashMap<>();

/**

* 注册渠道自己的 cipher jar 包

*/

public void registerCipherJar(String channel, File cipherJar) throws MalformedURLException {

URLClassLoader cipherClassLoader = new URLClassLoader(new URL[]{cipherJar.toURI().toURL()});

cipherClassLoaders.put(channel, cipherClassLoader);

}

/**

* 根据渠道获得对应的 cipher 对象

*/

@SuppressWarnings("unchecked")

public Cipher getCipher(String channel) throws ClassNotFoundException {

if (!cipherClassLoaders.containsKey(channel)) {

// 或者注册一个默认的,找不到渠道就返回该默认值也行

throw new IllegalArgumentException("Channel '" + channel + "' not registered");

}

Class<Cipher> cipherClass = (Class<Cipher>)

cipherClassLoaders.get(channel).loadClass("org.apache.Cipher");

return createCipherInstance(cipherClass);

}

/**

* 创建 Cipher 实例对象

*/

private Cipher createCipherInstance(Class<Cipher> cipherClass) {

return null; // TODO 这个交给你自己实现

}

/**

* 根据需要释放资源

*/

@Override

public void close() throws IOException {

this.cipherClassLoaders.values().forEach(cl -> {

try {

cl.close();

} catch (IOException e) {

// ignore error

}

});

}

}

使用方法:

public static void main(String[] args) throws Exception {

ChannelCipherManager ccm = new ChannelCipherManager();

ccm.registerCipherJar("channel1", new File("lib-ch1/cipher.jar"));

ccm.registerCipherJar("channel2", new File("lib-ch2/cipher.jar"));

ccm.registerCipherJar("channel3", new File("lib-ch3/cipher.jar"));

Cipher cipher = ccm.getCipher("channel2");

// ...

}


回答:

如果你最终加密的结果,和版本无关,这你用哪个都没关系,如果是最终结果有差异,自定义classloader,加载外置jar也是可以的


回答:

这两个类的类加载器不一样,调用对应的类加载器就能获取到类

以上是 如何使用 ClassLoader 隔离不同版本的 jar 包? 的全部内容, 来源链接: utcz.com/p/944649.html

回到顶部