JavaCompiler在线编译Java

本文链接:

Javascript大神都知道 js中eval函数可谓是相当的强大,任何数据都能将其转换成可执行的代码,最近刚刚把项目上线了,于是乎闲暇时间记录一下之前项目中使用的技术,现在依然记得那是一个悲惨的开发岁月,被产品的需求折磨着,也是绞尽脑汁,说实在的个人写代码方面一致朝着可扩展性方向追求,业务更换灵活,由于公司自己的产品,种类繁多,涉及到金额,以及计算公式,每个产品的计算公式都不一样,而且在业务上还要方便扩展.于是就想到了在java中使用js库,js库中使用eval来计算公式,说实在的,业务倒是蛮灵活的,可是执行速度,那可是与编译型语言差远了,性能差,这是个问题,于是最近想到了一个解决方案

能不能用java自己的方式实现类似于js中的eval? 答案当然是肯定的啦........

好了,废话不多说,直接上干货,今天我们就自己来实现eval函数, 我们会用到的方式 ,java的反射,以及今天认识一个api

1.首先我们来认识一下 java中的一个对象 JavaCompiler

JavaCompiler : 不知道肯定很陌生,其实这个api出来很久了,他是jdk6的特性,用来编译java的源程式的,详细介绍可以参考百度或google一下,介绍都很详细

Java的反射 : 这个我不多做介绍了,程序中很常见,基本上java程序员都会接触到,列入金典的框架 spring 等等......

接下来我们就去使用这个api来实现eval方法,  上干货

 

/**
     * 装载字符串成为java可执行文件
     * @param className className
     * @param javaCodes javaCodes
     * @return Class
     */
    private  Class<?> compile(String className, String javaCodes) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,                 null, null);
        StrSrcJavaObject srcObject = new StrSrcJavaObject(className, javaCodes);
        Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(srcObject);
        String flag = "-d";
        String outDir = "";
        try {
            File classPath = new File(Thread.currentThread().getContextClassLoader().getResource("").toURI());
            outDir = classPath.getAbsolutePath() + File.separator;
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }
        Iterable<String> options = Arrays.asList(flag, outDir);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, fileObjects);
        boolean result = task.call();
        if (result == true) {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

上面的代码也是较为核心的部分 ,就是将我们的字符串转换成一个java类,然后编译成class 重点看call(),

call(): 此方法就是进行动态编译可执行的代码

编译完成后,会返回boolean  为true表示编译成功,反之则, 或者 error : java.lang.illegalstateexception' ....... 出现异常情况时,不要慌张,可能这时脑回路不正确,参考我的代码,比较一下自己的出处.

接下来我们得到编译完成的class , 成功后class已经加载到内存中了,我们这是只需要通过java的反射去找到该类文件并执行它就好了

private Object run(String method,String codes){
 
        String className = "com.test.Eval";
        StringBuilder sb = new StringBuilder();
        sb.append("package com.test;");
        sb.append("\n public class Eval{\n ");
        sb.append(codes);
        sb.append("\n}");
 
        Class<?> clazz = compile(className, sb.toString());
        try {
            // 生成对象
            Object obj = clazz.newInstance();
            Class<? extends Object> cls = obj.getClass();
            // 调用main方法
            Method m = clazz.getMethod(method,String[].class);
            Object invoke = m.invoke(obj, new Object[] { new String[] {} });
            return invoke;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
 
    }
public static Object eval() {
        Eval eval = mWeakReference.get();
 
        String method = "main";
 
        String codes = "public static void main(String[]args){" +
                "System.out.print(\"hello world\"); }";
 
        eval.run(method,codes);
        return null;
    }
 
 
    public static void main(String[] args) {
        eval();
    }

好了,代码完成,我们看一下执行结果

Java eval  demo 地址 : https://github.com/SunnyLive/JavaEval.git

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值