From da15abc2e516947cbc76c4252ffb149394bafce0 Mon Sep 17 00:00:00 2001 From: wxd-gaming <492794628@qq.com> Date: Fri, 5 Jul 2024 17:43:21 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E8=BF=9C?= =?UTF-8?q?=E7=A8=8Bclassloader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boot/agent/loader/RemoteClassLoader.java | 100 ++++++++++++++++++ .../boot/agent/system/ReflectContext.java | 10 +- 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/loader/RemoteClassLoader.java diff --git a/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/loader/RemoteClassLoader.java b/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/loader/RemoteClassLoader.java new file mode 100644 index 0000000..ab1f33b --- /dev/null +++ b/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/loader/RemoteClassLoader.java @@ -0,0 +1,100 @@ +package wxdgaming.boot.agent.loader; + +import lombok.Getter; + +import javax.tools.JavaFileObject; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * 远程loader + * + * @author: Troy.Chen(無心道, 15388152619) + * @version: 2024-07-05 14:08 + **/ +@Getter +public class RemoteClassLoader extends URLClassLoader { + + public static RemoteClassLoader build(ClassLoader parent, String... urls) { + try { + URL[] _ruls = new URL[urls.length]; + ArrayList resources = new ArrayList<>(); + ArrayList classResources = new ArrayList<>(); + for (int i = 0, urlsLength = urls.length; i < urlsLength; i++) { + String url = urls[i]; + URI uri = URI.create(url); + _ruls[i] = uri.toURL(); + try (ZipInputStream zipInputStream = new ZipInputStream(uri.toURL().openStream())) { + ZipEntry nextEntry = null; + while ((nextEntry = zipInputStream.getNextEntry()) != null) { + resources.add(nextEntry.getName()); + // System.out.println("resource:" + nextEntry.getName()); + if (!nextEntry.isDirectory() && nextEntry.getName().endsWith(JavaFileObject.Kind.CLASS.extension)) { + String replace = nextEntry.getName() + .replace("\\", "/") + .replace("/", "."); + replace = replace.substring(0, replace.length() - JavaFileObject.Kind.CLASS.extension.length()); + classResources.add(replace); + // System.out.println("class:" + replace); + } + } + } + } + + return new RemoteClassLoader( + _ruls, + parent, + Collections.unmodifiableList(resources), + Collections.unmodifiableList(classResources) + ); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private final List classResources; + private final List resources; + + public RemoteClassLoader(URL[] urls, ClassLoader parent, List resources, List classResources) { + super(urls, parent); + this.resources = resources; + this.classResources = classResources; + } + + public Stream> classStream() { + return classStream(null); + } + + public Stream> classStream(Predicate test) { + Stream stream = classResources.stream(); + if (test != null) { + stream = stream.filter(test); + } + return stream.map(v -> { + try { + return this.loadClass(v); + } catch (ClassNotFoundException e) { + throw new RuntimeException(v, e); + } + }); + } + + public List> classes() { + return classes(null); + } + + public List> classes(Predicate test) { + return classStream(test).collect(Collectors.toUnmodifiableList()); + } + +} diff --git a/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/system/ReflectContext.java b/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/system/ReflectContext.java index a295333..4ddd6a3 100644 --- a/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/system/ReflectContext.java +++ b/wxdgaming.boot.agent/src/main/java/wxdgaming/boot/agent/system/ReflectContext.java @@ -6,6 +6,7 @@ import lombok.experimental.Accessors; import org.slf4j.LoggerFactory; import wxdgaming.boot.agent.exception.Throw; import wxdgaming.boot.agent.loader.ClassDirLoader; +import wxdgaming.boot.agent.loader.RemoteClassLoader; import java.io.File; import java.lang.annotation.Annotation; @@ -254,6 +255,13 @@ public class ReflectContext { } } } + + if (classLoader instanceof RemoteClassLoader remoteClassLoader) { + remoteClassLoader + .classStream(v -> v.startsWith(packageName)) + .forEach(consumer); + } + Enumeration resources = classLoader.getResources(packagePath); if (resources != null) { URL url = null; @@ -338,7 +346,7 @@ public class ReflectContext { * @param jarPath jar文件路径 */ private void findClassByJar(String jarPath, Consumer> consumer) { - + if (jarPath.startsWith("http://") || jarPath.startsWith("https://")) return; String[] jarInfo = jarPath.split("!"); String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/")); String packagePath = jarInfo[1].substring(1);