sofastack / sofa-ark

SOFAArk is a light-weight,java based classloader isolation framework.
https://www.sofastack.tech/projects/sofa-boot/sofa-ark-readme/
Apache License 2.0
1.57k stars 500 forks source link

The custom ClassLoaderHook implementation class cannot be loaded. #352

Closed wapkch closed 4 years ago

wapkch commented 4 years ago

Your question

  1. 自定义的ClassLoaderHook实现类无法被加载。
  2. https://github.com/sofastack/sofa-ark/issues/159 中spring项目ark plugin化问题是否可以通过定义PluginClassLoaderHook,使用主bizClassLoader加载spring类来解决?

Your scenes

问题1场景: 在plugin中定义了ClassLoaderHook实现类并导出,启动后ClassLoaderHook实现类并未被加载。看源码发现extension的加载默认路径为META-INF/services/sofa-ark,应该如何定义ClassLoaderHook实现类才能被正确加载? ClassLoaderHook实现类:

@Extension(value = "plugin-classloader-hook")
public class PluginClassLoaderHook implements ClassLoaderHook<Plugin> {
    @Override
    public Class<?> preFindClass(String name, ClassLoaderService classLoaderService, Plugin plugin) throws ClassNotFoundException {
        return null;
    }
}

ExtensionLoaderServiceImpl中loadExtension逻辑:

public final static String EXTENSION_FILE_DIR = "META-INF/services/sofa-ark/";
public final static String fileName = "com.alipay.sofa.ark.spi.service.classloader.ClassLoaderHook";
Enumeration<URL> enumeration = resourceLoader.getResources(EXTENSION_FILE_DIR+ fileName);

问题2场景: https://github.com/sofastack/sofa-ark/issues/159 提到spring项目ark plugin化后问题的两种解决方案:

这两种方案对项目改造成本都比较大,否可以通过ClassLoaderHook解决?例如在plugin中定义ClassLoaderHook实现,使用主bizClassLoader加载spring类。

@Extension(value = "plugin-classloader-hook")
public class PluginClassLoaderHook implements ClassLoaderHook<Plugin> {
    @Override
    public Class<?> preFindClass(String name, ClassLoaderService classLoaderService, Plugin plugin) throws ClassNotFoundException {

        if (name.startsWith("org.springframework.")) {
            BizManagerService service = ArkServiceContainerHolder
                    .getContainer().getService(BizManagerService.class);
            String masterBizName = ArkConfigs.getStringValue(Constants.MASTER_BIZ);
            String version = "1.0.0";
            Biz biz = service.getBiz(masterBizName, version);
            return biz.getBizClassLoader().loadClass(name);
        }
        return null;
    }
}

@glmapper 麻烦帮忙看下上述问题,感谢!

Environment

sofastack-bot[bot] commented 4 years ago

Hi @wapkch, we detect non-English characters in the issue. This comment is an auto translation by @sofastack-robot to help other users to understand this issue.

We encourage you to describe your issue in English which is more friendly to other users.

Your question 1. The custom ClassLoaderHook implementation class cannot be loaded. 2. Can the ark pluginization problem of the spring project in https://github.com/sofastack/sofa-ark/issues/159 be solved by defining PluginClassLoaderHook and using the main bizClassLoader to load the spring class? ### Your scenes Problem 1 scenario: The ClassLoaderHook implementation class is defined in the plugin and exported. The ClassLoaderHook implementation class is not loaded after startup. Looking at the source code, it is found that the default loading path of the extension is META-INF / services / sofa-ark. How should the ClassLoaderHook implementation class be defined to be loaded correctly? ClassLoaderHook implementation class: `@Extension (value =&quot; plugin-classloader-hook &quot;) public class PluginClassLoaderHook implements ClassLoaderHook <Plugin> {@Override public Class <?> preFindClass (String name, ClassLoaderService classLoaderService, Plugin plugin) throws ClassNotFoundException {return null;}} LoadExtension logic in ExtensionLoaderServiceImpl: public final static String EXTENSION_FILE_DIR = &quot;META-INF / services / sofa-ark /&quot;; public final static String fileName = &quot;com.alipay.sofa.ark.spi.service.classloader.ClassLoaderHook&quot;; Enumeration <URL> enumeration = resourceLoader.getResources (EXTENSION_FILE_DIR fileName); Issue 2 scenario: https://github.com/sofastack/sofa-ark/issues/159 Mentioned two solutions to the problem after spring project ark pluginization:- Project despringization-Spring sinks into another ark plugin. These two solutions are relatively expensive for project transformation. Can they be solved by ClassLoaderHook? For example, the ClassLoaderHook implementation is defined in the plugin, and the main bizClassLoader is used to load the spring class. ``@Extension (value =" plugin-classloader-hook ") public class PluginClassLoaderHook implements ClassLoaderHook {@Override public Class <?> preFindClass (String name, ClassLoaderService classLoaderService, Plugin plugin) throws ClassNotFoundException {if (name.startsWith ("org.springframework.")) {BizManagerService service = ArkServiceContainerHolder .getContainer (). getService (BizManagerService.class); String masterBizName = ArkConfigs. getStringValue (Constants.MASTER_BIZ); String version = "1.0.0"; Biz biz = service.getBiz (masterBizName, version); return biz.getBizClassLoader (). loadClass (name);} return null;}} `@ glmapper please help look at the above problems, thanks! ### Environment-SOFAArk version: 1.0.0-JVM version (eg java -version):-OS version (eguname -a):-Maven version:-IDE version:

glmapper commented 4 years ago

@wapkch 委托 master biz 去加载 Spring 的类理论上是可行的。

如果使得自定义的hook 生效:在 META-INF.services.sofa-ark目录下新建一个 名为 com.alipay.sofa.ark.spi.service.classloader.ClassLoaderHook 的文件,文件中写hook 类的全限定名,如: com.alipay.sofa.ark.container.service.classloader.hook.TestBizClassLoaderHook。参考 这里

wapkch commented 4 years ago

@glmapper 非常感谢!