JVM SandBox源码解析(二):增强目标类、模块刷新、模块卸载

本文详细解析了JVMSandBox的模块加载、增强目标类、模块刷新及卸载等机制,包括loadCompleted方法调用时机、onWatch方法原理、模块刷新方式以及卸载流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()方法核心流程如下:

  1. 使用一个全局的AtomicInteger生成watchId
  2. 给对应的模块追加SandboxClassFileTransformer
  3. 将SandboxClassFileTransformer注册到CoreModule中
  4. 调用Instrumentation的addTransformer()方法,接下来引起的类加载都会经过SandClassFileTransformer
  5. 查找需要渲染的类集合
  6. 调用reTransformClasses()方法,实际调用了Instrumentation的retransformClasses()方法,对JVM已经加载的类重新触发类加载
  7. 判断自定义模块的默认状态是否为激活,如果是,激活增强类

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()方法核心流程如下:

  1. 卸载所有用户模块
  2. 加载用户模块目录下的所有模块
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()方法核心流程如下:

  1. 通过checksumCRC32找出变动文件
  2. 卸载所有变动的用户模块
  3. 加载用户模块目录下的所有变动的用户模块

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()方法核心流程如下:

  1. 尝试冻结模块
  2. 从模块注册表中删除,并打上删除标记
  3. 释放所有可释放资源
  4. 尝试关闭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);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邋遢的流浪剑客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值