模拟IDE上的run过程

看了一下老陈写的模仿JDK动态代理,从中取一部分单独扩展,模拟一下IDE上的run过程(不愧是老陈,去年写的东西我要现在才能理解)

对run过程的猜想

在点击run的过程中应该做了不少事。先编译运行run工具,执行引擎增加一个线程开始执行被加载的run工具的字节码指令;线程执行过程中将目标源码进行编译,获取ClassLoader实例对字节码进行加载,在堆上创建并初始化Class< T >对象,调用类运行时对象的静态main方法。

模拟工具实现run过程

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.lang.reflect.Method;

/**
 * USER: zzzz76
 * Date: 2017/12/30
 * Time: 16:44
 */
public class beforeRun {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        try {
            String fileName = args[0];
            System.err.println("run target: " + fileName);

            //拿到编译器
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            //文件管理者
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            //获取文件
            Iterable iterable = fileManager.getJavaFileObjects(fileName);
            //创建编译任务
            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
            //进行编译
            task.call();
            fileManager.close();
            System.err.println("************ compile successfully! ************");

            ClassLoader classLoader = ClassLoader.getSystemClassLoader();
            //加载目标字节码
            String className = fileName.substring(0, fileName.length() - 5);
            Class targetClass = classLoader.loadClass(className);
            //调用main方法
            Method method = targetClass.getDeclaredMethod("main", String[].class);
            method.invoke(null, (Object) new String[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * USER: zzzz76
 * Date: 2017/12/30
 * Time: 17:28
 */
public class Target {
    public static void main(String[] args) {
        System.out.println("run target!");
        Other.runOther();
    }
}

/**
 * USER: zzzz76
 * Date: 2017/12/30
 * Time: 18:14
 */
public class Other {
    public static void runOther() {
        System.out.println("run other!");
    }
}


运行结果

➜  Desktop javac beforeRun.java
➜  Desktop java beforeRun Target.java
run target: Target.java
************ compile successfully! ************
run target!
run other!



posted @ 2017-12-30 19:09  小z同学  阅读(467)  评论(0编辑  收藏  举报