java在线编译功能

码云开源代码:

https://gitee.com/china-bin/vue-onlinecode

原理:
1.利用java里面有JavaComile 可以实现在程序里面编译允许其他的java代码

步骤:
1.利用JavaComile, 将java代码 编译到内存中
2.从内存中根据类名取出此类
3.通过java反射调用此类的方法

详细Demo代码如下:

import com.haiyang.onlinejava.complier.util.ClassClassLoader;

import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;

/**
 * @author: bin
 * @email: 958615915@qq.com
 * @create: 2019-08-03
 */
public class TestComiles {
    private String javaSource = "class Solution {   " +
            " public static String sayHello() {                return \"hello world\";        } " +
            "}";

    private String javaSource2 = "class Solution {   " +
            " public static String sayHello(int i) {                return \"hello world\" + i;        } " +
            "}";

    private String className = "Solution";

    private String methoName = "sayHello";
    // path 是你想把.class 放在哪里的路径,
    private String path = "C:\\Users\\bin\\Desktop\\java\\";

    public void comile() throws Exception {
        // javqComile 是java程序里的java编译器类
        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

        // StandardJavaFileManager 对象主要负责
        // 编译文件对象的创建,编译的参数等等,我们只对它做些基本设置比如编译 CLASSPATH 等。
        StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);

            // JavaFileObject 为类文件上进行操作的工具的文件抽象
        StringObject stringObject = new StringObject(className, javaSource2);

        JavaFileObject javaFileObject = stringObject;

        // Array Map Set 等都属于Itreable类型
        Iterable options = Arrays.asList("-d", path);

        Iterable<? extends JavaFileObject> files = Arrays.asList(javaFileObject);

        // 通过一些选项,javafileObject, classPath 来获取JvaComiler.ComilationTask
        JavaCompiler.CompilationTask task = javaCompiler.getTask(null,
                standardJavaFileManager, null, options, null, files);

        // 将Class 在内存中编译
        Boolean result = task.call();

        // 通过类名 加载class
        ClassLoader classLoader = new ClassClassLoader(getClass().getClassLoader());
//        ClassLoader classLoader = getClass().getClassLoader();
        Class cls = classLoader.loadClass(className);

        // java反射机制 method.setAcessible 设置允许访问
        Method method = cls.getMethod(methoName, int.class);
        method.setAccessible(true);

        Object[] args = new Object[]{2};
        args[0] = 1;

        Object obj = method.invoke(null, args);

        System.out.println(obj.toString());
    }

    public static void main(String[] args) {

        try {
            new TestComiles().comile();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private class StringObject extends SimpleJavaFileObject {
        private String contents = null;

        public StringObject(String clasName, String contents) throws Exception {
            super(URI.create("String:///" + clasName + Kind.SOURCE.extension), Kind.SOURCE);
            this.contents = contents;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return contents;
        }
    }

    private class ClassClassLoader extends ClassLoader {

        ClassClassLoader(ClassLoader parent) {
            super(parent);
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            //这个classLoader的主要方法
            String classPath = name.replace(".", "\\") + ".class";//将包转为目录
            String classFile = path + classPath;//拼接完整的目录
            Class clazz = null;
            try {
                byte[] data = getClassFileBytes(classFile);
                clazz = defineClass(name, data, 0, data.length);
                if (null == clazz) {//如果在这个类加载器中都不能找到这个类的话,就真的找不到了


                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            return clazz;

        }

        private byte[] getClassFileBytes(String classFile) throws Exception {
            //采用NIO读取
            FileInputStream fis = new FileInputStream(classFile);
            FileChannel fileC = fis.getChannel();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            WritableByteChannel outC = Channels.newChannel(baos);
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            while (true) {
                int i = fileC.read(buffer);
                if (i == 0 || i == -1) {
                    break;
                }
                buffer.flip();
                outC.write(buffer);
                buffer.clear();
            }
            fis.close();
            return baos.toByteArray();
        }
    }


}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值