alibaba / one-java-agent

Apache License 2.0
551 stars 118 forks source link

插件之间service共享机制 #21

Open hengyunabc opened 3 years ago

hengyunabc commented 3 years ago

有两种思路:

假定 one java agent本身启动好后,叫 container。

简单的Service机制

  1. 提供最简单的方案,每个插件自己启动后,向 container 注册某些类,或者注册一个handler,用来判断某个类是否应该从我这里加载。 然后插件方在使用时,要先 getService(serviceClassName),得到一个对象,然后再强转,得到真正的 serviceImpl,然后再调用。

    这种方式很可能工作不了。另外,插件本身编程时也可能会有问题。

完整的类隔离方案,类似 pandora/osgi

pandora的方式

pandora的方式有一些缺点。

pandora是把所有的插件的导出类放到一个 cache map里。 这个实现导致类加载可能会提前,也会加载不必要的类。 可以改用lazy init方式加载类。但这个方案本身终究不是很合理。

pandora不支持导出 resources 。支持这个会导致加载效率不可避免的降低。 或者可以做一些限定。比如只允许导出固定名称的resource,或者只允许导出固定 prefix 的resource。 这样子在 getResources 先做一个前缀判断??

轻量级osgi的方式

完整的osgi太复杂了,要做一个剪裁。但剪裁的度在哪里,不好把握。


提供类共享机制,会有一个比较大的问题: 插件不能随意unistall了。因为 class 对象会被其它的插件,或者container本身持有。

是否对于类共享的插件,不再支持 uninstall ?

hengyunabc commented 3 years ago

共享类带来的问题

共享类之后,如果还想要做到插件可以重复 install/uninstall 会非常的复杂。

我们先考虑一种最简单的情况。

比如插件 A有 HelloService,内部有一个实现类HelloServiceImpl;然后插件B在代码里非常简单的引用这个类:

HelloService helloService = ServiceRef.getService(HelloService.class);
System.out.println(helloService.hello());

那么这时:

那么现在:


这个在OSGI里是可以工作的,答案是:

我们可以看到,就是这么简单一个实例,就非常的复杂。并且在这种情况下 ClassLoaderA1 是不能被回收的。因为HelloService.class 还一直被引用。

hengyunabc commented 3 years ago

测试类共享能否卸载干净时,可以用 arthas vmtool的 forceGc来检验。