博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单java在线测评程序
阅读量:6243 次
发布时间:2019-06-22

本文共 12685 字,大约阅读时间需要 42 分钟。

简单java程序在线测评程序

v一.前言

  大家过年好!今年的第一篇博客啊!家里没有网,到处蹭无线!日子过得真纠结!因为毕设的需求,简单写了一个java程序在线测评程序,当然也可以在本地测试。

v二.思路

  首先简单介绍一下思路:

  1.得到java程序的源代码,不需要导入包。得到源码之后在前面加入”import java.util.*;”

  2.通过JavaCompiler对象可以帮助我们将java源代码编译成class文件。

  3.通过DiagnosticCollector对象可以获得编译过程中产生的编译信息。

  4.通过StandardJavaFileManager对象管理生成的class文件,例如文件的存放位置。

  5.StringSourceJavaObject对象可以对java源码进行包装并处理。

数据是控制台输入的,所以要重定向System.in(注意保存标准的输入流);另外程序的输出是到标准的输出流的,为了获得输出结果,我的方法是重定向输出流到ByteArrayOutputStream,然后利用ByteArrayOutputStream构造BufferedReader

  6.运行程序,通过java的反射机制,获得main函数的Method对象。

  7.运行时间的计算通过System.currentTimeMillis()方法。

  8.程序所需内存通过RuntimefreeMemory()方法。

  9.异常信息的获取:StringWriter sw = new StringWriter();  e.printStackTrace(new PrintWriter(sw, true)); sw.toString();

 

v三.问题解决

1. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 出现NullPointerException

  查看部分源码如下:

 

private static final String[] defaultToolsLocation = { "lib", "tools.jar" };private Class
findSystemToolClass(String toolClassName) throws MalformedURLException, ClassNotFoundException { // try loading class directly, in case tool is on the bootclasspath try { return Class.forName(toolClassName, false, null); } catch (ClassNotFoundException e) { trace(FINE, e); // if tool not on bootclasspath, look in default tools location (tools.jar) ClassLoader cl = (refToolClassLoader == null ? null : refToolClassLoader.get()); if (cl == null) { File file = new File(System.getProperty("java.home")); if (file.getName().equalsIgnoreCase("jre")) file = file.getParentFile(); for (String name : defaultToolsLocation) file = new File(file, name); // if tools not found, no point in trying a URLClassLoader // so rethrow the original exception. if (!file.exists()) throw e; URL[] urls = { file.toURI().toURL() }; trace(FINE, urls[0].toString()); cl = URLClassLoader.newInstance(urls); refToolClassLoader = new WeakReference
(cl); } return Class.forName(toolClassName, false, cl); }}

 

打印 System.out.println(System.getProperty("java.home")); 如下:

 C:\Program Files (x86)\Java\jre6

defaultToolsLocation = { "lib", "tools.jar" }; 也就是最终到

C:\Program Files (x86)\Java\jre6\lib\tools.jar中寻找tools.jar

然而jre6\lib中没有tools.jar, 而是在C:\Program Files (x86)\Java\jdk\lib中。最直接的办法就是将它复制进去就行了。

 

2.异常信息的获取。

 

3.输入流和输出流的重定向。

 

详细内容请看代码!

v四.代码

 

import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintStream;import java.io.PrintWriter;import java.io.StringWriter;import java.lang.reflect.Method;import java.net.URI;import java.util.Arrays;import java.util.regex.Matcher;import java.util.regex.Pattern;import javax.tools.Diagnostic;import javax.tools.DiagnosticCollector;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.StandardLocation;import javax.tools.ToolProvider;public class CompileAndRunJavaFile {    public static void main(String[] args) {        StringBuilder code = new StringBuilder();        try {            BufferedReader br = new BufferedReader(new FileReader(new File("测试程序地址")));            String content;            while((content = br.readLine()) != null){                code.append(content).append("\n");            }        } catch (Exception e) {            e.printStackTrace();        }        CompileAndRunJavaFile cr = new CompileAndRunJavaFile();        cr.compileAndRunJavaFile(code.toString());        if(cr.isCompileAndRunOK()) {            System.out.println("运行时间: " + cr.getUseTime() + "ms");            System.out.println("内存使用: " + cr.getUseMemory() + "kb9");            System.out.println("运行结果: \n" + cr.getOutMsg());        } else if(cr.isCompilerError()) {            System.out.println("编译错误: " + cr.getCE());        } else if(cr.isRunningError()) {            System.out.println("运行错误: " + cr.getError());        }    }    //编译错误    private StringBuilder ce = new StringBuilder();    public String getCE(){        return ce.toString();    }        //内存使用    private double useMemory = 0.0;    public double getUseMemory(){        return useMemory;    }        //运行时间    private long useTime = 0;    public long getUseTime(){        return useTime;    }    //输出信息    private StringBuilder outMsg = new StringBuilder();    public String getOutMsg(){        return outMsg.toString();    }    //异常信息    private String error = null;    public String getError(){        return error;    }    //是否正常编译并运行    private boolean isCompileAndRunOK = false;         public boolean isCompileAndRunOK(){        return isCompileAndRunOK;    }        //程序的运行时间, 单位:ms    private int limitTime = 2000;    //程序所占内存, 单位 :KB    private double limitMemory = 256000.0;        public void setLimitTime(int limitTime){        this.limitTime = limitTime;    }        public void setLimitMemory(double limitMemory){        this.limitMemory = limitMemory;    }        //是否为编译错误    private boolean isCompilerError = false;    public boolean isCompilerError(){        return isCompilerError;    }        //是否为运行错误    private boolean isRunningError = false;    public boolean isRunningError(){        return isRunningError;    }        private static final String className = "Main";    private static final String methodName = "main";    private String getClassOutput(){        //设置class文件的存放位置        if(System.getProperty("java.class.path").contains("bin")) return "bin/";        else return "./";    }        private void compileAndRunJavaFile(String code){        PrintStream ps = null;        FileInputStream fis = null;        BufferedReader br = null;        //保存标准输出流        InputStream stdIn = System.in;        //保存标准输入流        PrintStream stdOut = System.out;                //为源代码导入默认的包        code = "import java.util.*;\n" + code;        try {            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();            // define the diagnostic object, which will be used to save the            // diagnostic information            DiagnosticCollector
oDiagnosticCollector = new DiagnosticCollector
(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(oDiagnosticCollector, null, null); // set class output location fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(getClassOutput()) })); StringSourceJavaObject sourceObject = new CompileAndRunJavaFile.StringSourceJavaObject(className, code); Iterable
fileObjects = Arrays.asList(sourceObject); CompilationTask task = compiler.getTask(null, fileManager, oDiagnosticCollector, null, null, fileObjects); boolean result = task.call(); if (result) { Runtime runtime = Runtime.getRuntime(); Class
clazz = Class.forName(className); Method method = clazz.getMethod(methodName, new Class
[]{String[].class}); //重置输入流, 需要存放数据文件的文件名 fis = new FileInputStream(new File("数据文件地址")); System.setIn(fis); //重置输出流,需要获得控制台的输出 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ps = new PrintStream(bao); System.setOut(ps); long startFreeMemory = runtime.freeMemory();//Java 虚拟机中的空闲内存量 //执行时间也是无法知道,因为dos执行java命令,程序无法知道它到底执行到那里了,两个进程,互不了解 long startCurrentTime = System.currentTimeMillis();//获取系统当前时间 method.invoke(null, new Object[]{
null}); long endCurrentTime = System.currentTimeMillis(); long endFreeMemory = runtime.freeMemory(); //内存的使用情况,不是很精确 useMemory = (startFreeMemory-endFreeMemory)/1024.0; if(useMemory > limitMemory) throw new Exception("Out Limit Memory!"); useTime = endCurrentTime-startCurrentTime; if(useTime > limitTime) throw new Exception("Time Limited!"); //获得控制台的输出 br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bao.toByteArray()))); String outc = null; while((outc = br.readLine()) != null) outMsg.append(outc).append("\n"); //正常编译并运行 isCompileAndRunOK = true; } else { isCompilerError = true; //打印编译的错误信息 Pattern p = Pattern.compile("Main.java\\D*(\\d+):", Pattern.DOTALL); for (Diagnostic
oDiagnostic : oDiagnosticCollector.getDiagnostics()){ /*信息示例: Compiler Error: Main.java:8: 找不到符号 符号: 类 Scanner 位置: 类 Main */ //将行号减1 Matcher m = p.matcher("Compiler Error: " + oDiagnostic.getMessage(null)); if(m.find()) { ce.append(m.replaceAll("Main.java " + String.valueOf(Integer.valueOf(m.group(1))-1)) + ":").append("\n"); } else { ce.append("Compiler Error: " + oDiagnostic.getMessage(null)).append("\n"); } } } } catch (Exception e) { isRunningError = true; StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw, true)); Pattern p = Pattern.compile("Main.java\\D*(\\d+)", Pattern.DOTALL); Matcher m = p.matcher(sw.toString()); if(m.find()){ error = m.replaceAll("Main.java " + String.valueOf(Integer.valueOf(m.group(1))-1) + ":"); } else { error = sw.toString(); } } finally { //关闭流 try { if(fis != null) fis.close(); if(ps != null) ps.close(); if(br != null) br.close(); } catch (IOException e) { e.printStackTrace(); } //恢复输入输出流 System.setIn(stdIn); System.setOut(stdOut); } } private class StringSourceJavaObject extends SimpleJavaFileObject { private String content = null; public StringSourceJavaObject(String name, String content) { super(URI.create(name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.content = content; } public CharSequence getCharContent(boolean ignoreEncodingErrors) { return content; } }}

 

五.运行结果显示

1.正常运行

运行时间: 16ms

内存使用: 225.5546875kb

运行结果

5 4 3 2 1 

 

2.编译错误

编译错误: Compiler Error: Main.java 8 找不到符号

符号: 类 Scanner

位置: 类 Main:

Compiler Error: Main.java 8 找不到符号

符号: 类 Scanner

位置: 类 Main:

3.运行错误

(1)运行错误: java.lang.reflect.InvocationTargetException

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at com.test.CompileAndRunJavaFile.compileAndRunJavaFile(CompileAndRunJavaFile.java:163)

at com.test.CompileAndRunJavaFile.main(CompileAndRunJavaFile.java:44)

Caused by: java.lang.StackOverflowError

at Main.fun(Main.java 4:)

at Main.fun(Main.java 4:)

 

(2)运行错误: java.lang.reflect.InvocationTargetException

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at com.test.CompileAndRunJavaFile.compileAndRunJavaFile(CompileAndRunJavaFile.java:163)

at com.test.CompileAndRunJavaFile.main(CompileAndRunJavaFile.java:44)

Caused by: java.lang.ArrayIndexOutOfBoundsException: 6

at Main.main(Main.java 18:)

... 6 more

 

v六.测试程序

public class Main {    public static void fun(){        fun();    }    public static void main(String[] args) {        Scanner scan = new Scanner(System.in);        int n = scan.nextInt();        int[] array = new int[n];        for(int i=0; i

 

 

转载地址:http://xpvia.baihongyu.com/

你可能感兴趣的文章
linux 编写防火墙脚本
查看>>
方差分析库 ANOVA C++ (libANOVA)
查看>>
线程,进程和程序的简单比较
查看>>
Resetting warning light on AIX
查看>>
Java 实现文件随机读写-RandomAccessFile
查看>>
hdu2027 统计元音
查看>>
星巴克——最单纯的SNS应用
查看>>
spring配置线程池
查看>>
2016年2月5、6日:调研应用监控系统
查看>>
在eclipse中搭建咖啡兔的Activiti演示工程中的各种坑及其解决方法(kft-activiti-demo-no-maven)...
查看>>
我的友情链接
查看>>
简单易用的headless浏览器
查看>>
weka中使用liblinear
查看>>
获取url后面的参数
查看>>
网络超时检测的三种方法
查看>>
Add Two Numbers
查看>>
为什么你需要U-Mail邮件网关上万能安全锁
查看>>
JSON 官网中文
查看>>
解决ubuntu-supervisor-unix:var-run-supervisor.sock-no-such-file.的方法
查看>>
jQuery导航下拉滑动油漆刷墙效果
查看>>