Js中有eval函数,可以执行字符串。具体思路是这样的
首先生成源代码,然后进行编译,最后通过反射的方式加载类文件,创建实例,执行方法。
方法1:
public class EvalSuccess extends ClassLoader {
public static void main(String[] args) {
EvalSuccess escs = new EvalSuccess();
try {
escs.eval();
}catch (Exception e){
e.printStackTrace();
}
}
public void eval()throws Exception{
//生成源代码
String str = "public class Temp{public void test(){System.out.println(\"Hello\");}}";
System.out.println(this.getResource("").getPath());
File f = new File(this.getResource("").getPath() + "Temp.java");
PrintWriter pw = new PrintWriter(new FileOutputStream(f));
pw.println(str);
pw.close();
//编译
this.compile(f.getPath());
// 通过反射的方式获取类的Class
Class<?> clazz = this.loadClass("Temp");
Method main = clazz.getMethod("test");
//生成实例,执行方法
Object m = clazz.newInstance();
main.invoke(m);
}
/**编译源代码
*@author -武刚鹏-2018/2/12
* @param -文件路径
* @return
**/
public boolean compile(String filename)throws Exception{
Process p = Runtime.getRuntime().exec("javac " + filename);
try{
p.waitFor();
}catch (Exception e){
System.out.println(e);
}
int ret = p.exitValue();
return ret ==0;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class clazz = null;
String fileStub = name.replace(".","/");
String javaFilename = fileStub + ".java";
String classFilename = fileStub + ".class";
File javaFile = new File(javaFilename);
File classFile = new File(classFilename);
if(javaFile.exists() && (!classFile.exists() || classFile.lastModified() > javaFile.lastModified())){
try{
if(!compile(javaFilename) || !classFile.exists()){
throw new ClassNotFoundException("ClassNotFoundException:" + javaFilename);
}
}catch (Exception e){
e.printStackTrace();
}
}
if(classFile.exists()){
try{
byte[] raw = getBytes(classFilename);
clazz = defineClass(name,raw,0,raw.length);
}catch (IOException e){
e.printStackTrace();
}
}
if(clazz == null){
throw new ClassNotFoundException(name);
}
return clazz;
}
private byte[] getBytes(String filename)throws IOException{
File file = new File(filename);
long len = file.length();
byte[] raw = new byte[(int)len];
try(FileInputStream fin = new FileInputStream(file);){
int r = fin.read(raw);
if(r!= len){
throw new IOException("无法读取全部文件!" + r + "!=" + len);
}
return raw;
}
}
}
方法二:
public class EvalOnline {
public static void main(String[] args) throws Exception{
EvalOnline evalOnline = new EvalOnline();
evalOnline.eval();
// evalOnline.getPath();
}
/**
* eval函数的实现
* @throws Exception
*/
public void eval() throws Exception{
//1、生成源代码
String sourceStr = "public class Hello{public String sayHello(String name){return \"Hello, \"+name;}}";
String clsName = "Hello";
//2、设置编译的一些条件,以及生成编译到 文件单元
String methodName = "sayHello";
JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = cmp.getStandardFileManager(null,null,null);
JavaFileObject jfo = new StringJavaObject(clsName,sourceStr);
List<String> optionsList = new ArrayList<>();
String path = this.getClass().getResource("/").getPath();
System.out.println(path);
optionsList.addAll(Arrays.asList(new String[]{"-d",path}));
List<JavaFileObject> jfos = Arrays.asList(new JavaFileObject[]{jfo});
JavaCompiler.CompilationTask task = cmp.getTask(null,fm,null,
optionsList,null,jfos);
//3、task.call进行编译,编译成功
if(task.call()){
//4、生成实例
Object obj = Class.forName( clsName).newInstance();
//
Class<? extends Object> cls = obj.getClass();
//5、执行方法 调用sayHello方法
Method m = cls.getMethod(methodName,String.class);
String str = (String)m.invoke(obj,"武刚鹏");
System.out.println(str);
}
}
//获取一些路径的方法
public void getPath(){
// 第一种:获取类加载的根路径 D:\git\daotie\daotie\target\classes
File f = new File(this.getClass().getResource("/").getPath());
System.out.println("类加载的根路径:" + f);
// 获取当前类的所在工程路径; 如果不加“/” 获取当前类的加载目录 D:\git\daotie\daotie\target\classes\my
File f2 = new File(this.getClass().getResource("").getPath());
System.out.println("当前类的加载目录"+ f2);
// 第二种:获取项目路径 D:\git\daotie\daotie
File directory = new File("");// 参数为空
try{
String courseFile = directory.getCanonicalPath();
System.out.println("项目路径:" + courseFile);
}catch (Exception e){
e.printStackTrace();
}
// 第三种: file:/D:/git/daotie/daotie/target/classes/
URL xmlpath = this.getClass().getClassLoader().getResource("");
System.out.println(xmlpath);
System.out.println( "当前类的包名:" + this.getClass().getPackage().getName());
// 第四种: D:\git\daotie\daotie
// System.out.println(System.getProperty("user.dir"));
/*
* 结果: C:\Documents and Settings\Administrator\workspace\projectName
* 获取当前工程路径
*/
// 第五种: 获取所有的类路径 包括jar包的路径
// System.out.println(System.getProperty("java.class.path"));
}
}