需求:运行态、不重启,动态装载本地 /远程类。
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 ),这东西简单想想还行实际做起来确实挺复杂 |