Java 有否 在不预配置类路径类名的情况下,运行态动态装载类及其依赖类的方法?

2023-02-06 14:32:45 +08:00
 matepi

需求:运行态、不重启,动态装载本地 /远程类。

SPI 带类路径类名配置的比较容易做到。OSGi 是不是也类似的搞法?

但如果要求不配置的情况下,此时如果只是装载单个无依赖类(严格说是依赖均已存在的类),也比较容易做到。如果要进一步装载这个无依赖子类的父类啥的,想办法搞搞也能做到。

但难的就是,如何把这个类的所有依赖也装载进来。

想来想去,想到两个办法:

1 、要么就是装载类里面自己先搞个成员,自声明需要依赖的类(但这个就要保证对所有的依赖、依赖的依赖……都要声明出来、挺难保证的);

2 、还有一种就是给个保证 100%覆盖率的对应 Tester 方法或者类内方法,预先加载 Tester 方法,循环处理掉每个 ClassNotFound 异常,做对应依赖的装载(但这个要保证 100%覆盖率、甚至是依赖类的覆盖率也要做到,也是挺容易出问题的)

1705 次点击
所在节点    Java
16 条回复
assiadamo
2023-02-06 14:35:52 +08:00
agent + instrument
matepi
2023-02-06 14:59:58 +08:00
@assiadamo 你说的应该是 instrumentation.appendToSystemClassLoaderSearch 之类的吧?这个也就是 premain 一次性的。进一步的还是要解决问题 1 吧?
assiadamo
2023-02-06 15:08:32 +08:00
嗯,这只是临时热更解决问题,之后还是需要带上改动出版本更新维护的
assiadamo
2023-02-06 15:10:59 +08:00
运行时可以通过 rmi 或 jmx ,去调用 instrumentation 的 api 去替换 class 的字节码
matepi
2023-02-06 15:31:42 +08:00
@assiadamo 我的需求不是临时热更新处理一些临时问题。而是功能特性上,在一些处理本地文件分析的节点、在设计上,就要能够动态加载 节点使用者所提交的类。由于处理文件量很大,设计上必须是把处理逻辑分发到每个节点上,而不是把文件整体提交到专有的处理节点。
registerrr
2023-02-06 15:42:09 +08:00
@matepi 按你这描述,不如让节点使用者单独起一个服务并保证其可用性,让你的服务去调用它,而不是把它化成你的一部分。
aguesuka
2023-02-06 15:46:07 +08:00
osgi 也是配置 require-bundle 才能实现的. 也就是加载整个模块, 并且在模块的 MANIFEST 里指定依赖.
janwarlen
2023-02-06 15:55:52 +08:00
应该不行的吧,java 的类路径相当于 class 的 id 了
可以尝试将类打入 jre ,然后不用 package ,扁平化存放
jdk9 的 jlink 可以自定义 jre 的

不过还不知道有人这么干过,如果成功了踢我一脚
matepi
2023-02-06 16:18:52 +08:00
@registerrr 上面回复中也提到了:调用的入参是一个大文件,做的功能大文件的数据处理;如果变为远程调用、以服务方式 把大文件整体传输过去,效率上不能行。对大文件此时的设计,需要是分发计算,而不是分发数据。
2han9wen71an
2023-02-06 17:29:17 +08:00
你可能需要的是 URLClassLoader
assiadamo
2023-02-06 19:06:49 +08:00
为了实现不停机的需求的话,可不可以使用脚本,比如 JavaScript 或 Lua
pursuer
2023-02-06 19:07:57 +08:00
如果只要求标准 jre 平台,可以重载 classloader 的 findClass ,调用 defineClass 就行。
如果要 android 平台则需要返回一个由另一个子 classloader 加载的对应类。
第二种方法我之前开发一个框架的时候写过类似的东西,可以参考一下
https://github.com/partic2/xplatj/blob/main/commonj/src/main/java/xplatj/javaplat/pursuer/lang/IntegratedClassLoader.java
aristotll
2023-02-06 22:12:08 +08:00
Groovy 脚本
ql562482472
2023-02-07 09:35:59 +08:00
我觉得你可以写自己的类加载器,当被加载时,如果符合某些特征就进行初始化,否则就光加载连接
nekoneko
2023-02-07 21:07:19 +08:00
Groovy
Aresxue
2023-02-14 10:46:22 +08:00
动态装载的类也是有它的开发环境和过程的,可以考虑在开发过程中把这个类使用的类打包为一个新的 jar ,装载时使用自定义的 classloader 去 load 这个 jar ,至于实际实现的话可以用静态分析( import 的递归和对反射的分析)和动态分析(限定类的指定运行方法,开发时自己 run 一遍将 jvm 中所有类都记下来,将 jdk 和已有依赖的类排除其它的类合并为一个新的 jar ),这东西简单想想还行实际做起来确实挺复杂

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/913605

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX