一、前言
- 使用过leetcode或者类似在线编译网站功能的人,或许会比较感兴趣,关于在线编译的实现原理,由于我比较头铁,所以一冲动之下毕业设计的项目选择制作一个类似于在线编译的一个网站。
- 在决定做这个之前,大概对这方面的东西一窍不通,网上的资料很多也是比较千篇一律,给我这种萌新带来的难度不是一点半点,当然,最终收获还是挺大的,所以想写一点东西,作为梳理,也给以后想学的人做一个参考作用(其实在写的过程中还是踩了一些坑的)。
- 最终,其实成果挺水的,做出来的成品,就只是实现了一个简陋的Java语言的在线编译功能,这里也想吐槽一下,其实leetcode,支持那么多语言的在线编译真的挺厉害的。
二、前期准备
首先在运行java程序之前,肯定要想办法把.java
的文件使用编译器,编译成.class
的字节码文件。
运气好的是,强大的Java已经具备类似的API,就是JavaCompiler
类,下面做一点简单介绍:
JavaCompiler是java语言自带的一个接口,大概是一个对Java编译器的一个抽象,通过ToolProvider 类的静态方法获取其实现对象:
public interface JavaCompiler extends Tool, OptionChecker
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
稍微看一下源码
private static final String defaultJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; private static synchronized ToolProvider instance() { if (instance == null) instance = new ToolProvider(); return instance; } /** * Gets the Java™ programming language compiler provided * with this platform. * @return the compiler provided with this platform or * {@code null} if no compiler is provided */ public static JavaCompiler getSystemJavaCompiler() { return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName); }
可以知道,返回的是一个JavacTool对象,是一个接口实现类
public final class JavacTool implements JavaCompiler {
这个类实现了run
方法
public interface Tool { int run(InputStream in,<mark>本文来源gaodaimacom搞#^代%!码&网(</mark> OutputStream out, OutputStream err, String... arguments); }
各个参数的意思分别是
in
java编译器提供信息
out
用于获取输出信息
err
用于获取错误信息
arguments
编译的文件(路径)
前面三个参数如果,为null
则会用默认标准输入输出代替。网上到处都搜的到不做累述。
三、JavaCompiler V1.0
于是就有了第一种在线编译运行的实现思路,使用文件IO来动态生成.java
格式的文件与路径,然后写入代码内容。
最初我便是打算姑且使用这种方式,由于数据封装对象UserDto与Question都具有一个唯一的Id属性,因此 xx.userId.questionId
似乎挺适合用来做生成文件的类路径的,类名就可以统一学习leetcode使用Solution ,于是一番努力后写出了我的Compilerv1.0
然而这种方式就给人感觉很low,“java动态编译”听起来还挺?诺模?峁?幌缚矗?驼猓?/p>