package com.compile.shell;
import com.alibaba.fastjson.JSONObject;
import com.compile.executor.JavaShellExecutor;
import javax.tools.*;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
/**
* Compile动态执行java的String代码到内存中并执行
* 1.创建 URLClassLoader 类加载器
* 2.获取当前执行的classpath的所有jar包的路径
* 3.通过java的ToolProvider创建JavaCompile,用来执行class源文件
* 4.创建DiagnosticCollector用来执行获取执行失败的错误结果
* 5.添加动态执行的编译环境 options 是个集合,添加内容,字符集,classpath等
* 6.传入JavaFileObject的java文件,是个集合,创建JavaSourceObject实现这个接口,Kind.SOURCE.extension = '.java'
* 7.创建任务并执行
* 8.获取执行完成后的返回JavaClassObject类
* 9.创建DynamicClassLoader来加载类 ,defineClass这个方法
*
* @Description:
* @Auther: wjx
* @Date: 2019/1/18 14:55
*/
public class DynamicEngine extends JavaShellExecutor {
private static DynamicEngine dynamicEngine;
/**
* 单例模式
*
* @return
*/
public static DynamicEngine getInstance() {
if (dynamicEngine == null) {
synchronized (DynamicEngine.class) {
if (dynamicEngine == null) {
dynamicEngine = new DynamicEngine();
}
}
}
return dynamicEngine;
}
//创建动态加载jar包
private URLClassLoader classLoader;
//当前的classpath环境
private String classpath;
private DynamicEngine() {
//获取类加载器
this.classLoader = (URLClassLoader) this.getClass().getClassLoader();
this.buildClasspath();
}
private void buildClasspath() {
//初始化classpath为null
this.classpath = null;
StringBuilder sb = new StringBuilder();
for (URL url : this.classLoader.getURLs()) {
String f = url.getFile();
sb.append(f).append(File.pathSeparator);
}
this.classpath = sb.toString();
}
public Object javaCodeToObject(String className, String javaCode) {
//记录编译起始时间
long startTime = System.currentTimeMillis();
//通过java工具获取编译的compile
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//创建DiagnosticCollector对象
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
//建立一个用于保存java文件管理器ClassFileManage
//每一个文件被保存在JavaClassObject的类里面
ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null));
//使用编译选项可以默认编译行为,编译选项是一个String的Iterable集合
List<String> options = new ArrayList<>();
options.add("-encoding");
options.add("UTF-8");
options.add("-classpath");
options.add(this.classpath);
//传递源文件,是一个JavaFileObject的集合
List<JavaFileObject> fileObjectList = new ArrayList<>();
fileObjectList.add(new JavaSourceObject(className, javaCode));
//创建任务
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, options, null, fileObjectList);
//执行编译
Boolean call = task.call();
if (call) {
//编译成功
System.out.println("编译成功");
} else {
//编译失败
System.out.println("编译失败");
String error = null;
for (Diagnostic diagnostic : diagnosticCollector.getDiagnostics()) {
error += compilePrint(diagnostic);
}
throw new RuntimeException(error);
}
return fileManager.getJavaClassObject();
}
/**
* @param diagnostic
* @return
* @MethodName : compilePrint
* @Description : 输出编译错误信息
*/
private String compilePrint(Diagnostic diagnostic) {
System.out.println("Code:" + diagnostic.getCode());
System.out.println("Kind:" + diagnostic.getKind());
System.out.println("Position:" + diagnostic.getPosition());
System.out.println("Start Position:" + diagnostic.getStartPosition());
System.out.println("End Position:" + diagnostic.getEndPosition());
System.out.println("Source:" + diagnostic.getSource());
System.out.println("Message:" + diagnostic.getMessage(null));
System.out.println("LineNumber:" + diagnostic.getLineNumber());
System.out.println("ColumnNumber:" + diagnostic.getColumnNumber());
StringBuffer res = new StringBuffer();
res.append("Code:[" + diagnostic.getCode() + "]\n");
res.append("Kind:[" + diagnostic.getKind() + "]\n");
res.append("Position:[" + diagnostic.getPosition() + "]\n");
res.append("Start Position:[" + diagnostic.getStartPosition() + "]\n");
res.append("End Position:[" + diagnostic.getEndPosition() + "]\n");
res.append("Source:[" + diagnostic.getSource() + "]\n");
res.append("Message:[" + diagnostic.getMessage(null) + "]\n");
res.append("LineNumber:[" + diagnostic.getLineNumber() + "]\n");
res.append("ColumnNumber:[" + diagnostic.getColumnNumber() + "]\n");
return res.toString();
}
/**
* 创建一个新的ClassLoader
*
* @param ruleName
*/
public void createNewClassLoader(String ruleName) {
try {
DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.classLoader);
DataEventFactory.eventClassLoaders.put(ruleName, dynamicClassLoader);
} catch (Exception e) {
e.printStackTrace();
}
}
}

小海龟的吻
- 粉丝: 24
最新资源
- (源码)基于Arduino平台的颗粒物传感器监测系统.zip
- 近期国际金融基础设施机构区块链技术研究进展及重要观点.docx
- 20XXIT科技互联网年会创意策划案通用课件模板.pptx
- 物联网感知层设计的主要技术要点研究.docx
- 启程自动化培训机构每日一题案例解析三.doc
- 机械设计方案制造及其自动化(汽车工程)专业.doc
- 礼仪修养显个人魅力信息化说课稿.ppt
- 我的毕设-基于知识图谱和循环神经网络的推荐系统
- 根际微生物群落结构与生态功能
- 我国计算机业的发展状况.doc
- 启发式教学法在软件工程课程中的应用.docx
- 基于消费者心理视角网络广告效果评价研究分析.doc
- 影响计算机网络安全的因素及解决措施.docx
- C单片机远程数据采集系统设计方案.doc
- 计算机基础知识题集414道.doc
- 我国高校教育信息化现状及发展策略研究.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈


