Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the bug that host classes could be loaded from the plugin class loader. #1353

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 All @@ -110,19 +139,23 @@ public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundExce
* @throws ClassNotFoundException 无法通过类加载
*/
public Class<?> loadSermantClass(String name) throws ClassNotFoundException {
Class<?> clazz = null;
synchronized (getClassLoadingLock(name)) {
Class<?> clazz = loadPluginClass(name);

try {
clazz = super.loadClass(name, false);
} catch (ClassNotFoundException ignored) {
// 无法找到类,忽略,后续抛出异常
}
if (clazz == null) {
try {
clazz = super.loadClass(name, false);
} catch (ClassNotFoundException ignored) {
// 无法找到类,忽略,后续抛出异常
}
}

// 如果无法找到类,则抛出异常
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);
}
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
Loading