需求:运行态、不重启,动态装载本地 /远程类。
SPI 带类路径类名配置的比较容易做到。OSGi 是不是也类似的搞法?
但如果要求不配置的情况下,此时如果只是装载单个无依赖类(严格说是依赖均已存在的类),也比较容易做到。如果要进一步装载这个无依赖子类的父类啥的,想办法搞搞也能做到。
但难的就是,如何把这个类的所有依赖也装载进来。
想来想去,想到两个办法:
1 、要么就是装载类里面自己先搞个成员,自声明需要依赖的类(但这个就要保证对所有的依赖、依赖的依赖……都要声明出来、挺难保证的);
2 、还有一种就是给个保证 100%覆盖率的对应 Tester 方法或者类内方法,预先加载 Tester 方法,循环处理掉每个 ClassNotFound 异常,做对应依赖的装载(但这个要保证 100%覆盖率、甚至是依赖类的覆盖率也要做到,也是挺容易出问题的)
1
assiadamo 2023-02-06 14:35:52 +08:00
agent + instrument
|
2
matepi OP @assiadamo 你说的应该是 instrumentation.appendToSystemClassLoaderSearch 之类的吧?这个也就是 premain 一次性的。进一步的还是要解决问题 1 吧?
|
3
assiadamo 2023-02-06 15:08:32 +08:00
嗯,这只是临时热更解决问题,之后还是需要带上改动出版本更新维护的
|
4
assiadamo 2023-02-06 15:10:59 +08:00
运行时可以通过 rmi 或 jmx ,去调用 instrumentation 的 api 去替换 class 的字节码
|
5
matepi OP @assiadamo 我的需求不是临时热更新处理一些临时问题。而是功能特性上,在一些处理本地文件分析的节点、在设计上,就要能够动态加载 节点使用者所提交的类。由于处理文件量很大,设计上必须是把处理逻辑分发到每个节点上,而不是把文件整体提交到专有的处理节点。
|
6
registerrr 2023-02-06 15:42:09 +08:00
@matepi 按你这描述,不如让节点使用者单独起一个服务并保证其可用性,让你的服务去调用它,而不是把它化成你的一部分。
|
7
aguesuka 2023-02-06 15:46:07 +08:00
osgi 也是配置 require-bundle 才能实现的. 也就是加载整个模块, 并且在模块的 MANIFEST 里指定依赖.
|
8
janwarlen 2023-02-06 15:55:52 +08:00
应该不行的吧,java 的类路径相当于 class 的 id 了
可以尝试将类打入 jre ,然后不用 package ,扁平化存放 jdk9 的 jlink 可以自定义 jre 的 不过还不知道有人这么干过,如果成功了踢我一脚 |
9
matepi OP @registerrr 上面回复中也提到了:调用的入参是一个大文件,做的功能大文件的数据处理;如果变为远程调用、以服务方式 把大文件整体传输过去,效率上不能行。对大文件此时的设计,需要是分发计算,而不是分发数据。
|
10
2han9wen71an 2023-02-06 17:29:17 +08:00
你可能需要的是 URLClassLoader
|
11
assiadamo 2023-02-06 19:06:49 +08:00 via Android
为了实现不停机的需求的话,可不可以使用脚本,比如 JavaScript 或 Lua
|
12
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 |
13
aristotll 2023-02-06 22:12:08 +08:00
Groovy 脚本
|
14
ql562482472 2023-02-07 09:35:59 +08:00
我觉得你可以写自己的类加载器,当被加载时,如果符合某些特征就进行初始化,否则就光加载连接
|
15
nekoneko 2023-02-07 21:07:19 +08:00
Groovy
|
16
Aresxue 2023-02-14 10:46:22 +08:00
动态装载的类也是有它的开发环境和过程的,可以考虑在开发过程中把这个类使用的类打包为一个新的 jar ,装载时使用自定义的 classloader 去 load 这个 jar ,至于实际实现的话可以用静态分析( import 的递归和对反射的分析)和动态分析(限定类的指定运行方法,开发时自己 run 一遍将 jvm 中所有类都记下来,将 jdk 和已有依赖的类排除其它的类合并为一个新的 jar ),这东西简单想想还行实际做起来确实挺复杂
|