JVM SandBox源码解析(一):启动时初始化、启动时加载模块、ModuleHttpServlet进行Http路由
4、增强目标类
自定义模块示例:
@MetaInfServices(Module.class)
@Information(id = "TestControllerInterceptor", isActiveOnLoad = false)
public class TestControllerInterceptor extends ModuleLifecycleAdapter implements Module {
@Resource
private ModuleEventWatcher moduleEventWatcher;
@Override
public void loadCompleted() {
new EventWatchBuilder(moduleEventWatcher)
.onClass("com.ppdai.demo.web.TestController")
.onBehavior("hello").withEmptyParameterTypes()
.onWatch(new AdviceListener() {
@Override
protected void before(Advice advice) throws ProcessControlException {
System.out.println("sandbox interceptor success");
}
});
}
}
1)、重写的loadCompleted()
何时被调用
模块加载过程中,会调用DefaultCoreModuleManager的load()
方法
public class DefaultCoreModuleManager implements CoreModuleManager {
/**
* 加载并注册模块
* <p>1. 如果模块已经存在则返回已经加载过的模块</p>
* <p>2. 如果模块不存在,则进行常规加载</p>
* <p>3. 如果模块初始化失败,则抛出异常</p>
*
* @param uniqueId 模块ID
* @param module 模块对象
* @param moduleJarFile 模块所在JAR文件
* @param moduleClassLoader 负责加载模块的ClassLoader
* @throws ModuleException 加载模块失败
*/
private synchronized void load(final String uniqueId,
final Module module,
final File moduleJarFile,
final ModuleJarClassLoader moduleClassLoader) throws ModuleException {
if (loadedModuleBOMap.containsKey(uniqueId)) {
logger.debug("module already loaded. module={};", uniqueId);
return;
}
logger.info("loading module, module={};class={};module-jar={};",
uniqueId,
module.getClass().getName(),
moduleJarFile
);
// 实例化模块信息
final CoreModule coreModule = new CoreModule(uniqueId, moduleJarFile, moduleClassLoader, module);
// 注入@Resource资源
injectResourceOnLoadIfNecessary(coreModule);
callAndFireModuleLifeCycle(coreModule, MODULE_LOAD);
// 设置为已经加载
coreModule.markLoaded(true);
// 如果模块标记了加载时自动激活,则需要在加载完成之后激活模块
markActiveOnLoadIfNecessary(coreModule);
// 注册到模块列表中
loadedModuleBOMap.put(uniqueId, coreModule);
// 通知生命周期,模块加载完成
callAndFireModuleLifeCycle(coreModule, MODULE_LOAD_COMPLETED);
}
load()
方法最后会调用callAndFireModuleLifeCycle()
方法来通知生命周期,模块加载完成,此时传入的生命周期状态为MODULE_LOAD_COMPLETED(模块加载完成)
public class DefaultCoreModuleManager implements CoreModuleManager {
/*
* 通知模块生命周期
*/
private void callAndFireModuleLifeCycle(final CoreModule coreModule, final ModuleLifeCycleType type) throws ModuleException {
if (coreModule.getModule() instanceof ModuleLifecycle) {
final ModuleLifecycle moduleLifecycle = (ModuleLifecycle) coreModule.getModule();
final String uniqueId = coreModule.getUniqueId();
switch (type) {
case MODULE_LOAD: {
try {
moduleLifecycle.onLoad();
} catch (Throwable throwable) {
throw new ModuleException(uniqueId, MODULE_LOAD_ERROR, throwable);
}
break;
}
case MODULE_UNLOAD: {
try {
moduleLifecycle.onUnload();
} catch (Throwable throwable) {
throw new ModuleException(coreModule.getUniqueId(), MODULE_UNLOAD_ERROR, throwable);
}
break;
}
case MODULE_ACTIVE: {
try {
moduleLifecycle.onActive();
} catch (Throwable throwable) {
throw new ModuleException(coreModule.getUniqueId(), MODULE_ACTIVE_ERROR, throwable);
}
break;
}
case MODULE_FROZEN: {
try {
moduleLifecycle.onFrozen();
} catch (Throwable throwable) {
throw new ModuleException(coreModule.getUniqueId(), MODULE_FROZEN_ERROR, throwable);
}
break;
}
}// switch
}
// 这里要对LOAD_COMPLETED事件做特殊处理
// 因为这个事件处理失败不会影响模块变更行为,只做简单的日志处理
if (type == MODULE_LOAD_COMPLETED
&& coreModule.getModule() instanceof LoadCompleted) {
try {
// 调用模块的loadCompleted()方法
((LoadCompleted) coreModule.getModule()).loadCompleted();
} catch (Throwable cause) {
logger.warn("loading module occur error when load-completed. module={};", coreModule.getUniqueId(), cause);
}
}
}
callAndFireModuleLifeCycle()
方法中,当生命周期状态为MODULE_LOAD_COMPLETED时,会调用模块的loadCompleted()
方法,实际为自定义模块中重写的loadCompleted()
方法
2)、IBuildingForBehavior的onWatch()
方法
自定义模块中最后调用onWatch()
方法,该方法实现如下:
private class BuildingForBehavior implements IBuildingForBehavior {
@Override
public EventWatcher onWatch(AdviceListener adviceListener) {
return build(new AdviceAdapterListener(adviceListener), null, BEFORE, RETURN, THROWS, IMMEDIATELY_RETURN, IMMEDIATELY_THROWS);
}
onWatch()
中调用了build()
方法:
public class EventWatchBuilder {
private EventWatcher build(final EventListener listener,
final Progress progress,
final Event.Type... eventTypes) {
// 调用moduleEventWatcher.watch去修改目标类的字节码
final int watchId = moduleEventWatcher.watch(
// 创建事件观察条件、过滤类和方法
toEventWatchCondition(),
listener,
progress,
eventTypes
);
return new EventWatcher() {
final List<Progress> progresses = new ArrayList<Progress>();
@Override
public int getWatchId() {
return watchId;
}
@Override
public IBuildingForUnWatching withProgress(Progress progress) {
if (null != progress) {
progresses.add(progress);
}
return this;
}
@Override
public void onUnWatched() {
moduleEventWatcher.delete(watchId, toProgressGroup(progresses));
}
};
}
build()
方法中调用ModuleEventWatcher的watch()
方法去修改目标类的字节码
public class DefaultModuleEventWatcher implements ModuleEventWatcher {
@Override
public int watch(final EventWatchCondition condition,
final EventListener listener,
final Progress progress,
final Event.Type... eventType) {
return watch(toOrGroupMatcher(condition.getOrFilterArray()), listener, progress, eventType);
}
// 这里是用matcher重制过后的watch
private int watch(final Matcher matcher,
final EventListener listener,
final Progress progress,
final Event.Type... eventType) {
// 使用一个全局的AtomicInteger生成watchId
final int watchId = watchIdSequencer.next();
// 给对应的模块追加ClassFileTransformer
final SandboxClassFileTransformer sandClassFileTransformer = new SandboxClassFileTransformer(
watchId, coreModule.getUniqueId(), matcher, listener, isEnableUnsafe, eventType, namespace);
// 注册到CoreModule中
coreModule.getSandboxClassFileTransformers().add(sandClassFileTransformer);
// 这里addTransformer后,接下来引起的类加载都会经过sandClassFileTransformer
inst.addTransformer(sandClassFileTransformer, true);
// 查找需要渲染的类集合
final List<Class<?>> waitingReTransformClasses = classDataSource.findForReTransform(matcher);
logger.info("watch={} in module={} found {} classes for watch(ing).",
watchId,
coreModule.getUniqueId(),
waitingReTransformClasses.size()
);
int cCnt = 0, mCnt = 0;
// 进度通知启动
beginProgress(progress, waitingReTransformClasses.size());
try {
// 应用JVM
reTransformClasses(watchId,waitingReTransformClasses, progress);
// 计数
cCnt += sandClassFileTransformer.getAffectStatistic().cCnt();
mCnt += sandClassFileTransformer.getAffectStatistic().mCnt();
// 激活增强类
if (coreModule.isActivated()) {
final int listenerId = sandClassFileTransformer.getListenerId();
EventListenerHandler.getSingleton()
.active(listenerId, listener, eventType);
}
} finally {
finishProgress(progress, cCnt, mCnt);
}
return watchId;
}
/*
* 形变观察所影响的类
*/
private void reTransformClasses(
final int watchId,
final List<Class<?>> waitingReTransformClasses,
final Progress progress) {
// 需要形变总数
final int total = waitingReTransformClasses.size();
// 如果找不到需要被重新增强的类则直接返回
if (CollectionUtils.isEmpty(waitingReTransformClasses)) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("reTransformClasses={};module={};watch={};",
waitingReTransformClasses, coreModule.getUniqueId(), watchId);
}
int index = 0;
for (final Class<?> waitingReTransformClass : waitingReTransformClasses) {
index++;
try {
if (null != progress) {
try {
progress.progressOnSuccess(waitingReTransformClass, index);
} catch (Throwable cause) {
// 在进行进度汇报的过程中抛出异常,直接进行忽略,因为不影响形变的主体流程
// 仅仅只是一个汇报作用而已
logger.warn("watch={} in module={} on {} report progressOnSuccess occur exception at index={};total={};",
watchId, coreModule.getUniqueId(), waitingReTransformClass,
index - 1, total,
cause
);
}
}
inst.retransformClasses(waitingReTransformClass);
logger.info("watch={} in module={} single reTransform {} success, at index={};total={};",
watchId, coreModule.getUniqueId(), waitingReTransformClass,
index - 1, total
);
} catch (Throwable causeOfReTransform) {
logger.warn("watch={} in module={} single reTransform {} failed, at index={};total={}. ignore this class.",
watchId, coreModule.getUniqueId(), waitingReTransformClass,
index - 1, total,
causeOfReTransform
);
if (null != progress) {
try {
progress.progressOnFailed(waitingReTransformClass, index, causeOfReTransform);
} catch (Throwable cause) {
logger.warn("watch={} in module={} on {} report progressOnFailed occur exception, at index={};total={};",
watchId, coreModule.getUniqueId(), waitingReTransformClass,
index - 1, total,
cause
);
}
}
}
}//for
}
DefaultModuleEventWatcher的watch()
方法核心流程如下:
- 使用一个全局的AtomicInteger生成watchId
- 给对应的模块追加SandboxClassFileTransformer
- 将SandboxClassFileTransformer注册到CoreModule中
- 调用Instrumentation的
addTransformer()
方法,接下来引起的类加载都会经过SandClassFileTransformer - 查找需要渲染的类集合
- 调用
reTransformClasses()
方法,实际调用了Instrumentation的retransformClasses()
方法,对JVM已经加载的类重新触发类加载 - 判断自定义模块的默认状态是否为激活,如果是,激活增强类
JVM SandBox字节码增强和撤销流程流程图如下:
字节码增强时,通过Instrumentation的addTransformer(ClassFileTransformer transformer)方法注册一个ClassFileTransformer,从此之后的类加载都会被ClassFileTransformer拦截,然后调用Instrumentation的retransformClasses(Class<?>… classes)对JVM已经加载的类重新触发类加载,类加载时会被ClassFileTransformer拦截
字节码增强撤销时,通过Instrumentation的removeTransformer(ClassFileTransformer transformer)方法移除相应的ClassFileTransformer,然后调用Instrumentation的retransformClasses(Class<?>… classes)重新触发类加载
5、模块刷新
sh sandbox/bin/sandbox.sh -p pid -f/-F
模块刷新分为强制刷新和软刷新两种类型
# -F force flush module
[[ -n ${OP_MODULE_FORCE_FLUSH} ]] &&
sandbox_curl_with_exit "sandbox-module-mgr/flush" "&force=true"
# -f flush module
[[ -n ${OP_MODULE_FLUSH} ]] &&
sandbox_curl_with_exit "sandbox-module-mgr/flush" "&force=false"
1)、ModuleMgrModule的flush()
方法
@MetaInfServices(Module.class)
@Information(id = "sandbox-module-mgr", author = "luanjia@taobao.com", version = "0.0.2")
public class ModuleMgrModule implements Module {
@Command("flush")
public void flush(final Map<String, String> param,
final PrintWriter writer) throws ModuleException {
final String isForceString = getParamWithDefault(param, "force", EMPTY);
final boolean isForce = BooleanUtils.toBoolean(isForceString);
moduleManager.flush(isForce);
output(writer, "module flush finished, total=%s;", moduleManager.list().size());
}
最终会调用DefaultCoreModuleManager的flush()
方法
public class DefaultCoreModuleManager implements CoreModuleManager {
@Override
public synchronized void flush(final boolean isForce) throws ModuleException {
if (isForce) {
forceFlush();
} else {
softFlush();
}
}
强制刷新是简单粗暴重新卸载加载所有的用户模块,而软刷新则是通过文件校验只刷新变化的用户模块
2)、强制刷新
public class DefaultCoreModuleManager implements CoreModuleManager {
/**
* 强制刷新
* 对所有已经加载的用户模块进行强行卸载并重新加载
*
* @throws ModuleException 模块操作失败
*/
private void forceFlush() throws ModuleException {
logger.info("force-flushing modules:{}", loadedModuleBOMap.keySet());
// 1. 卸载模块
// 等待卸载的模块集合
final Collection<CoreModule> waitingUnloadCoreModules = new ArrayList<CoreModule>();
// 找出所有USER的模块,所以这些模块都卸载了
for (final CoreModule coreModule : loadedModuleBOMap.values()) {
// 如果判断是属于USER模块目录下的模块,则加入到待卸载模块集合,稍后统一进行卸载
if (!isSystemModule(coreModule.getJarFile())) {
waitingUnloadCoreModules.add(coreModule);
}
}
// 记录下即将被卸载的模块ID集合
if (logger.isInfoEnabled()) {
final Set<String> uniqueIds = new LinkedHashSet<String>();
for (final CoreModule coreModule : waitingUnloadCoreModules) {
uniqueIds.add(coreModule.getUniqueId());
}
logger.info("force-flush modules: will be unloading modules : {}", uniqueIds);
}
// 强制卸载掉所有等待卸载的模块集合中的模块
for (final CoreModule coreModule : waitingUnloadCoreModules) {
unload(coreModule, true);
}
// 2. 加载模块
// 用户模块加载目录,加载用户模块目录下的所有模块
// 对模块访问权限进行校验
// 用户模块目录
final File[] userModuleLibFileArray = cfg.getUserModuleLibFiles();
for (final File userModuleLibDir : userModuleLibFileArray) {
if (userModuleLibDir.exists()
&& userModuleLibDir.canRead()) {
logger.info("force-flush modules: module-lib={}", userModuleLibDir);
new ModuleLibLoader(userModuleLibDir, cfg.getLaunchMode())
.load(new InnerModuleJarLoadCallback(), new InnerModuleLoadCallback());
} else {
logger.warn("force-flush modules: module-lib can not access, will be ignored. module-lib={}", userModuleLibDir);
}
}
}
DefaultCoreModuleManager的forceFlush()
方法核心流程如下:
- 卸载所有用户模块
- 加载用户模块目录下的所有模块
3)、软刷新
public class DefaultCoreModuleManager implements CoreModuleManager {
/**
* 软刷新
* 找出有变动的模块文件,有且仅有改变这些文件所对应的模块
*/
private void softFlush() {
logger.info("soft-flushing modules:{}", loadedModuleBOMap.keySet());
final File systemModuleLibDir = new File(cfg.getSystemModuleLibPath());
try {
final ArrayList<File> appendJarFiles = new ArrayList<File>();
final ArrayList<CoreModule> removeCoreModules = new ArrayList<CoreModule>();
final ArrayList<Long> checksumCRC32s = new ArrayList<Long>();
// 1. 找出所有有变动的文件(add/remove)
for (final File jarFile : cfg.getUserModuleLibFiles()) {
final long checksumCRC32;
try {
checksumCRC32 = FileUtils.checksumCRC32(jarFile);
} catch (IOException cause) {
logger.warn("soft-flushing module: compute module-jar CRC32 occur error. module-jar={};", jarFile, cause);
continue;
}
checksumCRC32s.add(checksumCRC32);
// 如果CRC32已经在已加载的模块集合中存在,则说明这个文件没有变动,忽略
if (isChecksumCRC32Existed(checksumCRC32)) {
logger.info("soft-flushing module: module-jar is not changed, ignored. module-jar={};CRC32={};", jarFile, checksumCRC32);
continue;
}
logger.info("soft-flushing module: module-jar is changed, will be flush. module-jar={};CRC32={};", jarFile, checksumCRC32);
appendJarFiles.add(jarFile);
}
// 2. 找出所有待卸载的已加载用户模块
for (final CoreModule coreModule : loadedModuleBOMap.values()) {
final ModuleJarClassLoader moduleJarClassLoader = coreModule.getLoader();
// 如果是系统模块目录则跳过
if (isOptimisticDirectoryContainsFile(systemModuleLibDir, coreModule.getJarFile())) {
logger.debug("soft-flushing module: module-jar is in system-lib, will be ignored. module-jar={};system-lib={};",
coreModule.getJarFile(),
systemModuleLibDir
);
continue;
}
// 如果CRC32已经在这次待加载的集合中,则说明这个文件没有变动,忽略
if (checksumCRC32s.contains(moduleJarClassLoader.getChecksumCRC32())) {
logger.info("soft-flushing module: module-jar already loaded, ignored. module-jar={};CRC32={};",
coreModule.getJarFile(),
moduleJarClassLoader.getChecksumCRC32()
);
continue;
}
logger.info("soft-flushing module: module-jar is changed, module will be reload/remove. module={};module-jar={};",
coreModule.getUniqueId(),
coreModule.getJarFile()
);
removeCoreModules.add(coreModule);
}
// 3. 删除remove
for (final CoreModule coreModule : removeCoreModules) {
unload(coreModule, true);
}
// 4. 加载add
for (final File jarFile : appendJarFiles) {
new ModuleLibLoader(jarFile, cfg.getLaunchMode())
.load(new InnerModuleJarLoadCallback(), new InnerModuleLoadCallback());
}
} catch (Throwable cause) {
logger.warn("soft-flushing modules: occur error.", cause);
}
}
DefaultCoreModuleManager的softFlush()
方法核心流程如下:
- 通过checksumCRC32找出变动文件
- 卸载所有变动的用户模块
- 加载用户模块目录下的所有变动的用户模块
7、模块卸载
模块卸载由DefaultCoreModuleManager的unload()
方法实现:
public class DefaultCoreModuleManager implements CoreModuleManager {
/**
* 卸载并删除注册模块
* <p>1. 如果模块原本就不存在,则幂等此次操作</p>
* <p>2. 如果模块存在则尝试进行卸载</p>
* <p>3. 卸载模块之前会尝试冻结该模块</p>
*
* @param coreModule 等待被卸载的模块
* @param isIgnoreModuleException 是否忽略模块异常
* @throws ModuleException 卸载模块失败
*/
@Override
public synchronized CoreModule unload(final CoreModule coreModule,
final boolean isIgnoreModuleException) throws ModuleException {
if (!coreModule.isLoaded()) {
logger.debug("module already unLoaded. module={};", coreModule.getUniqueId());
return coreModule;
}
logger.info("unloading module, module={};class={};",
coreModule.getUniqueId(),
coreModule.getModule().getClass().getName()
);
// 尝试冻结模块
frozen(coreModule, isIgnoreModuleException);
// 通知生命周期
try {
callAndFireModuleLifeCycle(coreModule, MODULE_UNLOAD);
} catch (ModuleException meCause) {
if (isIgnoreModuleException) {
logger.warn("unload module occur error, ignored. module={};class={};code={};",
meCause.getUniqueId(),
coreModule.getModule().getClass().getName(),
meCause.getErrorCode(),
meCause
);
} else {
throw meCause;
}
}
// 从模块注册表中删除
loadedModuleBOMap.remove(coreModule.getUniqueId());
// 标记模块为:已卸载
coreModule.markLoaded(false);
// 释放所有可释放资源
coreModule.releaseAll();
// 尝试关闭ClassLoader
closeModuleJarClassLoaderIfNecessary(coreModule.getLoader());
return coreModule;
}
DefaultCoreModuleManager的unload()
方法核心流程如下:
- 尝试冻结模块
- 从模块注册表中删除,并打上删除标记
- 释放所有可释放资源
- 尝试关闭ModuleJarClassLoader
1)、尝试冻结模块
调用frozen()
方法尝试冻结模块:
public class DefaultCoreModuleManager implements CoreModuleManager {
@Override
public synchronized void frozen(final CoreModule coreModule,
final boolean isIgnoreModuleException) throws ModuleException {
// 如果模块已经被冻结(尚未被激活),则直接幂等返回
if (!coreModule.isActivated()) {
logger.debug("module already frozen. module={};", coreModule.getUniqueId());
return;
}
logger.info("frozen module, module={};class={};module-jar={};",
coreModule.getUniqueId(),
coreModule.getModule().getClass().getName(),
coreModule.getJarFile()
);
// 通知生命周期
try {
callAndFireModuleLifeCycle(coreModule, MODULE_FROZEN);
} catch (ModuleException meCause) {
if (isIgnoreModuleException) {
logger.warn("frozen module occur error, ignored. module={};class={};code={};",
meCause.getUniqueId(),
coreModule.getModule().getClass().getName(),
meCause.getErrorCode(),
meCause
);
} else {
throw meCause;
}
}
// 冻结所有监听器
for (final SandboxClassFileTransformer sandboxClassFileTransformer : coreModule.getSandboxClassFileTransformers()) {
EventListenerHandler.getSingleton()
.frozen(sandboxClassFileTransformer.getListenerId());
}
// 标记模块为已冻结
coreModule.markActivated(false);
}
2)、释放所有可释放资源
调用releaseAll()
释放所有可释放资源:
public class CoreModule {
/**
* 在当前模块下移除所有可释放资源
*/
public void releaseAll() {
synchronized (releaseResources) {
final Iterator<ReleaseResource<?>> resourceRefIt = releaseResources.iterator();
while (resourceRefIt.hasNext()) {
final ReleaseResource<?> resourceRef = resourceRefIt.next();
resourceRefIt.remove();
if (null != resourceRef) {
logger.debug("release resource={} in module={}", resourceRef.get(), uniqueId);
try {
resourceRef.release();
} catch (Exception cause) {
logger.warn("release resource occur error in module={};", uniqueId, cause);
}
}
}
}
}
releaseAll()
中调用了resourceRef.release()
方法,这个方法是在加载模块,通过DefaultCoreModuleManager的injectResourceOnLoadIfNecessary()
方法注入@Resource资源的时候,实现沙箱模块内核封装对象CoreModule内部抽象类ReleaseResource的抽象release()
方法
// ModuleEventWatcher对象注入
else if (ModuleEventWatcher.class.isAssignableFrom(fieldType)) {
final ModuleEventWatcher moduleEventWatcher = coreModule.append(
new ReleaseResource<ModuleEventWatcher>(
SandboxProtector.instance.protectProxy(
ModuleEventWatcher.class,
new DefaultModuleEventWatcher(inst, classDataSource, coreModule, cfg.isEnableUnsafe(), cfg.getNamespace())
)
) {
@Override
public void release() {
logger.info("release all SandboxClassFileTransformer for module={}", coreModule.getUniqueId());
final ModuleEventWatcher moduleEventWatcher = get();
if (null != moduleEventWatcher) {
for (final SandboxClassFileTransformer sandboxClassFileTransformer
: new ArrayList<SandboxClassFileTransformer>(coreModule.getSandboxClassFileTransformers())) {
moduleEventWatcher.delete(sandboxClassFileTransformer.getWatchId());
}
}
}
});
writeField(
resourceField,
module,
moduleEventWatcher,
true
);
}
重写的release()
方法在目标模块已经产生织入行为之后,要从Jvm去掉之前带有增强的代码逻辑的字节码,然后再重新渲染一次原始类的字节码,最终调用了DefaultModuleEventWatcher的delete()
方法:
public class DefaultModuleEventWatcher implements ModuleEventWatcher {
@Override
public void delete(final int watcherId,
final Progress progress) {
final Set<Matcher> waitingRemoveMatcherSet = new LinkedHashSet<Matcher>();
// 找出待删除的SandboxClassFileTransformer
final Iterator<SandboxClassFileTransformer> cftIt = coreModule.getSandboxClassFileTransformers().iterator();
int cCnt = 0, mCnt = 0;
while (cftIt.hasNext()) {
final SandboxClassFileTransformer sandboxClassFileTransformer = cftIt.next();
if (watcherId == sandboxClassFileTransformer.getWatchId()) {
// 冻结所有关联代码增强
EventListenerHandler.getSingleton()
.frozen(sandboxClassFileTransformer.getListenerId());
// 在JVM中移除掉命中的ClassFileTransformer
inst.removeTransformer(sandboxClassFileTransformer);
// 计数
cCnt += sandboxClassFileTransformer.getAffectStatistic().cCnt();
mCnt += sandboxClassFileTransformer.getAffectStatistic().mCnt();
// 追加到待删除过滤器集合
waitingRemoveMatcherSet.add(sandboxClassFileTransformer.getMatcher());
// 清除掉该SandboxClassFileTransformer
cftIt.remove();
}
}
// 查找需要删除后重新渲染的类集合
final List<Class<?>> waitingReTransformClasses = classDataSource.findForReTransform(
new GroupMatcher.Or(waitingRemoveMatcherSet.toArray(new Matcher[0]))
);
logger.info("watch={} in module={} found {} classes for delete.",
watcherId,
coreModule.getUniqueId(),
waitingReTransformClasses.size()
);
beginProgress(progress, waitingReTransformClasses.size());
try {
// 应用JVM
reTransformClasses(watcherId, waitingReTransformClasses, progress);
} finally {
finishProgress(progress, cCnt, mCnt);
}
}
3)、尝试关闭ModuleJarClassLoader
如果该ModuleJarClassLoader所加载上来的所有模块都已经被卸载,则该ClassLoader需要主动进行关闭
public class DefaultCoreModuleManager implements CoreModuleManager {
/**
* 关闭ModuleJarClassLoader
* 如ModuleJarClassLoader所加载上来的所有模块都已经被卸载,则该ClassLoader需要主动进行关闭
*
* @param loader 需要被关闭的ClassLoader
*/
private void closeModuleJarClassLoaderIfNecessary(final ClassLoader loader) {
if (!(loader instanceof ModuleJarClassLoader)) {
return;
}
// 查找已经注册的模块中是否仍然还包含有ModuleJarClassLoader的引用
boolean hasRef = false;
for (final CoreModule coreModule : loadedModuleBOMap.values()) {
if (loader == coreModule.getLoader()) {
hasRef = true;
break;
}
}
if (!hasRef) {
logger.info("ModuleJarClassLoader={} will be close: all module unloaded.", loader);
((ModuleJarClassLoader) loader).closeIfPossible();
}
}
如果有模块实现模块文件卸载接口ModuleJarUnLoadSpi的onJarUnLoadCompleted()
方法,则会在这时收到消息通知,方便模块继续清理其他资源,如logback,避免因为资源未释放,导致ClassLoader关闭失败
@Stealth
public class ModuleJarClassLoader extends RoutingURLClassLoader {
public void closeIfPossible() {
onJarUnLoadCompleted();
try {
// 如果是JDK7+的版本,URLClassLoader实现了Closeable接口,直接调用即可
if (this instanceof Closeable) {
logger.debug("JDK is 1.7+, use URLClassLoader[file={}].close()", moduleJarFile);
try {
((Closeable)this).close();
} catch (Throwable cause) {
logger.warn("close ModuleJarClassLoader[file={}] failed. JDK7+", moduleJarFile, cause);
}
return;
}
// 对于JDK6的版,URLClassLoader要关闭起来就显得有点麻烦,这里弄了一大段代码来稍微处理下
// 而且还不能保证一定释放干净了,至少释放JAR文件句柄是没有什么问题了
try {
logger.debug("JDK is less then 1.7+, use File.release()");
final Object sun_misc_URLClassPath = unCaughtGetClassDeclaredJavaFieldValue(URLClassLoader.class, "ucp", this);
final Object java_util_Collection = unCaughtGetClassDeclaredJavaFieldValue(sun_misc_URLClassPath.getClass(), "loaders", sun_misc_URLClassPath);
for (Object sun_misc_URLClassPath_JarLoader :
((Collection) java_util_Collection).toArray()) {
try {
final JarFile java_util_jar_JarFile = unCaughtGetClassDeclaredJavaFieldValue(
sun_misc_URLClassPath_JarLoader.getClass(),
"jar",
sun_misc_URLClassPath_JarLoader
);
java_util_jar_JarFile.close();
} catch (Throwable t) {
// if we got this far, this is probably not a JAR loader so skip it
}
}
} catch (Throwable cause) {
logger.warn("close ModuleJarClassLoader[file={}] failed. probably not a HOTSPOT VM", moduleJarFile, cause);
}
} finally {
// 删除掉临时文件
FileUtils.deleteQuietly(tempModuleJarFile);
}
}
private void onJarUnLoadCompleted() {
try {
final ServiceLoader<ModuleJarUnLoadSpi> moduleJarUnLoadSpiServiceLoader
= ServiceLoader.load(ModuleJarUnLoadSpi.class, this);
for (final ModuleJarUnLoadSpi moduleJarUnLoadSpi : moduleJarUnLoadSpiServiceLoader) {
logger.info("unloading module-jar: onJarUnLoadCompleted() loader={};moduleJarUnLoadSpi={};",
this,
getJavaClassName(moduleJarUnLoadSpi.getClass())
);
moduleJarUnLoadSpi.onJarUnLoadCompleted();
}
} catch (Throwable cause) {
logger.warn("unloading module-jar: onJarUnLoadCompleted() occur error! loader={};", this, cause);
}
}