ChildFirstClassLoader (#1873)

* ChildFirstClassLoader

* Lint

* ChildFirstURLClassLoader

* Fix reference
This commit is contained in:
Mitchell Syer
2026-01-29 18:48:33 -05:00
committed by GitHub
parent 35bcbc69a2
commit 146290283f
2 changed files with 91 additions and 1 deletions

View File

@@ -0,0 +1,90 @@
package suwayomi.tachidesk.manga.impl.util
import java.io.IOException
import java.io.InputStream
import java.net.URL
import java.net.URLClassLoader
import java.util.Enumeration
/**
* A parent-last class loader that will try in order:
* - the system class loader
* - the child class loader
* - the parent class loader.
*/
class ChildFirstURLClassLoader(
urls: Array<URL>,
parent: ClassLoader? = null,
) : URLClassLoader(urls, parent) {
private val systemClassLoader: ClassLoader? = getSystemClassLoader()
override fun loadClass(
name: String?,
resolve: Boolean,
): Class<*> {
var c = findLoadedClass(name)
if (c == null && systemClassLoader != null) {
try {
c = systemClassLoader.loadClass(name)
} catch (_: ClassNotFoundException) {
}
}
if (c == null) {
c =
try {
findClass(name)
} catch (_: ClassNotFoundException) {
super.loadClass(name, resolve)
}
}
if (resolve) {
resolveClass(c)
}
return c
}
override fun getResource(name: String?): URL? =
systemClassLoader?.getResource(name)
?: findResource(name)
?: super.getResource(name)
override fun getResources(name: String?): Enumeration<URL> {
val systemUrls = systemClassLoader?.getResources(name)
val localUrls = findResources(name)
val parentUrls = parent?.getResources(name)
val urls =
buildList {
while (systemUrls?.hasMoreElements() == true) {
add(systemUrls.nextElement())
}
while (localUrls?.hasMoreElements() == true) {
add(localUrls.nextElement())
}
while (parentUrls?.hasMoreElements() == true) {
add(parentUrls.nextElement())
}
}
return object : Enumeration<URL> {
val iterator = urls.iterator()
override fun hasMoreElements() = iterator.hasNext()
override fun nextElement() = iterator.next()
}
}
override fun getResourceAsStream(name: String?): InputStream? {
return try {
getResource(name)?.openStream()
} catch (_: IOException) {
return null
}
}
}

View File

@@ -156,7 +156,7 @@ object PackageTools {
): Any {
try {
logger.debug { "loading jar with path: $jarPath" }
val classLoader = jarLoaderMap[jarPath] ?: URLClassLoader(arrayOf<URL>(Path(jarPath).toUri().toURL()))
val classLoader = jarLoaderMap[jarPath] ?: ChildFirstURLClassLoader(arrayOf<URL>(Path(jarPath).toUri().toURL()))
val classToLoad = Class.forName(className, false, classLoader)
jarLoaderMap[jarPath] = classLoader