jvm-sandbox DefaultCoreModuleManager
发表时间 2020-04-28  |  浏览量:  |  分类: jvm-sandbox

DefaultCoreModuleManager

简述:模块管理器,实现CoreModuleManager接口。构造该类对象时会加载并初始化所有的系统模块和用户模块。

关键方法

1. fireModuleLifecycle

简述:发布模块生命周期事件。如果模块自身实现了ModuleLifecycle接口,则优先调用该模块的生命周期方法 。然后会通过ModuleLifeCycleEventBus(模块生命周期事件总线)发布该模块的生命周期时间。模块的声明周期时间包括:

  1. LOAD:正在加载
  2. LOAD_COMPLETED:加载完成
  3. UNLOAD:正在卸载
  4. ACTIVE:激活
  5. FROZEN:冻结

2. injectRequiredResource

简述:Module对象的@Resouorce字段注入必要的对象,可注入的对象有:

  1. LoadedClassDataSource:可用查找类和列出所有已加载的类集合
  2. ModuleEventWatcher:将会构造一个新的DefaultModuleEventWatcher对象并注入到字段中,同时也会把新构造的这个watcher对象添加到moduleLifeCycleEventBus
  3. ModuleController:将会构造一个新的DefaultModuleController对象 并注入到字段中,通过该对象可以激活或冻结当前模块(也只能控制当前模块)
  4. ModuleManager:将会构造一个新的DefaultModuleManager对象并注入到字段中,该对象只是对CoreModuleManager的一个包装。通过该对象可以管理整个沙盒内的模块,如:刷新、重置、卸载、激活、冻结模块等。
  5. DefaultConfigInfo:将会构造一个新的DefaultConfigInfo对象并注入到字段中,该对象只是对CoreConfigure的一个包装。可以用于获取配置信息。
  6. EventMonitor:将会构造一个新的DefaultEventMonitor对象并注入到字段中。该对象内部持有EventPool的单例。通过该对象可以获取事件池的统计数据。

3. load

简述:加载并注册模块。

入参:

uniqueId – 模块ID
module – 模块对象
moduleJarFile – 模块所在JAR文件
moduleClassLoader – 负责加载模块的ClassLoader

  1. 构造对应的模块业务对象CoreModule

  2. 调用injectRequiredResource为模块业务对象注入需要的资源

  3. 调用fireModuleLifecycle发布模块业务对象的LOAD事件
  4. 设置模块业务对象的loaded为true
  5. 根据模块对象的@Information注解,决定是否在加载后激活该模块,如果是,则调用active方法激活该模块
  6. 将该模块添加到loadedModuleBOMap
  7. 调用fireModuleLifecycle发布模块业务对象的 LOAD_COMPLETED事件

4. unload

简述:卸载并删除注册模块。

入参:

coreModule – 等待被卸载的模块
isForce – 是否强制卸载

  1. 调用fireModuleLifecycle发布模块业务对象的 UNLOAD事件
  2. 调用frozen方法冻结该模块
  3. loadedModuleBOMap中移除该模块
  4. 设置模块业务对象的loaded为false
  5. 调用closeModuleClassLoaderIfNecessary尝试关闭该模块的ClassLoader

5. active

简述:激活模块。

入参:

coreModule – 模块业务对象

  1. 调用fireModuleLifecycle发布模块业务对象的 ACTIVE事件
  2. 调用coreModule.getSandboxClassFileTransformers()获取所有监听器,并激活其中类型为SandboxClassFileTransformer的监听器。激活方法是调用EventListenerHandlers.getSingleton().active(...)
  3. 设置模块业务对象的activated为true

6. frozen

简述:冻结模块。

入参:

coreModule – 模块业务对象
isForce – 是否强制冻结 强制冻结模块将会主动忽略冻结失败情况,强行将模块所有的事件监听行为关闭

  1. 调用fireModuleLifecycle发布模块业务对象的 FROZEN事件
  2. 调用coreModule.getSandboxClassFileTransformers()获取所有监听器,并激活其中类型为SandboxClassFileTransformer的监听器。激活方法是调用EventListenerHandlers.getSingleton().frozen(...)
  3. 设置模块业务对象的activated为false

7. flush

简述:刷新沙箱模块,如果入参isForce为true,则调用forceFlush,否则调用softFlush

8. reset

简述:沙箱重置。

  1. 遍历loadedModuleBOMap,对所有已加载的模块调用unload进行卸载,且指定为强制。
  2. 遍历moduleLibDirArray,对数组对应的所有元素都构建一个新的ModuleJarLoader实例进行加载(内部会构建每个lib对应的模块类加载器)。

9. closeModuleClassLoaderIfNecessary

简述:关闭Module的ClassLoader ,如果ModuleClassLoader所加载上来的所有模块都已经被卸载,则该ClassLoader需要主动进行关闭。

  1. 遍历loadedModuleBOMap,判断要卸载的模块类加载器是否还有被引用,如果没有才执行第二步
  2. 调用模块类加载器的closeIfPossible方法进行关闭

10. softFlush

简述:软刷新,找出有变动的模块文件,有且仅有改变这些文件所对应的模块。

  1. 调用CoreConfigure.getUserModuleLibFilesWithCache获取用户模块加载文件/目录(集合),遍历所有用户模块jar包
  2. 计算用户模块jar包的校验和(checksum)
  3. 找出所有有变动的文件:遍历loadedModuleBOMap,比较已加载的模块中是否有与步骤 2中计算出来的文件校验相匹配的模块,如果有匹配的,则该模块已经加载过,不需要刷新,没有则继续进行
  4. 找出所有待卸载的已加载用户模块: 遍历loadedModuleBOMap,找出所有已加载的模块中的用户模块,并且模块的校验和与步骤2中所计算得到的所有文件的校验和都不匹配(不匹配则说明该模块已经被从用户模块目录下移除,因此需要卸载)
  5. 调用unload方法卸载步骤 4得到的所有已加载的模块
  6. 对步骤3得到的所有jar包都构建一个新的ModuleJarLoader实例进行加载(内部会构建每个lib对应的模块类加载器)

10. forceFlush

简述:强制刷新,对所有已经加载的用户模块进行强行卸载并重新加载。

  1. 遍历loadedModuleBOMap,找出所有已加载的用户模块
  2. 调用unload方法卸载步骤1得到的所有模块
  3. 调用cfg.getUserModuleLibFiles()重新扫描得到所有待加载的用户模块jar包,并对每个jar包都构建一个新的ModuleJarLoader实例进行加载(内部会构建每个lib对应的模块类加载器)

11. InnerModuleJarLoadCallback类

简述:用户模块文件加载回调,内部会调用ProviderManager.loading方法来执行模块Jar文件加载链。

  1. 可以在这个实现中对目标期待加载的模块Jar文件进行解密,签名验证等操作
  2. 如果判定加载失败,可以通过抛出异常的形式中断加载,sandbox将会跳过此模块Jar文件的加载
  3. 整个模块文件的加载为一个链式的加载过程

12. InnerModuleLoadCallback类

简述:用户模块加载回调.

  1. 检查要加载的模块的id是否已经存在于loadedModuleBOMap中,如果有则直接return,不再执行下面的步骤(会导致放弃加载该模块)
  2. 调用providerManager.loading,作用详见InnerModuleJarLoadCallback类的解释
  3. 调用load方法加载模块
关闭