From 9071912cddb19b1253083b54b72c63f4089f9b45 Mon Sep 17 00:00:00 2001 From: Bkm016 Date: Tue, 11 Jun 2024 04:55:03 +0800 Subject: [PATCH] =?UTF-8?q?[6.1.2]=20=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../taboolib/common/env/JavaAnnotation.java | 12 +++++ .../java/taboolib/common/env/RuntimeEnv.java | 48 +++++++++++-------- .../common/platform/PlatformFactory.kt | 9 +++- .../taboolib/common/io/ProjectScanner.kt | 12 +++-- .../kotlin/taboolib/common/util/Collection.kt | 4 ++ .../java/taboolib/common/PrimitiveIO.java | 45 +++++++++-------- gradle.properties | 2 +- .../kotlin/taboolib/module/nms/Mapping.kt | 22 ++++----- 8 files changed, 96 insertions(+), 58 deletions(-) diff --git a/common-env/src/main/java/taboolib/common/env/JavaAnnotation.java b/common-env/src/main/java/taboolib/common/env/JavaAnnotation.java index 9b188e96e..000f667ff 100644 --- a/common-env/src/main/java/taboolib/common/env/JavaAnnotation.java +++ b/common-env/src/main/java/taboolib/common/env/JavaAnnotation.java @@ -24,6 +24,18 @@ public static T getAnnotationIfPresent(AnnotatedElement a } } + /** + * 获取指定注解的注解实例 + * 如果不存在则返回 null + */ + public static T[] getAnnotationsIfPresent(AnnotatedElement ae, Class annotationClass) { + try { + return ae.getAnnotationsByType(annotationClass); + } catch (Throwable ex) { + return null; + } + } + /** * 安全的判断是否存在指定注解 * 防止java.lang.ArrayStoreException: sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy异常 diff --git a/common-env/src/main/java/taboolib/common/env/RuntimeEnv.java b/common-env/src/main/java/taboolib/common/env/RuntimeEnv.java index 842e4461e..1809eb836 100644 --- a/common-env/src/main/java/taboolib/common/env/RuntimeEnv.java +++ b/common-env/src/main/java/taboolib/common/env/RuntimeEnv.java @@ -63,21 +63,24 @@ public void inject(@NotNull Class clazz) throws Throwable { loadDependency(clazz); } - public void loadAssets(@NotNull Class clazz) throws IOException { - RuntimeResource[] resources = null; - if (JavaAnnotation.hasAnnotation(clazz, RuntimeResource.class)) { - resources = clazz.getAnnotationsByType(RuntimeResource.class); - } else { + @Nullable + public RuntimeResource[] getAssets(@NotNull Class clazz) { + RuntimeResource[] resources = JavaAnnotation.getAnnotationsIfPresent(clazz, RuntimeResource.class); + if (resources == null && JavaAnnotation.hasAnnotation(clazz, RuntimeResources.class)) { RuntimeResources annotation = JavaAnnotation.getAnnotationIfPresent(clazz, RuntimeResources.class); if (annotation != null) { resources = annotation.value(); } } - if (resources == null) { - return; - } - for (RuntimeResource resource : resources) { - loadAssets(resource.name(), resource.hash(), resource.value(), resource.zip()); + return resources; + } + + public void loadAssets(@NotNull Class clazz) throws IOException { + RuntimeResource[] resources = getAssets(clazz); + if (resources != null) { + for (RuntimeResource resource : resources) { + loadAssets(resource.name(), resource.hash(), resource.value(), resource.zip()); + } } } @@ -111,23 +114,21 @@ public void loadAssets(String name, String hash, String url, boolean zip) throws } } - private boolean test(String path) { - String test = path.startsWith("!") ? path.substring(1) : path; - return !test.isEmpty() && ClassAppender.isExists(test); - } - - public void loadDependency(@NotNull Class clazz) throws Throwable { - File baseFile = new File(defaultLibrary); - RuntimeDependency[] dependencies = null; - if (JavaAnnotation.hasAnnotation(clazz, RuntimeDependency.class)) { - dependencies = clazz.getAnnotationsByType(RuntimeDependency.class); - } else { + public RuntimeDependency[] getDependency(@NotNull Class clazz) { + RuntimeDependency[] dependencies = JavaAnnotation.getAnnotationsIfPresent(clazz, RuntimeDependency.class); + if (dependencies == null && JavaAnnotation.hasAnnotation(clazz, RuntimeDependencies.class)) { RuntimeDependencies annotation = JavaAnnotation.getAnnotationIfPresent(clazz, RuntimeDependencies.class); if (annotation != null) { dependencies = annotation.value(); } } + return dependencies; + } + + public void loadDependency(@NotNull Class clazz) throws Throwable { + RuntimeDependency[] dependencies = getDependency(clazz); if (dependencies != null) { + File baseFile = new File(defaultLibrary); for (RuntimeDependency dep : dependencies) { String allTest = dep.test(); List tests = new ArrayList<>(); @@ -236,4 +237,9 @@ public void loadDependency( downloader.injectClasspath(Collections.singleton(dep)); } } + + private boolean test(String path) { + String test = path.startsWith("!") ? path.substring(1) : path; + return !test.isEmpty() && ClassAppender.isExists(test); + } } diff --git a/common-platform-api/src/main/kotlin/taboolib/common/platform/PlatformFactory.kt b/common-platform-api/src/main/kotlin/taboolib/common/platform/PlatformFactory.kt index 178bd1201..b4c29274b 100644 --- a/common-platform-api/src/main/kotlin/taboolib/common/platform/PlatformFactory.kt +++ b/common-platform-api/src/main/kotlin/taboolib/common/platform/PlatformFactory.kt @@ -46,8 +46,13 @@ object PlatformFactory { } // 加载运行环境 - runningClassesWithoutLibrary.forEach { - runCatching { RuntimeEnv.ENV.inject(it) }.exceptionOrNull()?.takeIf { it !is NoClassDefFoundError }?.printStackTrace() + runningClassesWithoutLibrary.parallelStream().forEach { + try { + RuntimeEnv.ENV.inject(it) + } catch (_: NoClassDefFoundError) { + } catch (ex: Throwable) { + ex.printStackTrace() + } } // 加载接口 diff --git a/common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt b/common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt index d8fc0eacc..b23f8f0e3 100644 --- a/common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt +++ b/common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt @@ -180,7 +180,7 @@ fun Class.getInstance(newInstance: Boolean = false): Supplier? { * 获取 URL 下的所有类 */ fun URL.getClasses(classLoader: ClassLoader = ClassAppender.getClassLoader()): Map> { - val classes = LinkedHashMap>() + val classes = ConcurrentHashMap>() val srcFile = try { File(toURI()) } catch (ex: IllegalArgumentException) { @@ -190,9 +190,13 @@ fun URL.getClasses(classLoader: ClassLoader = ClassAppender.getClassLoader()): M } // 是文件 if (srcFile.isFile) { - JarFile(srcFile).stream().filter { it.name.endsWith(".class") }.forEach { - val className = it.name.replace('/', '.').substringBeforeLast(".class") - runCatching { classes[className] = Class.forName(className, false, classLoader) } + JarFile(srcFile).use { jar -> + jar.stream().parallel().forEach { + if (it.name.endsWith(".class")) { + val className = it.name.replace('/', '.').substringBeforeLast('.') + runCatching { classes[className] = Class.forName(className, false, classLoader) } + } + } } } else { srcFile.walkTopDown().filter { it.extension == "class" }.forEach { diff --git a/common-util/src/main/kotlin/taboolib/common/util/Collection.kt b/common-util/src/main/kotlin/taboolib/common/util/Collection.kt index 311ffe5b2..ad7f6b86d 100644 --- a/common-util/src/main/kotlin/taboolib/common/util/Collection.kt +++ b/common-util/src/main/kotlin/taboolib/common/util/Collection.kt @@ -1,5 +1,9 @@ package taboolib.common.util +fun join(args: List, start: Int = 0, separator: String = " "): String { + return args.filterIndexed { index, _ -> index >= start }.joinToString(separator) +} + fun join(args: Array, start: Int = 0, separator: String = " "): String { return args.filterIndexed { index, _ -> index >= start }.joinToString(separator) } diff --git a/common/src/main/java/taboolib/common/PrimitiveIO.java b/common/src/main/java/taboolib/common/PrimitiveIO.java index 2337154c2..30e4fa60e 100644 --- a/common/src/main/java/taboolib/common/PrimitiveIO.java +++ b/common/src/main/java/taboolib/common/PrimitiveIO.java @@ -24,6 +24,15 @@ @SuppressWarnings("CallToPrintStackTrace") public class PrimitiveIO { + private static final int BUFFER_SIZE = 8192; + private static final ThreadLocal DIGEST_THREAD_LOCAL = ThreadLocal.withInitial(() -> { + try { + return MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + }); + /** * 当前运行的文件名 **/ @@ -91,21 +100,22 @@ public static boolean validation(File file, File hashFile) { */ @NotNull public static String getHash(File file) { - try { - MessageDigest digest = MessageDigest.getInstance("sha-1"); - try (InputStream inputStream = Files.newInputStream(file.toPath())) { - byte[] buffer = new byte[1024]; - int total; - while ((total = inputStream.read(buffer)) != -1) { - digest.update(buffer, 0, total); - } + MessageDigest digest = DIGEST_THREAD_LOCAL.get(); + digest.reset(); // Ensure the MessageDigest is reset before each use + try (InputStream inputStream = Files.newInputStream(file.toPath())) { + byte[] buffer = new byte[BUFFER_SIZE]; + int total; + while ((total = inputStream.read(buffer)) != -1) { + digest.update(buffer, 0, total); } - StringBuilder result = new StringBuilder(); - for (byte b : digest.digest()) { + byte[] hashBytes = digest.digest(); + // Convert byte array to hex string + StringBuilder result = new StringBuilder(hashBytes.length * 2); + for (byte b : hashBytes) { result.append(String.format("%02x", b)); } return result.toString(); - } catch (IOException | NoSuchAlgorithmException ex) { + } catch (IOException ex) { ex.printStackTrace(); } return "null (" + UUID.randomUUID() + ")"; @@ -115,15 +125,12 @@ public static String getHash(File file) { * 获取字符串哈希 */ public static String getHash(String data) { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("sha-1"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } + MessageDigest digest = DIGEST_THREAD_LOCAL.get(); + digest.reset(); // Ensure the MessageDigest is reset before each use digest.update(data.getBytes(StandardCharsets.UTF_8)); - StringBuilder result = new StringBuilder(); - for (byte b : digest.digest()) { + byte[] hashBytes = digest.digest(); + StringBuilder result = new StringBuilder(hashBytes.length * 2); + for (byte b : hashBytes) { result.append(String.format("%02x", b)); } return result.toString(); diff --git a/gradle.properties b/gradle.properties index 4baf38559..97c97e983 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=taboolib -version=6.1.2-beta5 +version=6.1.2-beta6 kotlin.incremental=true kotlin.incremental.java=true kotlin.caching.enabled=true diff --git a/module/module-nms/src/main/kotlin/taboolib/module/nms/Mapping.kt b/module/module-nms/src/main/kotlin/taboolib/module/nms/Mapping.kt index 3073c1720..007e99225 100644 --- a/module/module-nms/src/main/kotlin/taboolib/module/nms/Mapping.kt +++ b/module/module-nms/src/main/kotlin/taboolib/module/nms/Mapping.kt @@ -1,5 +1,6 @@ package taboolib.module.nms +import taboolib.common.PrimitiveIO import taboolib.common.util.join import java.io.InputStream import java.nio.charset.StandardCharsets @@ -21,32 +22,31 @@ class Mapping(inputStreamCombined: InputStream, inputStreamFields: InputStream) init { // 解析类名映射 inputStreamCombined.use { - it.readBytes().toString(StandardCharsets.UTF_8).lines().forEach { line -> + it.bufferedReader().readLines().forEach { line -> if (line.startsWith('#')) { return@forEach } - val args = line.split(' ') - if (args.size == 2) { - classMap[args[1].substringAfterLast('/', "")] = args[1] + if (line.contains(' ')) { + val name = line.substringAfterLast(' ') + classMap[name.substringAfterLast('/', "")] = name } } } // 解析字段映射 inputStreamFields.use { - it.readBytes().toString(StandardCharsets.UTF_8).lines().forEach { line -> + it.bufferedReader().readLines().forEach { line -> if (line.startsWith('#')) { return@forEach } val args = line.split(' ') if (args.size >= 3) { // 1.18 开始支持方法映射 - if (args[2].startsWith("(")) { - val info = join(args.toTypedArray(), 2) - val name = info.substringAfterLast(' ') - val parameter = info.substringBeforeLast(' ') - methods += Method(args[0].replace("/", "."), args[1], name, parameter) + if (args[2].startsWith('(')) { + val name = args.last() + val parameter = args[args.size - 2] + methods += Method(args[0].replace('/', '.'), args[1], name, parameter) } else { - fields += Field(args[0].replace("/", "."), args[1], args[2]) + fields += Field(args[0].replace('/', '.'), args[1], args[2]) } } }