我有 3 个类加载器:
- 主加载器
- 预加载加载器
- 游戏场景加载器
在整个程序执行过程中只有一个MainLoader实例,但PreloadingLoader和GameSceneLoader可以按需重新创建。
当我在程序中加载任何类时,我想:
- 如果类名以任何开头,则使用MainLoader
staticClasses
加载它 - 如果类名以任何开头,则使用PreloadingLoader
preloadingClasses
加载它 - 如果类名存在
pl.gieted.flappy_bird
但未在上述列表中列出,则使用GameSceneLoader加载它 - 否则使用默认的类加载器加载它
下面的代码有效,但仅适用于加载的第一个类,例如:
pl.gieted.flappy_bird.engine.Renderer
由GameSceneLoader请求- MainLoader尝试加载它,因为它是GameSceneLoader最古老的父级
- 有
Renderer
一个类依赖LoadingScene
- 由于
Renderer
是使用MainLoader加载的,因此Loading Scene
也正在使用MainLoader加载,但是找不到它。 java.lang.NoClassDefFoundError
被抛出。
我想要发生的是:
pl.gieted.flappy_bird.engine.Renderer
由GameSceneLoader请求- MainLoader尝试加载它,因为它是GameSceneLoader最古老的父级
- 有
Renderer
一个类依赖LoadingScene
- 的加载
LoadingScene
被传回GameSceneLoader - MainLoader找不到它。
- PreloadingLoader找到并加载它
- 加载继续...
val mainClassLoader = object : URLClassLoader(arrayOf(File(classesUrl).toURI().toURL()), null) {
val staticClasses = listOf(
"pl.gieted.flappy_bird.engine.Renderer",
"pl.gieted.flappy_bird.engine.Processing",
"pl.gieted.flappy_bird.engine.Scene",
"pl.gieted.flappy_bird.engine.LifecycleElement",
)
override fun findClass(name: String): Class<*>? {
return when {
staticClasses.any { name.startsWith(it) } -> super.findClass(name)
name.startsWith("pl.gieted.flappy_bird") -> null
else -> this::class.java.classLoader.loadClass(name)
}
}
}
var preloadingLoader = object : URLClassLoader(arrayOf(File(classesUrl).toURI().toURL()), mainClassLoader) {
val preloadingClasses = listOf(
"pl.gieted.flappy_bird.game.LoadingScene",
"pl.gieted.flappy_bird.game.FlappyBirdResourceLoader",
"pl.gieted.flappy_bird.game.Resources",
)
override fun findClass(name: String): Class<*>? {
return when {
preloadingClasses.any { name.startsWith(it) } -> super.findClass(name)
else -> null
}
}
}
var gameSceneLoader = URLClassLoader(arrayOf(File(classesUrl).toURI().toURL()), preloadingLoader)
val rendererClass = gameSceneLoader.loadClass("pl.gieted.flappy_bird.engine.Renderer")
如何实现这样的事情?
这些示例是用 Kotlin 编写的,但是您可以毫无问题地用 Java 回答我。