sdk项目的eclipse插件中需要用到tools.jar,使用tools.jar中com.sun.tools.attach.VirtualMachine的loadAgent方法实现运行时动态加载自己的代理jar。默认equinox中没有加载tools.jar且插件中不能打包tools.jar,搜了一圈没有啥好办法,看来只能通过给eclipse plugin写fragment的方式来实现runtime加载tools.jar中的类。

1、ClassLoaderDelegateHook控制类加载原理
Eclipse的内核使用OSGI框架,而Equinox是OSGI R4的一个实现。Equinox的设计非常经典,其在扩展方面提供了很多的支持,同样包括类加载方面的控制,除了通过标准的org.osgi.framework.bootdelegation以及equinox提供的osgi.parentClassLoader这两个属性来简单的控制类加载之外,还可通过实现ClassLoaderDelegateHook来更为灵活的控制类加载。

1.1、原理
EclipseStarter的构造器中创建通过获取HookRegistry来增加自行实现的ClassLoaderDelegateHook类,在HookRegistry的initialize方法中,会去加载配置的osgi.hook.configurators、osgi.hook.configurators.include和osgi.hook.configurators.exclude三个属性值或指定的hookconfigurators.properties文件,最后合并形成需要加载执行的HookConfigurator类;因此,只用在自行实现的ClassLoaderDelegateHook类上再增加HookConfigurator接口的实现,并将其注册到HookRegistry中,最后在osgi.hook.configurators中配置这个类即可;由于equinox内部已经有配置了一些HookConfigurator的,要么就需要把增加的HookConfigurator加到equinox jar的hookconfigurators.properties中。

1.2、ClassLoaderDelegateHook实现方法
我们通过开发equinox的plugin fragment来实现上面的想法,plguin fragment继承equinox的ClassLoaderDelegateHook实现类并增加自定义的ClassLoaderDelegateHook实现类(在其中控制我们需要的tools.jar中类的加载,自定义的ClassLoaderDelegateHook实现类配置在fragment的hookconfigurators.properties中);

2、Equinox的classloader查找和加载class的顺序
Equinox的ClassLoadingHook在createClassLoader后就完成了ClassLoader的创建,开始加载class,其顺序如下;
1)判断是否交由parent classloader去完成加载
2) 尝试调用Equinox提供的ClassLoaderDelegateHook的扩展来加载
3) 判断是否在import-package中,如在则交由相应的PackageSource去加载
4) 尝试从require-bundle中加载
5) 尝试从当前Bundle中加载
6) 尝试从DynamicImport-Package中加载
7) 再次尝试调用Equinox提供的ClassLoaderDelegateHook的扩展来加载
8) 尝试使用eclipse的buddy机制来加载
9) 判断一定的条件,如符合则从parent classloader中加载
10)经过以上所有步骤后,仍然未找到需要加载的class,则抛出ClassNotFoundException

因此我们将tools.jar中class的加载逻辑放到ClassLoaderDelegateHook接口的postFindClass方法中实现;

3、实现细节
3.1、ClassLoaderDelegateHook类实现

3.2、添加hookconfigurators.properties

3.3、DONE