Skip to content

Commit

Permalink
[6.1.2] 优化启动速度
Browse files Browse the repository at this point in the history
  • Loading branch information
Bkm016 committed Jun 10, 2024
1 parent d333943 commit 9071912
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 58 deletions.
12 changes: 12 additions & 0 deletions common-env/src/main/java/taboolib/common/env/JavaAnnotation.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ public static <T extends Annotation> T getAnnotationIfPresent(AnnotatedElement a
}
}

/**
* 获取指定注解的注解实例
* 如果不存在则返回 null
*/
public static <T extends Annotation> T[] getAnnotationsIfPresent(AnnotatedElement ae, Class<T> annotationClass) {
try {
return ae.getAnnotationsByType(annotationClass);
} catch (Throwable ex) {
return null;
}
}

/**
* 安全的判断是否存在指定注解
* 防止java.lang.ArrayStoreException: sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy异常
Expand Down
48 changes: 27 additions & 21 deletions common-env/src/main/java/taboolib/common/env/RuntimeEnv.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
}

Expand Down Expand Up @@ -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<String> tests = new ArrayList<>();
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

// 加载接口
Expand Down
12 changes: 8 additions & 4 deletions common-util/src/main/kotlin/taboolib/common/io/ProjectScanner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ fun <T> Class<T>.getInstance(newInstance: Boolean = false): Supplier<T>? {
* 获取 URL 下的所有类
*/
fun URL.getClasses(classLoader: ClassLoader = ClassAppender.getClassLoader()): Map<String, Class<*>> {
val classes = LinkedHashMap<String, Class<*>>()
val classes = ConcurrentHashMap<String, Class<*>>()
val srcFile = try {
File(toURI())
} catch (ex: IllegalArgumentException) {
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package taboolib.common.util

fun join(args: List<String>, start: Int = 0, separator: String = " "): String {
return args.filterIndexed { index, _ -> index >= start }.joinToString(separator)
}

fun join(args: Array<String>, start: Int = 0, separator: String = " "): String {
return args.filterIndexed { index, _ -> index >= start }.joinToString(separator)
}
Expand Down
45 changes: 26 additions & 19 deletions common/src/main/java/taboolib/common/PrimitiveIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
@SuppressWarnings("CallToPrintStackTrace")
public class PrimitiveIO {

private static final int BUFFER_SIZE = 8192;
private static final ThreadLocal<MessageDigest> DIGEST_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
try {
return MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
});

/**
* 当前运行的文件名
**/
Expand Down Expand Up @@ -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() + ")";
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down
22 changes: 11 additions & 11 deletions module/module-nms/src/main/kotlin/taboolib/module/nms/Mapping.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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])
}
}
}
Expand Down

0 comments on commit 9071912

Please sign in to comment.