Skip to content

Commit

Permalink
6.2.2 主要涉及加载逻辑的改动
Browse files Browse the repository at this point in the history
Dev/sky
  • Loading branch information
Bkm016 authored Jan 6, 2025
2 parents 771bcf3 + 163c89f commit 8cc3ab4
Show file tree
Hide file tree
Showing 32 changed files with 622 additions and 127 deletions.
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ subprojects {
compileOnly("com.google.guava:guava:21.0")
compileOnly("com.google.code.gson:gson:2.8.7")
compileOnly("org.apache.commons:commons-lang3:3.5")
compileOnly("org.tabooproject.reflex:reflex:1.1.7")
compileOnly("org.tabooproject.reflex:analyser:1.1.7")
compileOnly("org.tabooproject.reflex:reflex:1.1.8")
compileOnly("org.tabooproject.reflex:analyser:1.1.8")
// 测试依赖
testImplementation(kotlin("stdlib"))
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
testImplementation("com.google.guava:guava:21.0")
testImplementation("com.google.code.gson:gson:2.8.7")
testImplementation("org.apache.commons:commons-lang3:3.5")
testImplementation("org.tabooproject.reflex:reflex:1.1.7")
testImplementation("org.tabooproject.reflex:analyser:1.1.7")
testImplementation("org.tabooproject.reflex:reflex:1.1.8")
testImplementation("org.tabooproject.reflex:analyser:1.1.8")
}

java {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class RuntimeEnv {
* 用于初始化 Kotlin 环境
*/
static void init() {
PrimitiveIO.debug("RuntimeEnv loaded in {0}ms.", TabooLib.execution(() -> {
PrimitiveIO.debug("RuntimeEnv 加载完成,用时 {0} 毫秒。", TabooLib.execution(() -> {
List<JarRelocation> rel = new ArrayList<>();
boolean loadKotlin = !KOTLIN_VERSION.equals("null");
boolean loadKotlinCoroutines = !KOTLIN_COROUTINES_VERSION.equals("null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
* @since 2024/7/20 20:31
*/
@SuppressWarnings("deprecation")

public class AetherResolver {

private static final Map<String, AetherResolver> resolverMap = Maps.newConcurrentMap();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package taboolib.common.platform

import org.tabooproject.reflex.serializer.BinarySerializable
import org.tabooproject.reflex.serializer.BinaryWriter

class AwakeClass(val name: String, val isClassVisitor: Boolean, val platformService: List<String>) : BinarySerializable {

override fun writeTo(writer: BinaryWriter) {
writer.writeNullableString(name)
writer.writeBoolean(isClassVisitor)
writer.writeList(platformService) { writer.writeNullableString(it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package taboolib.common.platform

import taboolib.common.LifeCycle
import taboolib.common.PrimitiveIO
import taboolib.common.PrimitiveSettings
import taboolib.common.TabooLib
import org.tabooproject.reflex.ReflexClass
import org.tabooproject.reflex.serializer.BinaryReader
import org.tabooproject.reflex.serializer.BinaryWriter
import taboolib.common.*
import taboolib.common.env.RuntimeEnv
import taboolib.common.inject.ClassVisitor
import taboolib.common.inject.ClassVisitorHandler
import taboolib.common.io.runningClassMapInJar
import taboolib.common.io.runningClasses
import taboolib.common.io.runningClassesWithoutLibrary
import taboolib.common.io.runningExactClasses
import taboolib.common.io.*
import taboolib.common.platform.function.registerLifeCycleTask
import taboolib.common.platform.function.unregisterCommands
import taboolib.common.util.t
import java.util.concurrent.ConcurrentHashMap

@Suppress("UNCHECKED_CAST")
Expand Down Expand Up @@ -50,51 +48,10 @@ object PlatformFactory {
}

val time = System.nanoTime()
var injected = 0
// 加载运行环境
for (cls in includedClasses) {
try {
injected += RuntimeEnv.ENV.inject(cls)
} catch (_: NoClassDefFoundError) {
} catch (ex: Throwable) {
ex.printStackTrace()
}
}

// 加载接口
for (cls in includedClasses) {
// 插件实例
if (cls.structure.superclass?.name == Plugin::class.java.name) {
Plugin.setInstance((cls.getInstance() ?: cls.newInstance()) as Plugin)
}
// 自唤醒
if (cls.hasAnnotation(Awake::class.java)) {
val instance = cls.getInstance() ?: cls.newInstance()
if (instance != null) {
// 依赖注入接口
if (ClassVisitor::class.java.isInstance(instance)) {
ClassVisitorHandler.register(instance as ClassVisitor)
}
// 平台服务
cls.interfaces.filter { it.hasAnnotation(PlatformService::class.java) }.forEach {
serviceMap[it.name!!] = instance
}
awokenMap[cls.name!!] = instance
} else {
PrimitiveIO.error("Failed to awake class: ${cls.name}")
}
}
}

// 调试信息
if (PrimitiveSettings.IS_DEBUG_MODE) {
PrimitiveIO.debug("PlatformFactory initialized. ({0}ms)", (System.nanoTime() - time) / 1_000_000)
PrimitiveIO.debug("Awakened: {0}", awokenMap.size)
PrimitiveIO.debug("Injected: {0}", injected)
PrimitiveIO.debug("Service : {0}", serviceMap.size)
serviceMap.forEach { (k, v) ->
PrimitiveIO.debug(" = {0} ({1})", k.substringAfterLast('.'), v.javaClass.simpleName)
}
// 是否有缓存
val useCache = BinaryCache.read("inject/platform", BinaryCache.primarySrcVersion) { injectByCache(it, time) }
if (useCache == null) {
inject(includedClasses, time)
}
}

Expand Down Expand Up @@ -154,4 +111,117 @@ object PlatformFactory {
inline fun <reified T : Any> registerService(instance: T) {
serviceMap[T::class.java.name] = instance
}

private fun injectByCache(bytes: ByteArray, time: Long) {
val reader = BinaryReader(bytes)
// 依赖注入
reader.readList { reader.readString() }.forEach { RuntimeEnv.ENV.inject(runningClassMap[it]!!) }

// 代理主类
val mainName = reader.readNullableString()
if (mainName != null) {
val main = runningClassMap[mainName]!!
Plugin.setInstance((main.getInstance() ?: main.newInstance()) as Plugin)
}

// 自唤醒
reader.readList {
AwakeClass(reader.readString(), reader.readBoolean(), reader.readList { reader.readString() })
}.forEach {
val cls = runningClassMap[it.name]!!
val instance = cls.getInstance() ?: cls.newInstance()
// 是依赖注入接口
if (it.isClassVisitor) {
ClassVisitorHandler.register(instance as ClassVisitor)
}
// 是平台服务
it.platformService.forEach { name ->
serviceMap[name] = instance!!
}
awokenMap[it.name] = instance!!
}

// 调试信息
if (PrimitiveSettings.IS_DEBUG_MODE) {
PrimitiveIO.debug("跨平台服务初始化完成,用时 {0} 毫秒。(使用 BinaryCache)", (System.nanoTime() - time) / 1_000_000)
}
}

private fun inject(includedClasses: Set<ReflexClass>, time: Long) {
var injected = 0
val writer = BinaryWriter()

val envList = arrayListOf<String>()
var main: String? = null
val awakeClassList = arrayListOf<AwakeClass>()

// 加载运行环境
for (cls in includedClasses) {
try {
val i = RuntimeEnv.ENV.inject(cls)
if (i > 0) {
injected += i
envList += cls.name!!
}
} catch (_: NoClassDefFoundError) {
} catch (ex: Throwable) {
ex.printStackTrace()
}
}

// 加载接口
for (cls in includedClasses) {
// 插件实例
if (cls.structure.superclass?.name == Plugin::class.java.name) {
Plugin.setInstance((cls.getInstance() ?: cls.newInstance()) as Plugin)
main = cls.name
}
// 自唤醒
if (cls.hasAnnotation(Awake::class.java)) {
val instance = cls.getInstance() ?: cls.newInstance()
if (instance != null) {
// 依赖注入接口
var isClassVisitor = false
if (ClassVisitor::class.java.isInstance(instance)) {
isClassVisitor = true
ClassVisitorHandler.register(instance as ClassVisitor)
}
// 平台服务
val platformService = arrayListOf<String>()
cls.interfaces.filter { it.hasAnnotation(PlatformService::class.java) }.forEach {
platformService += it.name!!
serviceMap[it.name!!] = instance
}
awokenMap[cls.name!!] = instance
awakeClassList += AwakeClass(cls.name!!, isClassVisitor, platformService)
} else {
PrimitiveIO.error(
"""
无法激活 ${cls.name} 的 @Awake 注解
Failed to enforce @Awake annotation on ${cls.name}
""".t()
)
}
}
}

// 写入缓存
writer.writeList(envList) { writer.writeNullableString(it) }
writer.writeNullableString(main)
writer.writeList(awakeClassList)

// 保存缓存
BinaryCache.save("inject/platform", BinaryCache.primarySrcVersion, writer.toByteArray())

// 调试信息
if (PrimitiveSettings.IS_DEBUG_MODE) {
PrimitiveIO.debug("跨平台服务初始化完成,用时 {0} 毫秒。", (System.nanoTime() - time) / 1_000_000)
PrimitiveIO.debug(" 唤醒: {0}", awokenMap.size)
PrimitiveIO.debug(" 注入: {0}", injected)
PrimitiveIO.debug(" 服务: {0}", serviceMap.size)
serviceMap.forEach { (k, v) ->
PrimitiveIO.debug(" = {0} ({1})", k.substringAfterLast('.'), v.javaClass.simpleName)
}
}
}
}
8 changes: 4 additions & 4 deletions common-reflex/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

dependencies {
implementation("org.tabooproject.reflex:reflex:1.1.7")
implementation("org.tabooproject.reflex:analyser:1.1.7")
implementation("org.tabooproject.reflex:reflex:1.1.8")
implementation("org.tabooproject.reflex:analyser:1.1.8")
}

tasks {
withType<ShadowJar> {
dependencies {
include(dependency("org.tabooproject.reflex:reflex:1.1.7"))
include(dependency("org.tabooproject.reflex:analyser:1.1.7"))
include(dependency("org.tabooproject.reflex:reflex:1.1.8"))
include(dependency("org.tabooproject.reflex:analyser:1.1.8"))
}
relocate("org.taboooproject", "taboolib.library")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void init() {
// 注册任务
TabooLib.registerLifeCycleTask(lifeCycle, priority, () -> ClassVisitorHandler.injectAll(lifeCycle));
}
PrimitiveIO.debug("ClassVisitorHandler initialized.");
PrimitiveIO.debug("ClassVisitorHandler 初始化完成。");
}

/**
Expand Down Expand Up @@ -72,7 +72,7 @@ public static Set<ReflexClass> getClasses() {
}
classes = cache;
});
PrimitiveIO.debug("ClassVisitor loaded {0} classes. ({1}ms)", classes.size(), time);
PrimitiveIO.debug("ClassVisitor 收集到 {0} 个有效类,用时 {1} 毫秒。", classes.size(), time);
}
return classes;
}
Expand Down
78 changes: 78 additions & 0 deletions common-util/src/main/kotlin/taboolib/common/BinaryCache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package taboolib.common

import taboolib.common.io.digest
import taboolib.common.io.groupId
import taboolib.common.io.newFile
import taboolib.common.util.t
import java.io.File

object BinaryCache {

val primarySrcVersion = try {
File(BinaryCache::class.java.getProtectionDomain().codeSource.location.file).digest()
} catch (ex: Throwable) {
"unknown"
}

fun <T> read(name: String, version: String, block: (bytes: ByteArray) -> T): T? {
// 是否有缓存文件
val cacheFile = getCacheFile().resolve("binary/${name}.cache")
if (cacheFile.exists()) {
// 检查版本
val metaFile = getCacheFile().resolve("binary/${name}.cache.sha1")
val sha1 = if (metaFile.exists()) metaFile.readText() else ""
if (sha1 == version) {
// 从缓存中读取
try {
return block(cacheFile.readBytes())
} catch (ex: Throwable) {
PrimitiveIO.warning(
"""
无法从缓存文件 "${cacheFile.name}" 中读取类信息。
Failed to read class information from cache file "${cacheFile.name}".
""".t()
)
ex.printStackTrace()
drop(name)
}
}
}
return null
}

fun save(name: String, version: String, bytes: ByteArray) = save(name, version) { bytes }

fun save(name: String, version: String, block: () -> ByteArray) {
val cacheFile = getCacheFile().resolve("binary/${name}.cache")
val metaFile = getCacheFile().resolve("binary/${name}.cache.sha1")
try {
newFile(cacheFile).writeBytes(block())
newFile(metaFile).writeText(version)
} catch (ex: Throwable) {
PrimitiveIO.warning(
"""
无法将类信息写入缓存文件 "${cacheFile.name}"。
Failed to write class information to cache file "${cacheFile.name}".
""".t()
)
ex.printStackTrace()
}
}

fun drop(name: String) {
try {
getCacheFile().resolve("binary/${name}.cache").delete()
getCacheFile().resolve("binary/${name}.cache.sha1").delete()
} catch (ex: Throwable) {
ex.printStackTrace()
}
}

fun getCacheFile(): File {
val file = File("cache/taboolib/${groupId}")
if (!file.exists()) {
file.mkdirs()
}
return file
}
}
Loading

0 comments on commit 8cc3ab4

Please sign in to comment.