Skip to content

Commit

Permalink
修复可以从插件类加载器中加载到宿主类的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
luanwenfei-venus committed Nov 2, 2023
1 parent a1308ed commit baf706a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;

/**
* 加载插件主模块的类加载器
Expand All @@ -37,6 +38,11 @@ public class PluginClassLoader extends URLClassLoader {
*/
private final boolean useContextLoader;

/**
* 对ClassLoader内部已加载的Class的管理
*/
private final Map<String, Class<?>> pluginClassMap = new HashMap<>();

/**
* 构造方法
*
Expand All @@ -48,6 +54,23 @@ public PluginClassLoader(URL[] urls, ClassLoader parent) {
useContextLoader = ConfigManager.getConfig(AgentConfig.class).isUseContextLoader();
}

/**
* 加载插件服务包中的类并维护
*
* @param name 全限定名
* @return Class对象
*/
private Class<?> loadPluginClass(String name) {
if (!pluginClassMap.containsKey(name)) {
try {
pluginClassMap.put(name, findClass(name));
} catch (ClassNotFoundException ignored) {
pluginClassMap.put(name, null);
}
}
return pluginClassMap.get(name);
}

/**
* 向类加载器中添加类的搜索路径
*
Expand All @@ -64,42 +87,48 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {

@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = null;
synchronized (getClassLoadingLock(name)) {
Class<?> clazz = loadPluginClass(name);

try {
clazz = super.loadClass(name, resolve);
} catch (ClassNotFoundException ignored) {
// ignored
}
// 自身无法加载类,则通过Sermant搜索路径中加载
if (clazz == null) {
try {
clazz = super.loadClass(name, resolve);
} catch (ClassNotFoundException ignored) {
// 捕获类找不到的异常,下一步会进入localLoader中去加载类
// ignored
}
}

// 无法从Sermant搜索路径中找到类,则尝试通过线程绑定的局部类加载器加载
if (clazz == null) {
ClassLoader loader = localLoader.get(Thread.currentThread().getId());
// 无法从Sermant搜索路径中找到类,则尝试通过线程绑定的局部类加载器加载
if (clazz == null) {
ClassLoader loader = localLoader.get(Thread.currentThread().getId());

if (loader == null && useContextLoader) {
loader = Thread.currentThread().getContextClassLoader();
}
if (loader == null && useContextLoader) {
loader = Thread.currentThread().getContextClassLoader();
}

// 确保局部类加载器不是当前类加载器,否则会stackoverflow
if (loader != null && !this.equals(loader)) {
try {
clazz = loader.loadClass(name);
} catch (ClassNotFoundException e) {
// 无法找到类,忽略,后续抛出异常
// 确保局部类加载器不是当前类加载器,否则会stackoverflow
if (loader != null && !this.equals(loader)) {
try {
clazz = loader.loadClass(name);
} catch (ClassNotFoundException e) {
// 无法找到类,忽略,后续抛出异常
}
}
}
}

// 如果无法找到类,则抛出异常
if (clazz == null) {
throw new ClassNotFoundException("Sermant pluginClassLoader can not load class: " + name);
}
// 如果无法找到类,则抛出异常
if (clazz == null) {
throw new ClassNotFoundException("Sermant pluginClassLoader can not load class: " + name);
}

// 如果有需要则解析该类
if (resolve) {
resolveClass(clazz);
// 如果有需要则解析该类
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
return clazz;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public ServiceClassLoader(URL[] urls, ClassLoader parent) {
* @param name 全限定名
* @return Class对象
*/
private Class<?> loadPluginClass(String name) {
private Class<?> loadServiceClass(String name) {
if (!serviceClassMap.containsKey(name)) {
try {
serviceClassMap.put(name, findClass(name));
Expand All @@ -74,7 +74,7 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class<?> clazz = loadPluginClass(name);
Class<?> clazz = loadServiceClass(name);
if (clazz == null) {
clazz = super.loadClass(name, resolve);

Expand Down

0 comments on commit baf706a

Please sign in to comment.