import javax.tools.*;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
public class SynamicCompiler extends ClassLoader {
public static void main(String[] args) throws Exception {
String classPath = "D:/test/class" ;
System.out.println( calculate("1.0+1.0",classPath));
SynamicCompiler synamicCompiler = new SynamicCompiler();
Class clz = synamicCompiler.findClass("Main");
Method method = clz.getMethod("test");
Object obj = clz.newInstance();
method.invoke(obj);
}
protected Class<?> findClass(String name) {
String myPath = "file:/D:/test/class/Main.class";
System.out.println(myPath);
byte[] cLassBytes = null;
Path path = null;
try {
path = Paths.get(new URI(myPath));
cLassBytes = Files.readAllBytes(path);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
Class clazz = defineClass(name, cLassBytes, 0, cLassBytes.length);
return clazz;
}
private static double calculate(String expr,String classPath) throws Exception {
String className = "Main";
String methodName = "test";
String source = "public class " + className + " { public static void " + methodName + "() {System.out.println(\"Hello World!\")"
+ "; } }";
System.out.println(source);
boolean result = complie(source,className, classPath);
System.out.println(result);
return 0;
}
public static boolean complie(String source,String className,String classPath){
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
StringSourceJavaObject sourceObject = null;
try {
Iterable<String> options = Arrays.asList("-d", classPath);
sourceObject = new SynamicCompiler.StringSourceJavaObject(className, source);
Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(sourceObject);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, fileObjects);
boolean result = false;
try{
result = task.call();
}catch (Exception e) {
System.out.println("============");
}
return result ;
} catch (URISyntaxException e) {
e.printStackTrace();
}
return false ;
}
private static class StringSourceJavaObject extends SimpleJavaFileObject {
private String content = null;
public StringSourceJavaObject(String name, String content) throws URISyntaxException {
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.content = content;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return content;
}
}
}
上面那个类可以实现动态编译java文件并将编译的class内容存在磁盘
MemoryJavaFileManager可以重定向class字节码的内容,可以直接在内存中获取到字节码内容,操作步骤和上面一样只是compiler.getTask(),的参数改成,compiler.getTask(null, memoryJavaFileManager, null, null, null, fileObjects);就可以现实内存直接获取字节码内容了。
final class MemoryJavaFileManager extends ForwardingJavaFileManager {
/**
* Java source file extension.
*/
private final static String EXT = ".java";
private Map<String, byte[]> classBytes;
public MemoryJavaFileManager(JavaFileManager fileManager) {
super(fileManager);
classBytes = new HashMap<>();
}
public Map<String, byte[]> getClassBytes() {
return classBytes;
}
public void close() throws IOException {
classBytes = new HashMap<String, byte[]>();
}
public void flush() throws IOException {
}
/**
* A file object that stores Java bytecode into the classBytes map.
*/
private class ClassOutputBuffer extends SimpleJavaFileObject {
private String name;
ClassOutputBuffer(String name) {
super(toURI(name), Kind.CLASS);
this.name = name;
}
public OutputStream openOutputStream() {
return new FilterOutputStream(new ByteArrayOutputStream()) {
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
classBytes.put(name, bos.toByteArray());
}
};
}
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
String className,
JavaFileObject.Kind kind,
FileObject sibling) throws IOException {
if (kind == JavaFileObject.Kind.CLASS) {
return new ClassOutputBuffer(className);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
static URI toURI(String name) {
File file = new File(name);
if (file.exists()) {
return file.toURI();
} else {
try {
final StringBuilder newUri = new StringBuilder();
//mfm是uri的写法,这里的mfm是自己定义的,可以按照自己喜欢的定义
newUri.append("mfm:///");
newUri.append(name.replace('.', '/'));
if (name.endsWith(EXT)) newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT);
return URI.create(newUri.toString());
} catch (Exception exp) {
return URI.create("mfm:///com/sun/script/java/java_source");
}
}
}
}
分享到:
相关推荐
本片文档剖析了java动态代理的原理。具体请看文档
java在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava...
下面小编就为大家带来一篇基于Protobuf动态解析在Java中的应用 包含例子程序。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
解析javadom解析javadom解析javadom解析javadom解析
深入解析Java虚拟机
java解析PDF格式的文件demo。JAVA实现PDF解析,对PDF文件中的文本内容可输出仅供参考学习,不喜勿喷。
java 解析 json文件java 解析 json文件java 解析 json文件java 解析 json文件java 解析 json文件
包括pom文件导入依赖,封装解析文件java类完整版,源yaml文件等
用Java写的Cron表达式解析, Java swing编写的简洁界面,表达式到界面,界面到表达式,实现双重解析
深度解析Java游戏服务器开发源代码 深度解析Java游戏服务器开发源代码 深度解析Java游戏服务器开发源代码
用JAVA解析DBC文件,考虑大小端,生成文件内容跟Vector CANDB++相同。
提供通过meteoInfo+geotools解析shp文件,提取出shp文件中的数据,javaj技术实现,获取边界线数据、中心点坐标、最大、最小经纬度值等
功能:读取DBC文件,将Bo_、SG_解析封装到实体类里,方便下一步的开发。
jar包里面包含了:hapi解析HL7的代码范例,所需jar包。亲测可用。《Java版本》
没有公网IP的就不要下载了吧,比如自己家里有宽带,一般家庭不是公网IP,你可以向运营商申请一下还是可以的,有了公网IP可以去阿里云,华为云等等买一个域名,新用户很便宜的,有了前两个利用工具自动动态解析 ...
modbus-rtu解析Java相关所需资源
eclipse idea 导入可以直接使用,解析环保212协议代码,已经封装好,亲测可用。
java实现gps信号的接收与解析。java实现gps信号的接收与解析。java实现gps信号的接收与解析。java实现gps信号的接收与解析。
java实现的EPUB 解析模块,从开源项目FBreader中优化出来的模块代码
支持解析sql的正确性,可以解析出sql 的列名,表名,别名,条件等,非常好用