Skip to content

记录一个 ClassLoaderHandler 类加载问题排查  #42

@hengyunabc

Description

@hengyunabc

在目前代码里,有一个 dubbo的示例,里面有一个 com.test.dubbo.DubboPluginClassLoaderHandler

public class DubboPluginClassLoaderHandler implements ClassLoaderHandler {

    @Override
    public Class<?> loadClass(String name) {
        if (name.startsWith("com.test.dubbo")) {
            try {
                Class<?> clazz = this.getClass().getClassLoader().loadClass(name);
                return clazz;
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

显然它是为了保证 dubbo-test-plugin-common 下的测试类 com.test.dubbo.RpcUtils 能被其它ClassLoader正常加载。


当用户自己写了一个 dubbo 的测试,里面的代码是 com.test.dubbo.EchoService ,这里就出现问题了。

  • package 和 DubboPluginClassLoaderHandler 里的重名了,导致应用的 com.test.dubbo.EchoService 会被 dubbo-plugin PluginClassLoader 加载。

  • PluginClassLoader 目前的加载顺序,最终会向上调用 super 去查找,PluginClassLoader 的 parent 是启动 one-java-agent 的 ClassLoader 。

  • 所以最终可能 com.test.dubbo.EchoService 是被 one-java-agent 的 ClassLoader 加载到。而并不是应用的 ClassLoader。


一个异常栈:

Thread [main] (Suspended (breakpoint at line 26 in AgentSpyImpl))	
	owns: Object  (id=11559)	
	owns: OneAgentClassLoader  (id=11560)	
	owns: PluginClassLoader  (id=11561)	
	owns: Object  (id=11562)	
	AgentSpyImpl.loadClass(String) line: 26	
	Launcher$AppClassLoader(ClassLoader).loadClass(String) line: 49	
	ClassLoader.defineClass1(String, byte[], int, int, ProtectionDomain, String) line: not available [native method]	
	Launcher$AppClassLoader(ClassLoader).defineClass(String, byte[], int, int, ProtectionDomain) line: 763	
	Launcher$AppClassLoader(SecureClassLoader).defineClass(String, byte[], int, int, CodeSource) line: 142	
	Launcher$AppClassLoader(URLClassLoader).defineClass(String, Resource) line: 468	
	URLClassLoader.access$100(URLClassLoader, String, Resource) line: 74	
	URLClassLoader$1.run() line: 369	
	URLClassLoader$1.run() line: 363	
	AccessController.doPrivileged(PrivilegedExceptionAction<T>, AccessControlContext) line: not available [native method]	
	Launcher$AppClassLoader(URLClassLoader).findClass(String) line: 362	
	Launcher$AppClassLoader(ClassLoader).loadClass(String, boolean) line: 424	
	Launcher$AppClassLoader.loadClass(String, boolean) line: 349	
	OneAgentClassLoader(ClassLoader).loadClass(String, boolean) line: 411	
	PluginClassLoader(ClassLoader).loadClass(String, boolean) line: 411	
	PluginClassLoader.loadClass(String, boolean) line: 144	
	PluginClassLoader(ClassLoader).loadClass(String) line: 357	
	DubboPluginClassLoaderHandler.loadClass(String) line: 16	
	ClassLoaderHandlerManagerImpl.loadClass(String) line: 80	
	AgentSpyImpl.loadClass(String) line: 26	
	ReLaunchURLClassLoader(ClassLoader).loadClass(String) line: 49	
	Class<T>.forName0(String, boolean, ClassLoader, Class<?>) line: not available [native method]	
	Class<T>.forName(String, boolean, ClassLoader) line: 348	
	ClassUtils.forName(String, ClassLoader) line: 280	
	ClassUtils.resolveClassName(String, ClassLoader) line: 320	
	ServiceClassPostProcessor.resolveClass(BeanDefinition) line: 361	
	ServiceClassPostProcessor.resolveClass(BeanDefinitionHolder) line: 353	
	ServiceClassPostProcessor.registerServiceBean(BeanDefinitionHolder, BeanDefinitionRegistry, DubboClassPathBeanDefinitionScanner) line: 279	
	ServiceClassPostProcessor.registerServiceBeans(Set<String>, BeanDefinitionRegistry) line: 175	
	ServiceClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry) line: 134	
	PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection<BeanDefinitionRegistryPostProcessor>, BeanDefinitionRegistry) line: 275	
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>) line: 125	
	AnnotationConfigApplicationContext(AbstractApplicationContext).invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory) line: 706	
	AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 532	
	SpringApplication.refresh(ApplicationContext) line: 744	
	SpringApplication.refreshContext(ConfigurableApplicationContext) line: 391	
	SpringApplication.run(String...) line: 312	
	SpringApplication.run(Class<?>[], String[]) line: 1215	
	SpringApplication.run(Class<?>, String...) line: 1204	
	Application.main(String[]) line: 33	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 498	
	LaunchRunner.run() line: 38	
	Thread.run() line: 748	

TODO

  • 仔细定义启动 one-java-agent的 ClassLoader 和 PluginClassLoader 的行为
  • 使用 ClassLoaderHandler 时要非常小心

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions