写在前面
又是一年毕业季。
毕业设计选题的时候一时兴起选了 Online Jedge 系统的设计与实现,但是,理想是丰满的,现实是骨感的,本人的技术不到位啊~
当初想得挺简单的:一个安全编译,一个线程池,一个消息队列,一个前后端交互。现在回想起来…
虽然说有些难度,但是定下来的东西总得去完成吧,我做事喜欢按照自己的思路来。
既然有代码提交过来,如果想要执行,按照Java语言的特性,那就得先编译
基于cmd的方式
记得一开始学Java的时候,安装完jdk
后会在cmd
控制台中输入 Java
或 Javac
命令来测试环境是否安装成功。其中 java classname
可以执行一个class文件, javac demod.java
则是启动Java编译器对已有的Java文件进行编译。
public static void test() {
Scanner ins = new Scanner(System.in);
Runtime runtime = Runtime.getRuntime();
Process P;
while (true) {
try {
P = runtime.exec("cmd /c "+ins.nextLine());
//获取输入流
BufferedReader input = new BufferedReader(new InputStreamReader(P.getInputStream()));
//获取错误流
BufferedReader err = new BufferedReader(new InputStreamReader(P.getErrorStream()));
for (String line = input.readLine(); line != null; line = input.readLine())
System.out.println(line);
for (String line = err.readLine(); line != null; line = err.readLine())
System.out.println(line);
} catch (IOException e) {
System.out.println("error");
}
}
}
主要的原理是利用 Runtime
去执行cmd
命令
但是这种方式有一个很致命的缺点:程序是由系统另外开启一个进程来执行的,不可控!
cmd编译,反射执行
基于上面的方法,我想出了一个补救方案
在这里我们先回顾一下类的生命周期
- 加载(Loading):从硬盘中读取二进制字节码文件,加载到虚拟机中
- 检查(Verification): 验证加载进来的class文件格式对不对,安不安全
- 准备(Preparation): 确定内存, 对静态/常量赋初始值
- 解析(Resolution): 把字符引用转化为直接引用
- 初始化(Initialization): 调用一些自定义的代码,比如说静态代码块
- 使用(Using):
- 卸载(Unloading):
在Java中使用 Class.forName()
就是对类进行加载
public static void main(String[] args) throws Exception {
Runtime runtime = Runtime.getRuntime();
Process P = runtime.exec("cmd /c cd ./src/test/ & javac Main.java -d ../../bin/");
//获取输入流
BufferedReader input = new BufferedReader(new InputStreamReader(P.getInputStream()));
//获取错误流
BufferedReader err = new BufferedReade