Skip to content

Commit

Permalink
*fix spi classloader
Browse files Browse the repository at this point in the history
Signed-off-by: provenceee <[email protected]>
  • Loading branch information
provenceee committed Nov 19, 2024
1 parent 531fb32 commit c51416c
Show file tree
Hide file tree
Showing 18 changed files with 64 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class ClassLoaderManager {

private static FrameworkClassLoader frameworkClassLoader;

private static ClassLoader userClassLoader;

private ClassLoaderManager() {
}

Expand Down Expand Up @@ -88,6 +90,23 @@ public PluginClassLoader run() {
});
}

public static void setUserClassLoader(ClassLoader userClassLoader) {
ClassLoaderManager.userClassLoader = userClassLoader;
}

/**
* get ContextClassLoader or UserClassLoader
*
* @return ClassLoader
*/
public static ClassLoader getContextClassLoaderOrUserClassLoader() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader != null) {
return classLoader;
}
return userClassLoader;
}

public static SermantClassLoader getSermantClassLoader() {
return sermantClassLoader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class ClassLoaderLoadClassInterceptor extends AbstractClassLoaderIntercep

@Override
public ExecuteContext before(ExecuteContext context) throws Exception {
ClassLoaderManager.setUserClassLoader((ClassLoader) context.getObject());
return context;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.sermant.core.plugin.classloader;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.config.ConfigManager;
import io.sermant.core.plugin.agent.config.AgentConfig;
Expand Down Expand Up @@ -131,9 +132,16 @@ public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundExce

private Class<?> getClassFromLocalClassLoader(String name) {
ClassLoader loader = localLoader.get(Thread.currentThread().getId());

if (loader == null) {
LOGGER.log(Level.FINE, "localLoader is null, thread name is {0}, classs name is {1}.",
new Object[]{Thread.currentThread().getName(), name});
}
if (loader == null && useContextLoader) {
loader = Thread.currentThread().getContextClassLoader();
loader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
if (loader == null) {
LOGGER.log(Level.WARNING, "contextClassLoader is null, thread name is {0}, classs name is {1}.",
new Object[]{Thread.currentThread().getName(), name});
}
}
Class<?> clazz = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.core.utils;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;

import java.io.IOException;
Expand Down Expand Up @@ -111,7 +112,7 @@ public static Optional<Class<?>> loadClass(String className, ClassLoader classLo
public static Optional<Object> createInstance(String className, ClassLoader classLoader, Class<?>[] paramTypes) {
ClassLoader curClassLoader = classLoader;
if (curClassLoader == null) {
curClassLoader = Thread.currentThread().getContextClassLoader();
curClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
}
try {
final Class<?> clazz = curClassLoader.loadClass(className);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.core.utils;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;

import java.lang.reflect.AccessibleObject;
Expand Down Expand Up @@ -166,7 +167,7 @@ private static Optional<Class<?>> loadClass(String className) {
return Optional.empty();
}
return CLASS_CACHE.computeIfAbsent(className, value -> {
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
try {
return Optional.ofNullable(contextClassLoader.loadClass(className));
} catch (ClassNotFoundException ignored) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.flowcontrol.common.handler.retry;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.flowcontrol.common.config.FlowControlConfig;
Expand Down Expand Up @@ -53,7 +54,8 @@ protected final Class<? extends Throwable>[] findClass(String[] classNames) {
final List<Class<?>> result = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
result.add(Class.forName(className, false, Thread.currentThread().getContextClassLoader()));
result.add(Class.forName(className, false,
ClassLoaderManager.getContextClassLoaderOrUserClassLoader()));
} catch (ClassNotFoundException exception) {
LoggerFactory.getLogger().info(String.format(Locale.ENGLISH,
"Can not find retry exception class %s", className));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.flowcontrol.config;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
Expand Down Expand Up @@ -101,7 +102,7 @@ private boolean isHasMethodLoadSpringFactories() {

private void injectConfigurationsWithLowVersion(Object result, String factoryName) {
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
if (result instanceof List) {
final List<String> convertedResult = (List<String>) result;
CLASS_DEFINES.forEach(classInjectDefine -> {
Expand All @@ -115,7 +116,7 @@ private void injectConfigurationsWithLowVersion(Object result, String factoryNam

private void injectConfigurations(Object result) {
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
final boolean isMultiValueMap = result instanceof MultiValueMap;
if (result instanceof Map) {
// Spring high version processing, for List, which is an immutable list, a layer of processing is required.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.flowcontrol.inject;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.service.inject.ClassInjectDefine;
import io.sermant.core.utils.ClassUtils;

Expand Down Expand Up @@ -53,6 +54,6 @@ public Plugin plugin() {
}

private boolean isLoadedClass(String className) {
return ClassUtils.loadClass(className, Thread.currentThread().getContextClassLoader(), true).isPresent();
return ClassUtils.loadClass(className, ClassLoaderManager.getContextClassLoaderOrUserClassLoader(), true).isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.flowcontrol.retry;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.utils.ClassUtils;
import io.sermant.flowcontrol.retry.cluster.AlibabaDubboCluster;
Expand Down Expand Up @@ -70,7 +71,7 @@ protected ExecuteContext doAfter(ExecuteContext context) {
return context;
}
final Optional<Class<?>> retryInvokerClass;
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
if (APACHE_DUBBO_CLUSTER_CLASS_NAME.equals(type.getName())) {
ClassUtils.defineClass(
"io.sermant.flowcontrol.retry.cluster.ApacheDubboClusterInvoker", contextClassLoader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.flowcontrol.retry;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.utils.ReflectUtils;
Expand Down Expand Up @@ -99,7 +100,7 @@ private Optional<Object> buildResult(Object lastServer, String responseClassName
if (defaultResponseClazz == null) {
return Optional.empty();
}
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
try {
final Class<?> clazz = contextClassLoader.loadClass(defaultResponseClazz);
final Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(ServiceInstance.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.sermant.dubbo.registry.utils;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.utils.ClassLoaderUtils;
import io.sermant.dubbo.registry.cache.DubboCache;
Expand Down Expand Up @@ -100,7 +101,7 @@ private ReflectUtils() {
* @return Host class
*/
public static Optional<Class<?>> defineClass(String className) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
try {
return Optional.of(ClassLoaderUtils.defineClass(className, contextClassLoader,
ClassLoaderUtils.getClassResource(ReflectUtils.class.getClassLoader(), className)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.config;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.plugin.service.PluginServiceManager;
Expand Down Expand Up @@ -119,7 +120,7 @@ private Optional<Object> tryGetInetUtils() {

private Optional<Object> tryGetInetUtilsByClazz() {
final Optional<Class<?>> clazz = ClassUtils
.loadClass(INET_UTILS_CLASS, Thread.currentThread().getContextClassLoader(), false);
.loadClass(INET_UTILS_CLASS, ClassLoaderManager.getContextClassLoaderOrUserClassLoader(), false);
if (!clazz.isPresent()) {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.inject;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.service.inject.ClassInjectDefine;
import io.sermant.core.utils.ClassUtils;
Expand Down Expand Up @@ -47,6 +48,7 @@ public Plugin plugin() {
* @return Whether it is loaded or not
*/
protected boolean isClassExistedOnCurrentClassLoader(String className) {
return ClassUtils.loadClass(className, Thread.currentThread().getContextClassLoader(), false).isPresent();
return ClassUtils.loadClass(className, ClassLoaderManager.getContextClassLoaderOrUserClassLoader(),
false).isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.inject;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.service.inject.ClassInjectDefine;
import io.sermant.core.utils.ClassUtils;

Expand Down Expand Up @@ -52,6 +53,6 @@ public ClassInjectDefine[] requiredDefines() {
public boolean canInject() {
return super.canInject() && ClassUtils.loadClass(
"org.springframework.cloud.netflix.ribbon.SpringClientFactory",
Thread.currentThread().getContextClassLoader(), false).isPresent();
ClassLoaderManager.getContextClassLoaderOrUserClassLoader(), false).isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.inject;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.service.inject.ClassInjectDefine;
import io.sermant.core.utils.ClassUtils;
Expand All @@ -41,7 +42,7 @@ public String factoryName() {

@Override
public boolean canInject() {
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
final RegisterConfig pluginConfig = PluginConfigManager.getPluginConfig(RegisterConfig.class);
return pluginConfig.isOpenMigration() && pluginConfig.isEnableSpringRegister()
&& ClassUtils.loadClass("com.netflix.loadbalancer.Server", contextClassLoader).isPresent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.interceptors;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.plugin.config.PluginConfigManager;
Expand Down Expand Up @@ -99,7 +100,7 @@ private boolean isHasMethodLoadSpringFactories() {

private void injectConfigurationsWithLowVersion(Object result, String factoryName) {
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
if (result instanceof List) {
final List<String> convertedResult = (List<String>) result;
CLASS_DEFINES.forEach(classInjectDefine -> {
Expand All @@ -113,7 +114,7 @@ private void injectConfigurationsWithLowVersion(Object result, String factoryNam

private void injectConfigurations(Object result) {
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
final boolean isMultiValueMap = result instanceof MultiValueMap;
if (result instanceof Map) {
// Spring is a higher version of the list, and it is an immutable list that needs to be processed at one
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.sermant.registry.interceptors.health;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.registry.context.RegisterContext;
Expand All @@ -40,7 +41,7 @@ protected boolean needCloseRegisterCenter() {
@Override
protected void close() throws Exception {
// Turn off the Eureka timer
final Class<?> discoveryClientClass = Thread.currentThread().getContextClassLoader()
final Class<?> discoveryClientClass = ClassLoaderManager.getContextClassLoaderOrUserClassLoader()
.loadClass("com.netflix.discovery.DiscoveryClient");
discoveryClientClass.getDeclaredMethod("shutdown").invoke(target);
LOGGER.warning("Eureka register center has been closed by user.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.sermant.registry.support;

import io.sermant.core.classloader.ClassLoaderManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.utils.ClassLoaderUtils;
Expand Down Expand Up @@ -74,7 +75,7 @@ private RegisterConfig getRegisterConfig() {
*/
protected final Class<?> getInstanceClass(String className) {
return cacheClasses.computeIfAbsent(className, fn -> {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
Class<?> result = null;
try {
result = ClassLoaderUtils.defineClass(className, contextClassLoader,
Expand Down

0 comments on commit c51416c

Please sign in to comment.