diff --git a/README.md b/README.md
index 693c9d1e7c92935831fdc69215fb538cb2737b1a..92b95eedb79bb8cbad1a4352fc24c46fef14eb99 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@
com.gitee.wb04307201
loader-util
- 1.1.1
+ 1.1.2
```
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClass.java b/src/main/java/cn/wubo/loader/util/class_loader/DynamicClass.java
index 26694550174133361377e79540adc3cc00c8be4f..e8d049d0a53e5177137ec94ecc28bca20c1a759b 100644
--- a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClass.java
+++ b/src/main/java/cn/wubo/loader/util/class_loader/DynamicClass.java
@@ -8,6 +8,7 @@ import javax.tools.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -19,7 +20,7 @@ public class DynamicClass {
@Getter
private String fullClassName;
private List options = new ArrayList<>();
- private byte[] classData;
+ private MemFileManager fileManager;
public DynamicClass(String javaSourceCode, String fullClassName) {
this.javaSourceCode = javaSourceCode;
@@ -28,8 +29,9 @@ public class DynamicClass {
/**
* 初始化一个DynamicClass对象
+ *
* @param javaSourceCode Java源代码字符串
- * @param fullClassName 完整的类名
+ * @param fullClassName 完整的类名
* @return 初始化后的DynamicClass对象
*/
public static DynamicClass init(String javaSourceCode, String fullClassName) {
@@ -140,9 +142,8 @@ public class DynamicClass {
return this;
}
-
/**
- * 编译方法
+ * 编译Java代码
*
* @return 返回DynamicClass对象
*/
@@ -156,7 +157,7 @@ public class DynamicClass {
DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>();
// 创建内存文件管理器
- MemFileManager fileManager = new MemFileManager(compiler.getStandardFileManager(diagnosticCollector, null, null));
+ this.fileManager = new MemFileManager(compiler.getStandardFileManager(diagnosticCollector, null, null));
// 创建JavaMemSource对象
JavaMemSource file = new JavaMemSource(fullClassName, javaSourceCode);
@@ -169,22 +170,17 @@ public class DynamicClass {
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, options, null, compilationUnits);
log.debug("执行编译");
+ boolean result = task.call();
// 执行编译任务
- if (Boolean.TRUE.equals(task.call())) {
- log.debug("编译成功");
- // 如果编译成功,将生成的Java类数据保存到classData变量中
- classData = fileManager.getJavaMemClass().getBytes();
- } else {
- StringBuilder message = new StringBuilder();
- // 遍历诊断收集器中的诊断信息,将错误信息添加到message中
- for (Diagnostic extends JavaFileObject> diagnostics : diagnosticCollector.getDiagnostics()) {
- message.append("\r\n").append(diagnostics.toString());
- }
- log.debug("编译失败 {}", message);
- // 如果编译失败,抛出LoaderRuntimeException异常,并传递错误信息
- throw new LoaderRuntimeException(message.toString());
+ if (!result) {
+ // 处理编译错误
+ String errorMessage = diagnosticCollector.getDiagnostics().stream()
+ .map(Object::toString)
+ .reduce("", (acc, x) -> acc + "\r\n" + x);
+ log.debug("编译失败: {}", errorMessage);
+ throw new LoaderRuntimeException("编译失败: " + errorMessage);
}
- // 返回DynamicClass对象
+ log.debug("编译成功");
return this;
}
@@ -198,13 +194,17 @@ public class DynamicClass {
*/
public Class> load() {
try {
- // 创建一个动态类加载器
- DynamicClassLoader myClassLoader = new DynamicClassLoader(classData);
- // 使用加载器加载指定的类
- return myClassLoader.loadClass(fullClassName);
+ // 获取已编译的类数据
+ Map compiledClasses = fileManager.getAllCompiledClassesData();
+ // 创建动态类加载器
+ DynamicClassLoader classLoader = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
+ // 将已编译的类数据添加到动态类加载器中
+ compiledClasses.forEach(classLoader::addClass);
+ // 加载指定类的类对象
+ return classLoader.loadClass(fullClassName);
} catch (ClassNotFoundException e) {
- // 如果找不到指定的类,则抛出运行时异常
- throw new LoaderRuntimeException(e.getMessage(), e);
+ // 加载类失败,抛出LoaderRuntimeException异常
+ throw new LoaderRuntimeException("加载类失败: " + e.getMessage(), e);
}
}
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java b/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java
index 82bc6f2c727fa4c0c107868b26c78a852a28199d..68b667e93cde5e6c284b8622c77cb72280570cae 100644
--- a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java
+++ b/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java
@@ -1,6 +1,8 @@
package cn.wubo.loader.util.class_loader;
import java.security.SecureClassLoader;
+import java.util.HashMap;
+import java.util.Map;
/**
* @description:动态编译加载器
@@ -10,25 +12,34 @@ import java.security.SecureClassLoader;
public class DynamicClassLoader extends SecureClassLoader {
/**
- * 编译的时候返回的class字节数组
+ * 编译的时候返回的class字节数组-支持内部类
*/
- private byte[] classData;
+ private final Map classBytes = new HashMap<>();
- public DynamicClassLoader(byte[] classData) {
- super();
- this.classData = classData;
+ public DynamicClassLoader(ClassLoader parent) {
+ super(parent);
}
+ public void addClass(String fullClassName, byte[] classData) {
+ classBytes.put(fullClassName, classData);
+ }
+
+ /**
+ * 重写父类方法,用于查找指定的类。
+ *
+ * @param fullClassName 指定的类名
+ * @return 查找到的类对象
+ * @throws ClassNotFoundException 如果找不到指定的类,则抛出该异常
+ */
@Override
protected Class> findClass(String fullClassName) throws ClassNotFoundException {
- // 1. 判断编译的class字节数组为null,若为null则说明已经编译过,无需再编译
- if (classData == null || classData.length == 0)
- throw new ClassNotFoundException("[动态编译]classdata不存在");
- // 2. 加载class字节数组
+ // 获取指定类的字节码数据
+ byte[] classData = classBytes.get(fullClassName);
+ if (classData == null) {
+ // 如果找不到指定的类,则抛出ClassNotFoundException异常
+ throw new ClassNotFoundException("[动态编译]找不到类: " + fullClassName);
+ }
+ // 定义并返回指定的类对象
return defineClass(fullClassName, classData, 0, classData.length);
}
-
-
-
-
}
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java b/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java
index 7c663b3b8f5efc03e3bdc4f54e398ddb1641534f..2ad832d276b064db59ef354325c96b3e2885a9ef 100644
--- a/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java
+++ b/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java
@@ -4,6 +4,8 @@ import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import java.util.HashMap;
+import java.util.Map;
/**
* @description: 内存文件管理器
@@ -12,32 +14,41 @@ import javax.tools.JavaFileObject;
*/
public class MemFileManager extends ForwardingJavaFileManager {
- /**
- * class内存对象
- */
- private JavaMemClass javaMemClass;
+ private final Map compiledClasses = new HashMap<>();
- protected MemFileManager(JavaFileManager fileManager) {
- super(fileManager);
- }
-
- public JavaMemClass getJavaMemClass() {
- return javaMemClass;
- }
-
- /**
- * 根据给定参数获取用于输出Java代码的JavaFileObject对象。
- *
- * @param location 代码发生的位置
- * @param className 类名
- * @param kind Java文件对象的类型
- * @param sibling 与新创建的JavaFileObject具有相同父级文件对象的兄弟文件对象
- * @return 用于输出Java代码的JavaFileObject对象
- */
- @Override
- public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
- javaMemClass = new JavaMemClass(className, kind);
- return javaMemClass;
- }
+ protected MemFileManager(JavaFileManager fileManager) {
+ super(fileManager);
+ }
+ /**
+ * 根据给定参数获取用于输出Java代码的JavaFileObject对象。
+ *
+ * @param location 代码发生的位置
+ * @param className 类名
+ * @param kind Java文件对象的类型
+ * @param sibling 与新创建的JavaFileObject具有相同父级文件对象的兄弟文件对象
+ * @return 用于输出Java代码的JavaFileObject对象
+ */
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
+ // 这里创建的JavaMemClass实例会被JavaCompiler用来存储编译好的类的字节码数据
+ JavaMemClass javaMemClass = new JavaMemClass(className, kind);
+ // 存储编译好的类
+ compiledClasses.put(className, javaMemClass);
+ return javaMemClass;
+ }
+
+ /**
+ * 获取所有编译好的类的字节码数据
+ *
+ * @return 所有编译好的类的字节码数据的Map,键为类名,值为类的字节码数据
+ */
+ public Map getAllCompiledClassesData() {
+ Map classDataMap = new HashMap<>();
+ for (Map.Entry entry : compiledClasses.entrySet()) {
+ // 将每个编译好的类的字节码数据存入Map中
+ classDataMap.put(entry.getKey(), entry.getValue().getBytes());
+ }
+ return classDataMap;
+ }
}