zoukankan      html  css  js  c++  java
  • 动态运行java代码

    在产品中有时会遇到想动态调用java代码的时候,即在运行过程中,调用一段java代码字符串,经调研是可行的。代码如下:

     
    import javax.tools.*;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import static java.nio.file.Files.readAllBytes;
    import static java.nio.file.Paths.get;


    public class InlineCompiler {

        public static void main(String[] args) {
            String filename = "code.txt";
            String code = "";
            try {
                code = new String(readAllBytes(get(filename)));
            } catch (Exception e) {
            }
            System.out.println(code);
            String klassName = "GetMachineNo";
            String methodName = "execute";
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("machine_no", "a1b2");
            params.put("abc", "def");
            String result = getResult(code, klassName, methodName, params);
            System.out.println("result: " + result);
        }

        public static String getResult(String code, String klassName, String methodName, Map<String, Object> params) {

            try {

                DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                //System.out.println("compiler: " + compiler);
                //StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
                ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, null, null));

                List<String> optionList = new ArrayList<String>();

                //Iterable<? extends JavaFileObject> compilationUnit = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(codeFile));
                List<JavaFileObject> jfiles = new ArrayList<>();
                jfiles.add(new CharSequenceJavaFileObject(klassName, code));
                JavaCompiler.CompilationTask task = compiler.getTask(
                        null,
                        fileManager,
                        diagnostics,
                        optionList,
                        null,
                        //compilationUnit);
                        jfiles);
                if (task.call()) {
                    //URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("/tmp/javacode").toURI().toURL()});
                    //Class<?> loadedClass = classLoader.loadClass(klassName);
                    JavaClassObject jco = fileManager.getJavaClassObject();
                    //DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.parentClassLoader);
                    DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
                    Class<?> loadedClass = dynamicClassLoader.loadClass(klassName, jco);
                    Object obj = loadedClass.newInstance();
                    Method[] methods = loadedClass.getDeclaredMethods();
                    Method callMethod = null;
                    for (Method method : methods) {
                        if (method.getName().equals(methodName)) {
                            System.out.println("mn: " + method.getName());
                            callMethod = method;
                            break;
                        }
                    }
                    callMethod.setAccessible(true);
                    String result = (String) callMethod.invoke(obj, params);

                    return result;
                } else {
                    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                        System.out.format("Error on line %d in %s%n",
                                diagnostic.getLineNumber(),
                                diagnostic.getSource().toUri());
                    }
                }
                fileManager.close();
            } catch (IOException | InstantiationException | IllegalAccessException | InvocationTargetException exp) {
                exp.printStackTrace();
            }
            return "";
        }
    }


    class ClassFileManager extends ForwardingJavaFileManager {
        private JavaClassObject jclassObject;

        public ClassFileManager(StandardJavaFileManager standardManager) {
            super(standardManager);
        }

        public JavaClassObject getJavaClassObject() {
            return jclassObject;
        }

        //需要覆盖
        @Override
        public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind,
                                                   FileObject sibling) throws IOException {
            jclassObject = new JavaClassObject(className, kind);
            return jclassObject;
        }
    }


    class CharSequenceJavaFileObject extends SimpleJavaFileObject {

        private CharSequence code;

        public CharSequenceJavaFileObject(String className, CharSequence code) {
            super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
        }
    }


    class JavaClassObject extends SimpleJavaFileObject {

        private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        public JavaClassObject(String name, Kind kind) {
            super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
        }

        public byte[] getBytes() {
            return outputStream.toByteArray();
        }

        @Override
        public OutputStream openOutputStream() throws IOException {
            return outputStream;
        }
    }


    class DynamicClassLoader extends ClassLoader {
        public DynamicClassLoader(ClassLoader parent) {
            super(parent);
        }

        public Class loadClass(String fullName, JavaClassObject jco) {
            byte[] classData = jco.getBytes();
            return this.defineClass(fullName, classData, 0, classData.length);
        }
    }


    执行结果:


    import java.util.Map;

    public class GetMachineNo {
        
        public String execute(Map<String, Object> map) {
            try {
                return String.valueOf(map.get("machine_no")) + "_" + String.valueOf(map.get("abc"));
            } catch (Exception e) {
            }
            return "";
        }
    }





    mn: execute
    result: a1b2_def

  • 相关阅读:
    c++ 从vector扩容看noexcept应用场景
    c++11-17 模板核心知识(十一)—— 编写泛型库需要的基本技术
    动态链接的PLT与GOT
    c++11-17 模板核心知识(十)—— 区分万能引用(universal references)和右值引用
    Golang性能分析与优化
    c++11-17 模板核心知识(九)—— 理解decltype与decltype(auto)
    [LuoguP4808][CCC 2018]平衡树(数论分块+记忆化搜索)(有复杂度证明)
    [NOI2016]区间(线段树+尺取法)
    [BZOJ4316]小C的独立集(仙人掌+树形DP)
    [CTSC2002]灭鼠行动(模拟)
  • 原文地址:https://www.cnblogs.com/zycjwdss/p/15480689.html
Copyright © 2011-2022 走看看