Skip to content

Commit

Permalink
[6.1.0][dev] 修复 ISOLATED_MODE 无法使用的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
Bkm016 committed Feb 5, 2024
1 parent 444b498 commit 9eaa917
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 83 deletions.
24 changes: 12 additions & 12 deletions common-env/src/main/java/taboolib/common/env/RuntimeEnv.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import taboolib.common.*;
import taboolib.common.ClassAppender;
import taboolib.common.PrimitiveIO;
import taboolib.common.PrimitiveSettings;
import taboolib.common.TabooLib;

import java.io.File;
import java.io.FileOutputStream;
Expand Down Expand Up @@ -38,17 +41,14 @@ public class RuntimeEnv {

static void init() throws Throwable {
List<JarRelocation> rel = new ArrayList<>();
// 在非隔离模式对 Kotlin 进行重定向
if (!PrimitiveSettings.IS_ISOLATED_MODE) {
// 其他 TabooLib 插件可能加载了相同版本的 Kotlin 环境,因此无需重复加载
if (TabooLib.isKotlinEnvironment()) {
return;
}
// 启用 Kotlin 重定向
if (!PrimitiveSettings.SKIP_KOTLIN_RELOCATE) {
rel.add(new JarRelocation(KOTLIN_ID + ".", KOTLIN_ID + PrimitiveSettings.formatVersion(KOTLIN_VERSION) + "."));
rel.add(new JarRelocation(KOTLIN_COROUTINES_ID + ".", KOTLIN_COROUTINES_ID + PrimitiveSettings.formatVersion(KOTLIN_COROUTINES_VERSION) + "."));
}
// 在非隔离模式下检查 Kotlin 环境
if (!PrimitiveSettings.IS_ISOLATED_MODE && TabooLib.isKotlinEnvironment()) {
return;
}
// 启用 Kotlin 重定向
if (!PrimitiveSettings.SKIP_KOTLIN_RELOCATE) {
rel.add(new JarRelocation(KOTLIN_ID + ".", KOTLIN_ID + PrimitiveSettings.formatVersion(KOTLIN_VERSION) + "."));
rel.add(new JarRelocation(KOTLIN_COROUTINES_ID + ".", KOTLIN_COROUTINES_ID + PrimitiveSettings.formatVersion(KOTLIN_COROUTINES_VERSION) + "."));
}
// 加载 Kotlin 环境
if (!KOTLIN_VERSION.equals("null")) ENV.loadDependency("org.jetbrains.kotlin:kotlin-stdlib:" + KOTLIN_VERSION, rel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object PlatformFactory {

// 加载接口
runningClassesWithoutLibrary.parallelStream().forEach {
if (it.isAnnotationPresent(Awake::class.java) && Platform.check(it)) {
if (it.isAnnotationPresent(Awake::class.java) && checkPlatform(it)) {
val interfaces = it.interfaces
val instance = it.getInstance(true)?.get() ?: return@forEach
// 依赖注入接口
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,13 @@ annotation class PlatformImplementation(val platform: Platform)
*/
@Suppress("UNCHECKED_CAST")
fun <T> Class<T>.findImplementation(): T? {
return runningClasses.firstOrNull { isAssignableFrom(it) && it != this && Platform.check(it) }?.getInstance(true)?.get() as? T
return runningClasses.firstOrNull { isAssignableFrom(it) && it != this && checkPlatform(it) }?.getInstance(true)?.get() as? T
}

/**
* 判断平台实现
*/
fun checkPlatform(cls: Class<*>): Boolean {
val platformSide = cls.getAnnotation(PlatformSide::class.java)
return platformSide == null || platformSide.value.any { i -> i == Platform.CURRENT }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package taboolib.common.platform.function
import taboolib.common.io.getInstance
import taboolib.common.io.runningClasses
import taboolib.common.platform.Platform
import taboolib.common.platform.checkPlatform

/**
* 搜索该类的当前平台实现
*/
@Suppress("UNCHECKED_CAST")
fun <T> Class<T>.findImplementation(): T? {
return runningClasses.firstOrNull { isAssignableFrom(it) && it != this && Platform.check(it) }?.getInstance(true)?.get() as? T
return runningClasses.firstOrNull { isAssignableFrom(it) && it != this && checkPlatform(it) }?.getInstance(true)?.get() as? T
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import taboolib.common.io.ProjectScannerKt;
import taboolib.common.platform.Ghost;
import taboolib.common.platform.Platform;
import taboolib.common.platform.PlatformSide;
import taboolib.common.platform.SkipTo;

import java.util.*;
Expand Down Expand Up @@ -175,7 +176,7 @@ public static Set<Class<?>> getClasses() {
continue;
}
// 排除其他平台
if (!Platform.check(it.getValue())) {
if (!checkPlatform(it.getValue())) {
continue;
}
classes.add(it.getValue());
Expand All @@ -184,4 +185,12 @@ public static Set<Class<?>> getClasses() {
}
return classes;
}

/**
* 检查指定类是否允许在当前平台运行
*/
public static boolean checkPlatform(Class<?> cls) {
PlatformSide platformSide = cls.getAnnotation(PlatformSide.class);
return platformSide == null || Arrays.stream(platformSide.value()).anyMatch(i -> i == Platform.CURRENT);
}
}
41 changes: 32 additions & 9 deletions common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import taboolib.common.ClassAppender
import taboolib.common.PrimitiveIO
import taboolib.common.PrimitiveSettings
import taboolib.common.TabooLib
import taboolib.common.platform.Platform
import taboolib.common.platform.PlatformSide
import taboolib.common.platform.Plugin
import java.io.File
import java.net.JarURLConnection
import java.net.URISyntaxException
Expand Down Expand Up @@ -93,6 +96,31 @@ var extraLoadedClasses = ConcurrentHashMap<String, Class<*>>()
*/
var extraLoadedResources = ConcurrentHashMap<String, ByteArray>()

/**
* 获取 Plugin 实现
*/
fun findPluginImpl(): Plugin? {
// 从 Jar 中获取类
val cls = runningClassMapInJar.values.firstOrNull { Plugin::class.java != it && Plugin::class.java.isAssignableFrom(it) && checkPlatform(it) }
return if (cls != null) {
try {
val declaredField = cls.getDeclaredField("INSTANCE")
declaredField.isAccessible = true
declaredField.get(null) as Plugin
} catch (ex: NoSuchFieldException) {
cls.getDeclaredConstructor().newInstance() as Plugin
}
} else null
}

/**
* 判断平台实现
*/
fun checkPlatform(cls: Class<*>): Boolean {
val platformSide = cls.getAnnotation(PlatformSide::class.java)
return platformSide == null || platformSide.value.any { i -> i == Platform.CURRENT }
}

/**
* 取该类在当前项目中被加载的任何实例
* 例如:@Awake 自唤醒类,或是 Kotlin Companion Object、Kotlin Object 对象
Expand Down Expand Up @@ -122,7 +150,7 @@ fun <T> Class<T>.getInstance(newInstance: Boolean = false): Supplier<T>? {
return try {
// 伴生类
val instanceObj = if (simpleName == "Companion") {
ReflexClass.of(getClass(name.substringBeforeLast('$'))).getField("Companion", findToParent = false, remap = false)
ReflexClass.of(classOf(name.substringBeforeLast('$'))).getField("Companion", findToParent = false, remap = false)
} else {
ReflexClass.of(this).getField("INSTANCE", findToParent = false, remap = false)
}
Expand Down Expand Up @@ -150,7 +178,7 @@ fun <T> Class<T>.getInstance(newInstance: Boolean = false): Supplier<T>? {
/**
* 获取 URL 下的所有类
*/
fun URL.getClasses(classLoader: ClassLoader = TabooLib::class.java.classLoader): Map<String, Class<*>> {
fun URL.getClasses(classLoader: ClassLoader = ClassAppender.getClassLoader()): Map<String, Class<*>> {
val classes = LinkedHashMap<String, Class<*>>()
val srcFile = try {
File(toURI())
Expand Down Expand Up @@ -193,11 +221,8 @@ fun URL.getResources(): Map<String, ByteArray> {
return resources
}

/**
* 从 TabooLib 的 ClassLoader 中获取类,且不触发类的初始化
*/
private fun getClass(name: String): Class<*> {
return Class.forName(name, false, TabooLib::class.java.classLoader)
private fun classOf(name: String): Class<*> {
return Class.forName(name, false, ClassAppender.getClassLoader())
}

private fun <T> sup(supplier: () -> T): Supplier<T> {
Expand All @@ -222,6 +247,4 @@ private fun init() {
extraLoadedResources += file.toURI().toURL().getResources()
}
}
// PrimitiveIO.println("Kotlin Env: %s", TabooLib.isKotlinEnvironment())
// PrimitiveIO.println("Running Classes %s", runningClasses)
}
27 changes: 7 additions & 20 deletions common/src/main/java/taboolib/common/ClassAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ public class ClassAppender {
}
}

ClassAppender() {
}

/**
* 加载一个文件到 ClassLoader
*
Expand All @@ -49,17 +46,14 @@ public class ClassAppender {
*/
public static ClassLoader addPath(Path path, boolean isIsolated, boolean isExternal) throws Throwable {
File file = new File(path.toUri().getPath());

// IsolatedClassLoader
ClassLoader loader = TabooLib.class.getClassLoader();
if (loader instanceof IsolatedClassLoader) {
if (isIsolated) {
addURL(loader, ucp(loader), file, isExternal);
return loader;
}
loader = loader.getParent();
if (isIsolated) {
IsolatedClassLoader loader = IsolatedClassLoader.INSTANCE;
loader.addURL(file.toURI().toURL());
callbacks.forEach(i -> i.add(loader, file, isExternal));
return loader;
}

ClassLoader loader = TabooLib.class.getClassLoader();
// Application
if (loader.getClass().getName().equals("jdk.internal.loader.ClassLoaders$AppClassLoader")) {
addURL(loader, ucp(loader.getClass()), file, isExternal);
Expand All @@ -80,14 +74,7 @@ else if (loader.getClass().getName().equals("net.minecraft.launchwrapper.LaunchC
* 获取 addPath 函数所使用的 ClassLoader(原函数为:judgeAddPathClassLoader)
*/
public static ClassLoader getClassLoader() {
ClassLoader loader = TabooLib.class.getClassLoader();
if (loader instanceof IsolatedClassLoader) {
if (PrimitiveSettings.IS_ISOLATED_MODE) {
return loader;
}
return loader.getParent();
}
return loader;
return PrimitiveSettings.IS_ISOLATED_MODE ? IsolatedClassLoader.INSTANCE : TabooLib.class.getClassLoader();
}

/**
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/java/taboolib/common/PrimitiveLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ static void loadFile(File file, boolean isIsolated, boolean isExternal, String[]
// 确保在 jar-relocator 加载后运行 >> java.lang.NoClassDefFoundError
if (relocate.length > 0) {
List<Relocation> rel = Arrays.stream(relocate).map(r -> new Relocation(r[0], r[1])).collect(Collectors.toList());
// 在非隔离模式下进行 Kotlin 重定向
if (!IS_ISOLATED_MODE && !SKIP_KOTLIN_RELOCATE) {
// 启用 Kotlin 重定向
if (!SKIP_KOTLIN_RELOCATE) {
String kt = "!kotlin".substring(1);
String ktc = "!kotlinx.coroutines".substring(1);
String kv = formatVersion(KOTLIN_VERSION);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package taboolib.common.classloader;

import jdk.internal.loader.URLClassPath;
import taboolib.common.PrimitiveIO;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
Expand Down Expand Up @@ -40,12 +43,26 @@ public IsolatedClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);

// 默认排除类
excludedClasses.add("taboolib.common.classloader.IsolatedClassLoader"); // JavaPlugin 直接访问
excludedClasses.add("taboolib.common.ClassAppender"); // 储存数据
excludedClasses.add("taboolib.common.TabooLib"); // 储存数据
excludedClasses.add("taboolib.common.OpenAPI"); // 其他插件访问,同时访问 TabooLib 的 AwakenedClasses
excludedClasses.add("taboolib.common.platform.Plugin"); // 其他插件访问
excludedPackages.add("java.");
// JavaPlugin 直接访问
excludedClasses.add("taboolib.common.classloader.IsolatedClassLoader");

// 储存数据
excludedClasses.add("taboolib.common.TabooLib");
excludedClasses.add("taboolib.common.ClassAppender");
excludedClasses.add("taboolib.common.ClassAppender$Callback");

// 其他插件访问
excludedClasses.add("taboolib.common.OpenAPI");
excludedClasses.add("taboolib.common.platform.Plugin");

// 交叉访问
excludedClasses.add("taboolib.common.LifeCycle");
excludedClasses.add("taboolib.common.LifeCycleTask");
excludedClasses.add("taboolib.common.PrimitiveIO");
excludedClasses.add("taboolib.common.PrimitiveSettings");
excludedClasses.add("taboolib.common.platform.Platform");
excludedClasses.add("taboolib.common.platform.PlatformSide");

// Load excluded classes and packages by SPI
ServiceLoader<IsolatedClassLoaderConfig> serviceLoader = ServiceLoader.load(IsolatedClassLoaderConfig.class, parent);
Expand All @@ -61,6 +78,11 @@ public IsolatedClassLoader(URL[] urls, ClassLoader parent) {
}
}

@Override
public void addURL(URL url) {
super.addURL(url);
}

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
return loadClass(name, resolve, true);
Expand Down
8 changes: 0 additions & 8 deletions common/src/main/java/taboolib/common/platform/Platform.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ public String checkClass() {
return checkClass;
}

/**
* 检查指定类是否允许在当前平台运行
*/
public static boolean check(Class<?> cls) {
PlatformSide platformSide = cls.getAnnotation(PlatformSide.class);
return platformSide == null || Arrays.stream(platformSide.value()).anyMatch(i -> i == CURRENT);
}

/**
* 获取属于 Minecraft 的平台类型
*/
Expand Down
27 changes: 23 additions & 4 deletions common/src/main/java/taboolib/common/platform/Plugin.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package taboolib.common.platform;

import org.jetbrains.annotations.Nullable;
import taboolib.common.ClassAppender;
import taboolib.common.PrimitiveIO;

import java.io.File;

Expand All @@ -16,22 +18,26 @@ public abstract class Plugin {
/**
* 当加载插件时调用
*/
public void onLoad() {}
public void onLoad() {
}

/**
* 当启用插件时调用
*/
public void onEnable() {}
public void onEnable() {
}

/**
* 当服务器启动完成时调用
*/
public void onActive() {}
public void onActive() {
}

/**
* 当卸载插件时调用
*/
public void onDisable() {}
public void onDisable() {
}

/**
* 重定向插件文件(用于改变 TabooLib 逻辑)
Expand All @@ -48,4 +54,17 @@ public File nativeJarFile() {
public File nativeDataFolder() {
return null;
}

/**
* 获取实现
*/
public static Plugin findImpl() {
try {
Class<?> scanner = Class.forName("taboolib.common.io.ProjectScannerKt", true, ClassAppender.getClassLoader());
Object impl = scanner.getDeclaredMethod("findPluginImpl").invoke(null);
return impl != null ? (Plugin) impl : null;
} catch (Throwable ex) {
throw new RuntimeException("Failed to find plugin implementation.", ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package taboolib.module.nms

import taboolib.common.TabooLib
import taboolib.common.ClassAppender

object AsmClassLoader : ClassLoader(TabooLib::class.java.classLoader) {
object AsmClassLoader : ClassLoader(ClassAppender.getClassLoader()) {

override fun findClass(name: String?): Class<*> {
try {
Expand Down
Loading

0 comments on commit 9eaa917

Please sign in to comment.