java读取远程jar的解决方案

需求背景

用户将自己写的java代码打成jar包,然后在A项目的前端页面上上传,后台会将jar包通过http方式上传到B项目。

现在有个需求是:A项目某业务逻辑会用到B项目的jar包,执行其中的方法并拿到方法返回结果。

需求的难点在于:

A项目如何远程执行B项目中jar包中的方法呢?

URLClassLoader远程加载

java中提供了URLClassLoader类来加载外部jar,并可以执行其中的方法,
参考 记录——JAVA动态加载外部JAR,并调用方法以及卸载关闭打开的外部JAR

这篇博文介绍的是如何加载本地jar,而我们的jar是放在远程的,不过URLClassLoader也可以直接加载远程jar,参考 URLClassLoader加载远程jar包

于是A项目采用的是 URLClassLoader加载远程jar包的方式。

URLClassLoader的内存溢出陷阱

A项目的并发量很高,每条数据过来都要去执行jar的方法。
jar包如果很小,性能可能不受太大影响。
jar包本身就很大时,远程读取的速度会更慢,性能会很感人。

所以A项目启动时,会提前将通过URLClassLoader加载的Class对象缓存在内存中,后续业务处理直接从内存中取出Class对象。

伪代码如下

Class clz = urlClassLoader.loadClass("com.sf.iotp.util.ParseUtil");
map.put(jarName, clz);

但是这样有个限制,我们不能通过urlClassLoader.close()来关闭外部jar,否则即使将Class对象缓存在内存中,执行时依旧会报找不到类的异常。

通过上述做法性能是快了,但是由于没有通过urlClassLoader.close()来关闭外部jar,可能存在内存溢出的陷阱(目前我没遇到过,但是存在这种可能性)。具体参考这篇博文 Java动态编译优化——URLClassLoader 内存泄漏问题解决

折中方案

既想通过urlClassLoader.close()来关闭外部jar从而防止内存溢出,又想提升读取性能,该怎么做呢?

我们最后用的一个方案是:

项目启动时,提前下载所有远程jar到本地目录(服务器的目录);
当数据过来时,后台通过URLClassLoader本地加载的方式来加载下载好的jar,此时就可以使用urlClassLoader.close()。本地加载速度远远大于远程加载速度;
下次项目再启动时,如果服务器本地目录有jar,说明之前下载过,此时无需重新下载。

这种方案,第一次启动时由于要下载,所以会慢点,但后续就快多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值