Skip to content

Commit aebae49

Browse files
authored
Merge pull request #1733 from chengyouling/develop-spi
Changed classloader to fixed the problem that classes cannot be loaded in the tomcat scenario
2 parents c272ccd + b5b4e80 commit aebae49

File tree

31 files changed

+105
-41
lines changed

31 files changed

+105
-41
lines changed

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/classloader/ClassLoaderManager.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class ClassLoaderManager {
4545

4646
private static FrameworkClassLoader frameworkClassLoader;
4747

48+
private static ClassLoader userClassLoader;
49+
4850
private ClassLoaderManager() {
4951
}
5052

@@ -88,6 +90,26 @@ public PluginClassLoader run() {
8890
});
8991
}
9092

93+
public static void setUserClassLoader(ClassLoader userClassLoader) {
94+
ClassLoaderManager.userClassLoader = userClassLoader;
95+
}
96+
97+
/**
98+
* get ContextClassLoader or UserClassLoader
99+
*
100+
* @return ClassLoader
101+
*/
102+
public static ClassLoader getContextClassLoaderOrUserClassLoader() {
103+
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
104+
if (classLoader != null) {
105+
return classLoader;
106+
}
107+
108+
// In some Tomcat scenarios, sermant cannot obtain the class loader of the current thread.
109+
// In this case, the host class loader is used to load classes.
110+
return userClassLoader;
111+
}
112+
91113
public static SermantClassLoader getSermantClassLoader() {
92114
return sermantClassLoader;
93115
}

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/agent/enhance/ClassLoaderLoadClassInterceptor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public ClassLoaderLoadClassInterceptor() {
4747

4848
@Override
4949
public ExecuteContext before(ExecuteContext context) throws Exception {
50+
ClassLoaderManager.setUserClassLoader((ClassLoader) context.getObject());
5051
return context;
5152
}
5253

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/classloader/PluginClassLoader.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.sermant.core.plugin.classloader;
1818

19+
import io.sermant.core.classloader.ClassLoaderManager;
1920
import io.sermant.core.common.LoggerFactory;
2021
import io.sermant.core.config.ConfigManager;
2122
import io.sermant.core.plugin.agent.config.AgentConfig;
@@ -133,9 +134,16 @@ public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundExce
133134

134135
private Class<?> getClassFromLocalClassLoader(String name) {
135136
ClassLoader loader = localLoader.get(Thread.currentThread().getId());
136-
137+
if (loader == null) {
138+
LOGGER.log(Level.FINE, "localLoader is null, thread name is {0}, classs name is {1}.",
139+
new Object[]{Thread.currentThread().getName(), name});
140+
}
137141
if (loader == null && useContextLoader) {
138-
loader = Thread.currentThread().getContextClassLoader();
142+
loader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
143+
if (loader == null) {
144+
LOGGER.log(Level.WARNING, "contextClassLoader is null, thread name is {0}, classs name is {1}.",
145+
new Object[]{Thread.currentThread().getName(), name});
146+
}
139147
}
140148
Class<?> clazz = null;
141149

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/plugin/subscribe/processor/IntegratedEventListenerAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package io.sermant.core.plugin.subscribe.processor;
1919

20+
import io.sermant.core.classloader.ClassLoaderManager;
2021
import io.sermant.core.service.dynamicconfig.common.DynamicConfigEvent;
2122
import io.sermant.core.service.dynamicconfig.common.DynamicConfigListener;
2223

@@ -43,7 +44,7 @@ public class IntegratedEventListenerAdapter implements DynamicConfigListener {
4344
public IntegratedEventListenerAdapter(ConfigProcessor processor, String rawGroup) {
4445
this.processor = processor;
4546
this.rawGroup = rawGroup;
46-
this.classLoader = Thread.currentThread().getContextClassLoader();
47+
this.classLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
4748
}
4849

4950
@Override
@@ -54,7 +55,7 @@ public void process(DynamicConfigEvent event) {
5455

5556
// The classloader at subscription time may not be the same as the classloader at listener configuration
5657
// time, so need to restore it
57-
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
58+
ClassLoader currentClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
5859
try {
5960
Thread.currentThread().setContextClassLoader(classLoader);
6061
processor.process(rawGroup, event);

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/ClassUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package io.sermant.core.utils;
1919

20+
import io.sermant.core.classloader.ClassLoaderManager;
2021
import io.sermant.core.common.LoggerFactory;
2122

2223
import java.io.IOException;
@@ -111,7 +112,7 @@ public static Optional<Class<?>> loadClass(String className, ClassLoader classLo
111112
public static Optional<Object> createInstance(String className, ClassLoader classLoader, Class<?>[] paramTypes) {
112113
ClassLoader curClassLoader = classLoader;
113114
if (curClassLoader == null) {
114-
curClassLoader = Thread.currentThread().getContextClassLoader();
115+
curClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
115116
}
116117
try {
117118
final Class<?> clazz = curClassLoader.loadClass(className);

sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/ReflectUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package io.sermant.core.utils;
1919

20+
import io.sermant.core.classloader.ClassLoaderManager;
2021
import io.sermant.core.common.LoggerFactory;
2122

2223
import java.lang.reflect.AccessibleObject;
@@ -166,7 +167,7 @@ private static Optional<Class<?>> loadClass(String className) {
166167
return Optional.empty();
167168
}
168169
return CLASS_CACHE.computeIfAbsent(className, value -> {
169-
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
170+
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
170171
try {
171172
return Optional.ofNullable(contextClassLoader.loadClass(className));
172173
} catch (ClassNotFoundException ignored) {

sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/config/SermantYamlConstructor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.sermant.implement.config;
1818

19+
import io.sermant.core.classloader.ClassLoaderManager;
1920
import io.sermant.core.exception.SermantRuntimeException;
2021

2122
import org.yaml.snakeyaml.LoaderOptions;
@@ -35,7 +36,7 @@ public class SermantYamlConstructor extends Constructor {
3536
*/
3637
public SermantYamlConstructor() {
3738
super(Object.class, new LoaderOptions());
38-
loader = Thread.currentThread().getContextClassLoader();
39+
loader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
3940
}
4041

4142
/**

sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/dynamicconfig/nacos/NacosBufferedClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.alibaba.nacos.api.exception.NacosException;
2323
import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
2424

25+
import io.sermant.core.classloader.ClassLoaderManager;
2526
import io.sermant.core.common.LoggerFactory;
2627
import io.sermant.core.config.ConfigManager;
2728
import io.sermant.core.service.dynamicconfig.config.DynamicConfig;
@@ -229,7 +230,7 @@ private Properties createProperties(String connectString, int sessionTimeout, St
229230
* @throws NacosInitException Connect to Nacos failed
230231
*/
231232
private void createNacosClient(String connectString, Properties properties) {
232-
ClassLoader tempClassLoader = Thread.currentThread().getContextClassLoader();
233+
ClassLoader tempClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
233234
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
234235
try {
235236
nacosClient = new NacosClient(properties);

sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/main/java/io/sermant/dynamic/config/inject/DynamicClassInjectDefine.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package io.sermant.dynamic.config.inject;
1919

20+
import io.sermant.core.classloader.ClassLoaderManager;
2021
import io.sermant.core.plugin.config.PluginConfigManager;
2122
import io.sermant.core.service.inject.ClassInjectDefine;
2223
import io.sermant.core.utils.ClassUtils;
@@ -42,6 +43,7 @@ public Plugin plugin() {
4243
@Override
4344
public boolean canInject() {
4445
return PluginConfigManager.getPluginConfig(DynamicConfiguration.class).isEnableDynamicConfig()
45-
&& ClassUtils.loadClass(REFRESH_CLASS, Thread.currentThread().getContextClassLoader()).isPresent();
46+
&& ClassUtils.loadClass(REFRESH_CLASS, ClassLoaderManager.getContextClassLoaderOrUserClassLoader())
47+
.isPresent();
4648
}
4749
}

sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/main/java/io/sermant/dynamic/config/interceptors/SpringFactoriesInterceptor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package io.sermant.dynamic.config.interceptors;
1919

20+
import io.sermant.core.classloader.ClassLoaderManager;
2021
import io.sermant.core.common.LoggerFactory;
2122
import io.sermant.core.plugin.agent.entity.ExecuteContext;
2223
import io.sermant.core.service.ServiceManager;
@@ -94,7 +95,7 @@ private boolean isHasMethodLoadSpringFactories() {
9495

9596
private void injectConfigurationsWithLowVersion(Object result, String factoryName) {
9697
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
97-
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
98+
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
9899
if (result instanceof List) {
99100
final List<String> convertedResult = (List<String>) result;
100101
CLASS_DEFINES.forEach(classInjectDefine -> {
@@ -108,7 +109,7 @@ private void injectConfigurationsWithLowVersion(Object result, String factoryNam
108109

109110
private void injectConfigurations(Object result) {
110111
final ClassInjectService service = ServiceManager.getService(ClassInjectService.class);
111-
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
112+
final ClassLoader contextClassLoader = ClassLoaderManager.getContextClassLoaderOrUserClassLoader();
112113
final boolean isMultiValueMap = result instanceof MultiValueMap;
113114
if (result instanceof Map) {
114115
// spring 高版本处理, 针对List其为不可变list,需做一层处理

0 commit comments

Comments
 (0)