Merge pull request #35 from Sincky/master

change PluginsClassLoader and fix 'loader constraint violation'
This commit is contained in:
NaturalHG 2020-04-06 22:46:49 +08:00 committed by GitHub
commit cdc7ab3c15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,7 +3,7 @@ package net.mamoe.mirai.console.plugins
import java.io.File import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
internal class PluginsClassLoader(parent: ClassLoader) : ClassLoader(parent) { internal class PluginsClassLoader(private val parent: ClassLoader) {
private val pluginLoaders = mutableMapOf<String, PluginClassLoader>() private val pluginLoaders = mutableMapOf<String, PluginClassLoader>()
/** /**
@ -15,7 +15,6 @@ internal class PluginsClassLoader(parent: ClassLoader) : ClassLoader(parent) {
} }
} }
/** /**
* 清除所有插件加载器 * 清除所有插件加载器
*/ */
@ -35,43 +34,44 @@ internal class PluginsClassLoader(parent: ClassLoader) : ClassLoader(parent) {
return true return true
} }
override fun loadClass(name: String): Class<*>? { fun loadClass(name: String): Class<*>? {
var c: Class<*>? = null var c: Class<*>? = null
// 循环插件classloader loadClass // 循环插件classloader loadClass
pluginLoaders.values.forEach { pluginLoaders.values.forEach {
it.runCatching { try{
c = this.loadClass(name) c = it.loadClass(name)
return@forEach return@forEach
} }catch (e : ClassNotFoundException){/*nothing*/}
} }
// 如果为null交给mirai的classloader进行加载 if(c == null){
if (c == null) { throw ClassNotFoundException("PluginsClassLoader can't load this class:${name}")
c = parent.loadClass(name) // 如果无法加载这个类,这里会抛异常
} }
return c return c
} }
fun loadDependClass(name: String): Class<*>? { fun loadDependClass(name: String): Class<*>? {
var c: Class<*>? = null var c: Class<*>? = null
// 依赖问题先交给mirai ClassLoader来处理
runCatching { // 依赖问题先交给MiraiClassLoader来处理
try {
c = parent.loadClass(name) c = parent.loadClass(name)
} }catch (e : ClassNotFoundException){/*nothing*/}
// 如果mirai加载不了依赖则交给插件的classloader进行加载
// 然后再交给插件的classloader来加载依赖
if (c == null) { if (c == null) {
pluginLoaders.values.forEach { pluginLoaders.values.forEach {
it.runCatching { try {
c = this.loadDependClass(name) c = it.loadDependClass(name)
return@forEach return@forEach
} }catch (e : ClassNotFoundException){/*nothing*/}
} }
} }
return c return c
} }
} }
internal class PluginClassLoader(files: File, parent: PluginsClassLoader?) : internal class PluginClassLoader(files: File,private val parent: PluginsClassLoader) :
URLClassLoader(arrayOf((files.toURI().toURL())), parent) { URLClassLoader(arrayOf((files.toURI().toURL()))) {
override fun loadClass(name: String): Class<*>? { override fun loadClass(name: String): Class<*>? {
synchronized(getClassLoadingLock(name)) { synchronized(getClassLoadingLock(name)) {
@ -79,11 +79,11 @@ internal class PluginClassLoader(files: File, parent: PluginsClassLoader?) :
var c = findLoadedClass(name) var c = findLoadedClass(name)
if (c == null) { if (c == null) {
c = try { c = try {
// 自己尝试加载 // 父类去加载本插件的依赖
this.findClass(name) //ClassNotFoundException parent.loadDependClass(name)
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
// 交给父类去加载非本插件的依赖 // 自己加载本插件按理说只有本插件的ClassName会到达这里
(this.parent as PluginsClassLoader).loadDependClass(name) this.findClass(name)//ClassNotFoundException or java.lang.LinkageError
} }
} }
return c return c
@ -94,7 +94,7 @@ internal class PluginClassLoader(files: File, parent: PluginsClassLoader?) :
synchronized(getClassLoadingLock(name)) { synchronized(getClassLoadingLock(name)) {
var c = findLoadedClass(name) var c = findLoadedClass(name)
if (c == null) { if (c == null) {
// 加载依赖,没有则丢出异常 // 加载依赖,没有则丢出异常
c = this.findClass(name) // ClassNotFoundException c = this.findClass(name) // ClassNotFoundException
} }
return c return c