• 动态编译和加载java代码


    package me.silentdoer.dynamicgeneration;
    
    import javax.tools.JavaCompiler;
    import javax.tools.SimpleJavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import java.io.File;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.URI;
    import java.nio.charset.StandardCharsets;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    import java.util.Locale;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * if IDE is idea, change working dir to xxx/target/classes
     *
     * @author liqi.wang
     * @version 1.0.0
     * @since 2020/9/28 15:05
     */
    public class Entrance {
        /**
         * package's folder must exists
         */
        public static String inputCode = "package dynamic.generation.mock; public class UserFuck" +
                " { public static void test(){System.out.println("Hello444");}}";
    
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException
                , IllegalAccessException, InstantiationException, InvocationTargetException {
    
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.CHINA, StandardCharsets.UTF_8);
            // dynamic/generation is the based folder for generated code package
            File file = new File("dynamic/generation");
            if (file.exists() && file.isFile()) {
                throw new IllegalStateException("package folder is a file");
            } else if (!file.exists()) {
                boolean flag = file.mkdirs();
                if (!flag) {
                    throw new IllegalStateException("create package's folder failure.");
                }
            }
            // can cache value, and if exists .class, ignore
            String className = parseClassName(inputCode);
            StringSourceJavaObject sourceObject = new StringSourceJavaObject(className, Entrance.inputCode);
            List<StringSourceJavaObject> objects = Collections.singletonList(sourceObject);
            // define output dir
            List<String> options = Arrays.asList("-d", "./");
            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, options, null, objects);
            Boolean compilerResult = task.call();
            if (compilerResult) {
                System.out.println("compile success");
                ClassLoader classLoader = Entrance.class.getClassLoader();
                // this throws ClassNotFoundException
                Class<?> userFuck = classLoader.loadClass(className);
                Method test = userFuck.getMethod("test");
                test.invoke(userFuck.newInstance());
            }
        }
    
        static String parseClassName(String inputCode) {
            Pattern packagePattern = Pattern.compile("package\s+(\S+);\s*");
            Matcher packageMatcher = packagePattern.matcher(inputCode);
            if (!packageMatcher.find()) {
                throw new IllegalArgumentException("input code is invalid.");
            }
            String packageName = packageMatcher.group(1);
            System.out.println("package: " + packageName);
            Pattern classSimpleNamePatter = Pattern.compile("public\s+class\s+(\w+)\s+\{");
            Matcher classSimpleNameMatcher = classSimpleNamePatter.matcher(inputCode);
            if (!classSimpleNameMatcher.find()) {
                throw new IllegalArgumentException("input code is invalid.");
            }
            String classSimpleName = classSimpleNameMatcher.group(1);
            System.out.println("className: " + classSimpleName);
            return packageName + "." + classSimpleName;
        }
    
        static class StringSourceJavaObject extends SimpleJavaFileObject {
    
            private final String sourceCode;
    
            public StringSourceJavaObject(String className, String sourceCode) {
                // DynamicCodeGen.UserFuck . to /
                super(URI.create("string:///" + className.replace(".", "/") + Kind.SOURCE.extension), Kind.SOURCE);
                this.sourceCode = sourceCode;
            }
    
            @Override
            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                return this.sourceCode;
            }
        }
    }
  • 相关阅读:
    关于JVM的一些东西
    网络的最大流最小割定理
    类的生命周期
    关于java中的不可变类(转)
    如何在Linux上升级java
    CAS操作
    如何使用fastJson来解析JSON格式数据和生成JSON格式数据
    计算机中如何实现除数是2的幂次的除法【转载自CSDN】
    python:使用Fabric自动化你的任务
    python中的元类
  • 原文地址:https://www.cnblogs.com/silentdoer/p/13750458.html
Copyright © 2020-2023  润新知