美文网首页
动态加载jar包的一个坑

动态加载jar包的一个坑

作者: 西三旗靓仔 | 来源:发表于2019-07-13 15:34 被阅读0次

具体场景

最近项目中基于jarslink做实时算法的加载,为了方便jar包更新测试,我们把jar包开发完后以snapshot版本推送到maven中央仓库中。jarslink查询器根据配置动态从maven仓库加载算法jar包及其依赖。为了在jar包发生改变时动态刷新,代码中农将对应jar包的md5作为版本version的一部分。在代码发生修改时,重新推送jar包到maven仓库,代码中的maven加载器动态刷新插件jar包,并重新加载子容器,此时意外发生了,jvm crash,多次试验,java虚拟机不是crash就是报ClassNotFoundException,原因为何?这就是本文要说的:不要在java虚拟机运行时替换正在使用的jar包!

具体原因探索

既然jar包名称和原来的一模一样,jar包里面的类也一致,为什么jvm就加载不到这个jar包里面的类呢?要回答这个问题,我们可以先通过lsof来查看一下某个java进程打开的文件句柄:

lsof | grep java 6213

20190322225128453.png

我们可以看到,这个java进程维护了多个jar包文件的句柄。通过这个,我们可以想到应该是jvm在运行中维护了这些jar包的inputstream,在需要某个类的时候,就从这些inputstream中获取某个类的字节码然后加载。这个维护的inputstream是针对原先旧jar包打开的输入流,如果这时jar包被替换了,那么对应的句柄就会失效,ClassPathXmlApplication在去加载这个jar包并初始化容器便会报错了!

另外我还发现,你把这个jar包删除,但是拷贝一模一样的jar包回去,代码不会出现任何问题,jvm对应的jar包是mem内存映射的方式打开对应的jar包文件的,只要文件内容完全相同(字节数没变),那么就不会出现类找不好或者非法内存访问造成jvm崩溃。

总结

其实,如果jvm程序后面在运行时不需要再从这个jar包加载什么类的话,就算替换了jar包也不会造成什么影响。但是应该没有哪个程序员敢说对要维护的java服务是了如指掌的,加上jvm是按需加载的。我们很难断定jvm在运行过程中就不会再从我们要替换的这个jar包中加载类了。因此,再做jarlink插件加载时,最好不同的子容器之间不要共用同一个jar包,免得一个子模块刷新时,对应的jar包发生SNAPSHOT版本更新,造成后面代码运行崩溃。线上最好使用release版本,并且将jar包拷贝到不同子模块目录下,做jar包之间的物理隔离。

相关文章

  • 动态加载jar包的一个坑

    具体场景 最近项目中基于jarslink做实时算法的加载,为了方便jar包更新测试,我们把jar包开发完后以sna...

  • 动态加载jar包

    概述 前段时间在开发外设驱动程序时,涉及到了动态加载jar包的知识,于是开始学习了下。这里主要是完成客户端驱动ja...

  • Android动态加载

    Dload 一个动态加载jar包的实例 github:https://github.com/andoop/Dloa...

  • Android动态加载jar包

    前言: 云端架构提出一个边缘计算的的概念,就是云端提供一个或者多个动态的jar包,里面包含了一些计算方法,需要An...

  • 动态加载jar、dex 热更新

    Android动态加载jar,dex,apk文件 坑 1.程序没给分配sd卡权限 mContext.getClas...

  • JVM之类加载机制

    Android类加载器 理解类加载 Eclipse使用第三方的插件其实就是动态加载Jar包里的Class字节码进行...

  • Android类加载器

    JVM之类加载机制 理解类加载 Eclipse使用第三方的插件其实就是动态加载Jar包里的Class字节码进行工作...

  • 使用classloader动态加载jar包

  • gradle加载依赖的几种方式

    基本方式 加载本地jar包 加载本地某个目录下的所有jar包 排除传递依赖中的某些依赖

  • 动态加载

    定义 加载so文件 加载dex/jar/apk文件 动态加载的基础就是classloader,一个app中至少需要...

网友评论

      本文标题:动态加载jar包的一个坑

      本文链接:https://www.haomeiwen.com/subject/sgcmkctx.html