【新增】远程classloader

This commit is contained in:
wxd-gaming
2024-07-05 17:43:21 +08:00
parent 07f9f2f645
commit da15abc2e5
2 changed files with 109 additions and 1 deletions

View File

@@ -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<String> resources = new ArrayList<>();
ArrayList<String> 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<String> classResources;
private final List<String> resources;
public RemoteClassLoader(URL[] urls, ClassLoader parent, List<String> resources, List<String> classResources) {
super(urls, parent);
this.resources = resources;
this.classResources = classResources;
}
public Stream<Class<?>> classStream() {
return classStream(null);
}
public Stream<Class<?>> classStream(Predicate<String> test) {
Stream<String> 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<Class<?>> classes() {
return classes(null);
}
public List<Class<?>> classes(Predicate<String> test) {
return classStream(test).collect(Collectors.toUnmodifiableList());
}
}

View File

@@ -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<URL> 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<Class<?>> 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);