onEnable 之前加载插件
修复 NoClassDefFoundError 的问题
This commit is contained in:
parent
b941cac63f
commit
2edca32b89
@ -14,7 +14,8 @@ import java.io.File;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1")
|
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1")
|
||||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.0.0")
|
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0")
|
||||||
|
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25")
|
||||||
public class TLib {
|
public class TLib {
|
||||||
|
|
||||||
private static TLib tLib;
|
private static TLib tLib;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.ilummc.tlib.annotations;
|
package com.ilummc.tlib.annotations;
|
||||||
|
|
||||||
|
import com.ilummc.tlib.util.Ref;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@ -20,6 +22,6 @@ public @interface Config {
|
|||||||
|
|
||||||
boolean listenChanges() default false;
|
boolean listenChanges() default false;
|
||||||
|
|
||||||
int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT;
|
int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT | Ref.ACC_SYNTHETIC | Ref.ACC_BRIDGE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.ilummc.tlib.inject;
|
|||||||
import com.ilummc.tlib.TLib;
|
import com.ilummc.tlib.TLib;
|
||||||
import com.ilummc.tlib.annotations.*;
|
import com.ilummc.tlib.annotations.*;
|
||||||
import com.ilummc.tlib.dependency.TDependency;
|
import com.ilummc.tlib.dependency.TDependency;
|
||||||
|
import com.ilummc.tlib.util.Ref;
|
||||||
import com.ilummc.tlib.util.TLogger;
|
import com.ilummc.tlib.util.TLogger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@ -14,22 +15,10 @@ import java.lang.reflect.Field;
|
|||||||
public class DependencyInjector {
|
public class DependencyInjector {
|
||||||
|
|
||||||
public static void inject(Plugin plugin, Object o) {
|
public static void inject(Plugin plugin, Object o) {
|
||||||
try {
|
|
||||||
injectLogger(plugin, o);
|
injectLogger(plugin, o);
|
||||||
} catch (NoClassDefFoundError ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
injectConfig(plugin, o);
|
injectConfig(plugin, o);
|
||||||
} catch (NoClassDefFoundError ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
injectPluginInstance(plugin, o);
|
injectPluginInstance(plugin, o);
|
||||||
} catch (NoClassDefFoundError ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
injectDependencies(plugin, o);
|
injectDependencies(plugin, o);
|
||||||
} catch (NoClassDefFoundError ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void injectOnEnable(Plugin plugin) {
|
static void injectOnEnable(Plugin plugin) {
|
||||||
@ -48,7 +37,7 @@ public class DependencyInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void ejectConfig(Plugin plugin, Object o) {
|
private static void ejectConfig(Plugin plugin, Object o) {
|
||||||
for (Field field : o.getClass().getDeclaredFields()) {
|
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
||||||
Config config;
|
Config config;
|
||||||
if ((config = field.getType().getAnnotation(Config.class)) != null) {
|
if ((config = field.getType().getAnnotation(Config.class)) != null) {
|
||||||
try {
|
try {
|
||||||
@ -64,7 +53,7 @@ public class DependencyInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void injectConfig(Plugin plugin, Object o) {
|
private static void injectConfig(Plugin plugin, Object o) {
|
||||||
for (Field field : o.getClass().getDeclaredFields()) {
|
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
||||||
try {
|
try {
|
||||||
Config config;
|
Config config;
|
||||||
if ((config = field.getType().getAnnotation(Config.class)) != null) {
|
if ((config = field.getType().getAnnotation(Config.class)) != null) {
|
||||||
@ -100,7 +89,7 @@ public class DependencyInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void injectLogger(Plugin plugin, Object o) {
|
private static void injectLogger(Plugin plugin, Object o) {
|
||||||
for (Field field : o.getClass().getDeclaredFields()) {
|
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
||||||
try {
|
try {
|
||||||
Logger logger;
|
Logger logger;
|
||||||
if ((logger = field.getAnnotation(Logger.class)) != null) {
|
if ((logger = field.getAnnotation(Logger.class)) != null) {
|
||||||
@ -116,7 +105,7 @@ public class DependencyInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void injectPluginInstance(Plugin plugin, Object o) {
|
private static void injectPluginInstance(Plugin plugin, Object o) {
|
||||||
for (Field field : o.getClass().getDeclaredFields()) {
|
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
||||||
try {
|
try {
|
||||||
PluginInstance instance;
|
PluginInstance instance;
|
||||||
if ((instance = field.getAnnotation(PluginInstance.class)) != null) {
|
if ((instance = field.getAnnotation(PluginInstance.class)) != null) {
|
||||||
|
@ -49,9 +49,7 @@ public class TLibPluginManager implements PluginManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
|
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
|
||||||
Plugin plugin = instance.loadPlugin(file);
|
return instance.loadPlugin(file);
|
||||||
DependencyInjector.injectOnEnable(plugin);
|
|
||||||
return plugin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,6 +92,7 @@ public class TLibPluginManager implements PluginManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enablePlugin(Plugin plugin) {
|
public void enablePlugin(Plugin plugin) {
|
||||||
|
DependencyInjector.injectOnEnable(plugin);
|
||||||
instance.enablePlugin(plugin);
|
instance.enablePlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
src/main/java/com/ilummc/tlib/util/IO.java
Normal file
18
src/main/java/com/ilummc/tlib/util/IO.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package com.ilummc.tlib.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class IO {
|
||||||
|
|
||||||
|
public static byte[] readFully(InputStream inputStream) throws IOException {
|
||||||
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int len = 0;
|
||||||
|
while ((len = inputStream.read(buf)) > 0) {
|
||||||
|
stream.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
return stream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
59
src/main/java/com/ilummc/tlib/util/Ref.java
Normal file
59
src/main/java/com/ilummc/tlib/util/Ref.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package com.ilummc.tlib.util;
|
||||||
|
|
||||||
|
import com.ilummc.tlib.util.asm.AsmAnalyser;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
public class Ref {
|
||||||
|
|
||||||
|
private static final Map<String, List<Field>> cachedFields = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public static final int ACC_BRIDGE = 0x0040;
|
||||||
|
public static final int ACC_SYNTHETIC = 0x1000;
|
||||||
|
|
||||||
|
public static List<Field> getDeclaredFields(Class<?> clazz) {
|
||||||
|
return getDeclaredFields(clazz, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Field> getDeclaredFields(String clazz, int excludeModifiers, boolean cache) {
|
||||||
|
try {
|
||||||
|
return getDeclaredFields(Class.forName(clazz), excludeModifiers, cache);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Field> getDeclaredFields(Class<?> clazz, int excludeModifiers, boolean cache) {
|
||||||
|
try {
|
||||||
|
Class.forName("org.objectweb.asm.ClassVisitor");
|
||||||
|
List<Field> fields;
|
||||||
|
if ((fields = cachedFields.get(clazz.getName())) != null) return fields;
|
||||||
|
ClassReader classReader = new ClassReader(clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class"));
|
||||||
|
AsmAnalyser analyser = new AsmAnalyser(new ClassWriter(ClassWriter.COMPUTE_MAXS), excludeModifiers);
|
||||||
|
classReader.accept(analyser, ClassReader.SKIP_DEBUG);
|
||||||
|
fields = analyser.getFields().stream().map(name -> {
|
||||||
|
try {
|
||||||
|
return clazz.getDeclaredField(name);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
if (cache) cachedFields.putIfAbsent(clazz.getName(), fields);
|
||||||
|
return fields;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java
Normal file
31
src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package com.ilummc.tlib.util.asm;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.FieldVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AsmAnalyser extends ClassVisitor implements Opcodes {
|
||||||
|
|
||||||
|
private final List<String> fields = new ArrayList<>();
|
||||||
|
|
||||||
|
private final int excludeModifier;
|
||||||
|
|
||||||
|
public AsmAnalyser(ClassVisitor classVisitor, int excludeModifiers) {
|
||||||
|
super(Opcodes.ASM6, classVisitor);
|
||||||
|
this.excludeModifier = excludeModifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||||
|
if ((access & excludeModifier) == 0)
|
||||||
|
fields.add(name);
|
||||||
|
return super.visitField(access, name, descriptor, signature, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
@ -51,21 +51,6 @@ import java.util.Random;
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class Main extends JavaPlugin implements Listener {
|
public class Main extends JavaPlugin implements Listener {
|
||||||
|
|
||||||
public Main() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
inst = this;
|
|
||||||
disable = false;
|
|
||||||
|
|
||||||
TLib.injectPluginManager();
|
|
||||||
|
|
||||||
// 载入配置
|
|
||||||
saveDefaultConfig();
|
|
||||||
|
|
||||||
// 加载依赖
|
|
||||||
TLib.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static Plugin inst;
|
private static Plugin inst;
|
||||||
@Getter
|
@Getter
|
||||||
@ -116,6 +101,17 @@ public class Main extends JavaPlugin implements Listener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
|
inst = this;
|
||||||
|
disable = false;
|
||||||
|
|
||||||
|
TLib.injectPluginManager();
|
||||||
|
|
||||||
|
// 载入配置
|
||||||
|
saveDefaultConfig();
|
||||||
|
|
||||||
|
// 加载依赖
|
||||||
|
TLib.init();
|
||||||
|
|
||||||
// 载入目录
|
// 载入目录
|
||||||
setupDataFolder();
|
setupDataFolder();
|
||||||
// 注册配置
|
// 注册配置
|
||||||
|
Loading…
Reference in New Issue
Block a user