Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/sky #528

Merged
merged 5 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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