JVM类加载器应用之多版本库支持

问题

  开发过程中,咱们经常需要使用不同的库版本,而这些版本又不是向后兼容的,或者出于某种原因需要支持同一库的多个版本。

  在这种情况下,默认的类加载器已经是不支持了,因为 loadClass 方法只加载一次特定的类,之后所有的加载请求就直接返回现有 Class 实例的引用了。

解决办法

  在这种情况下,可以自定义一个类加载器,用这个具有优先设置的加载器加载需要的库就可以了。

基本代码如下:

复制代码
 1 import java.net.URL;
 2 import java.net.URLClassLoader;
 3 import java.util.List;
 4 
 5 public class CustomClassLoader extends ClassLoader {
 6     private ChildClassLoader childClassLoader;
 7 
 8     public CustomClassLoader(List<URL> classpath) {
 9 
10         super(Thread.currentThread().getContextClassLoader());
11         URL[] urls = classpath.toArray(new URL[classpath.size()]);
12         childClassLoader = new ChildClassLoader(urls, new DetectClass(this.getParent()));
13     }
14 
15     @Override
16     protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
17         try {
18             return childClassLoader.findClass(name);
19         } catch(ClassNotFoundException e) {
20             return super.loadClass(name, resolve);
21         }
22     }
23 
24     private static class ChildClassLoader extends URLClassLoader {
25         private DetectClass realParent;
26 
27         public ChildClassLoader(URL[] urls, DetectClass realParent) {
28             super(urls, null);
29             this.realParent = realParent;
30         }
31 
32         @Override
33         public Class<?> findClass(String name) throws ClassNotFoundException {
34             try {
35                 Class<?> loaded = super.findLoadedClass(name);
36                 if(loaded != null) return loaded;
37                 return super.findClass(name);
38             } catch(ClassNotFoundException e) {
39                 return realParent.loadClass(name);
40             }
41         }
42     }
43 
44     private static class DetectClass extends ClassLoader {
45         public DetectClass(ClassLoader parent) {
46             super(parent);
47         }
48 
49         @Override
50         public Class<?> findClass(String name) throws ClassNotFoundException {
51             return super.findClass(name);
52         }
53     }
54 }
复制代码

All Done!

  至此就算完成了,通过这种解决办法就可以使单个 jvm 中有多个库版本,或者同一个版本中由于静态变量导致的多实例共存了。

注意:有些库中可能还加载了一些 classpath 下的资源文件,这种情况下就按需要覆盖 getResource 等方法就可以了。

 

posted @   洛神灬殇  阅读(328)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示