1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-25 13:03:35 +08:00

Fix DynLibClassLoader class resolving logic

This commit is contained in:
Karlatemp 2022-05-23 18:20:45 +08:00
parent 237320317e
commit 72d248f1e6
No known key found for this signature in database
GPG Key ID: BA173CA2B9956C59
3 changed files with 37 additions and 12 deletions
mirai-console/backend
integration-test
src
testers/plugin-resolve-self-dependencies-over-console-ones/src
mirai-console/src/internal/plugin

View File

@ -39,6 +39,19 @@ public fun File.assertNotExists() {
fail { "Except ${this.absolutePath} not exists but this file exists in disk" }
}
}
public fun assertClassSame(expected: Class<*>?, actually: Class<*>?) {
fun vt(c: Class<*>?): String {
if (c == null) return "<null>"
return "$c from ${c.classLoader}"
}
if (expected === actually) return
fail {
"Class not same:\n" +
"Class excepted: ${vt(expected)}\n" +
"Class actually: ${vt(actually)}"
}
}
// endregion
// region JVM Utils
@ -48,7 +61,7 @@ public val vmClassfileVersion: Int = runCatching {
classobj.version
}.recoverCatching {
val ccl = object : ClassLoader(null) {
fun canLoad(ver: Int) : Boolean{
fun canLoad(ver: Int): Boolean {
val klass = ClassWriter(ClassWriter.COMPUTE_MAXS)
val cname =
"net/mamoe/console/integrationtest/vtest/C${ver}_${System.currentTimeMillis()}_${UUID.randomUUID()}"

View File

@ -12,6 +12,7 @@ package pluginresolveselfdepoverconsoleones
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.ktor.client.plugins.resources.*
import net.mamoe.console.integrationtest.assertClassSame
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import net.mamoe.mirai.utils.info
@ -27,5 +28,7 @@ public class PluginResolveSelfDependenciesOverConsoleOnes :
install(Resources)
}.toString()
}
val hcC = Class.forName("io.ktor.client.HttpClient")
assertClassSame(hcC, jvmPluginClassLoaderAccess.pluginIndependentLibrariesClassLoader.loadClass(hcC.name))
}
}

View File

@ -79,6 +79,22 @@ internal class DynLibClassLoader : URLClassLoader {
else -> DynLibClassLoader(parent, clName)
}
}
fun tryFastOrStrictResolve(name: String): Class<*>? {
if (name.startsWith("java.")) return Class.forName(name, false, JavaSystemPlatformClassLoader)
// All mirai-core hard-linked should use same version to avoid errors (ClassCastException).
if (name.startsWith("io.netty") || name in AllDependenciesClassesHolder.allclasses) {
return AllDependenciesClassesHolder.appClassLoader.loadClass(name)
}
if (name.startsWith("net.mamoe.mirai.")) { // Avoid plugin classing cheating
try {
return AllDependenciesClassesHolder.appClassLoader.loadClass(name)
} catch (ignored: ClassNotFoundException) {
}
}
return null
}
}
internal fun loadClassInThisClassLoader(name: String): Class<*>? {
@ -142,7 +158,8 @@ internal class DynLibClassLoader : URLClassLoader {
}
override fun loadClass(name: String, resolve: Boolean): Class<*> {
if (name.startsWith("java.")) return Class.forName(name, false, JavaSystemPlatformClassLoader)
tryFastOrStrictResolve(name)?.let { return it }
val pt = this.parent
val topPt: ClassLoader? = if (pt is DynLibClassLoader) {
pt.findButNoSystem(name)?.let { return it }
@ -331,16 +348,8 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
override fun loadClass(name: String, resolve: Boolean): Class<*> = loadClass(name)
override fun loadClass(name: String): Class<*> {
if (name.startsWith("java.")) return Class.forName(name, false, JavaSystemPlatformClassLoader)
if (name.startsWith("io.netty") || name in AllDependenciesClassesHolder.allclasses) {
return AllDependenciesClassesHolder.appClassLoader.loadClass(name)
}
if (name.startsWith("net.mamoe.mirai.")) { // Avoid plugin classing cheating
try {
return AllDependenciesClassesHolder.appClassLoader.loadClass(name)
} catch (ignored: ClassNotFoundException) {
}
}
DynLibClassLoader.tryFastOrStrictResolve(name)?.let { return it }
sharedLibrariesLogger.loadClassInThisClassLoader(name)?.let { return it }
// Search dependencies first