简单java程序在线测评程序

一.前言

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

二.思路

  首先简单介绍一下思路:

  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.程序所需内存: 通过Runtime的freeMemory()方法。

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

三.问题解决

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 bootclasspathtry {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<ClassLoader>(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.输入流和输出流的重定向。

详细内容请看代码!

四.代码

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;}//程序的运行时间, 单位:msprivate int limitTime = 2000;//程序所占内存, 单位 :KBprivate 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 informationDiagnosticCollector<JavaFileObject> oDiagnosticCollector = new DiagnosticCollector<JavaFileObject>();StandardJavaFileManager fileManager = compiler.getStandardFileManager(oDiagnosticCollector, null, null);// set class output locationfileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(getClassOutput()) }));StringSourceJavaObject sourceObject = new CompileAndRunJavaFile.StringSourceJavaObject(className, code);Iterable<? extends JavaFileObject> 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<? extends JavaFileObject> oDiagnostic : oDiagnosticCollector.getDiagnostics()){/*信息示例:Compiler Error: Main.java:8: 找不到符号符号: 类 Scanner位置: 类 Main*///将行号减1Matcher 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;}}
}

View Code

五.运行结果显示

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

六.测试程序

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<n; ++i)array[i] = scan.nextInt();for(int i=0; i<n; ++i)System.out.print(array[i] + " ");System.out.println();//array[n+1] = 0;//fun();
    }}

View Code

转载于:https://www.cnblogs.com/hujunzheng/p/5203067.html

简单java在线测评程序相关推荐

  1. java 在线测评_简单java在线测评程序

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

  2. 亚信java在线测评题库_校招秋招,网申在线测评如何训练才能通过?

    校招又分为春招秋招,是无数毕业生就业的重要通道,尤其是今年的情况使得在线测评变得更加普及,将来这也是必然的趋势.校招中第一道门槛便是这线上测评.用人单位在收到毕业生的简历后,先发送线上测评,通过线上测 ...

  3. java在线测评系统_JavaWeb项目:在线评测系统

    此项目为本人的Java大作业. 一.项目概况 1.1设计内容 一个在线评测系统,分用户和管理员两种身份.用户能够通过注册登录,参加比赛,最后实时得到比赛结果,并保存历史比赛结果:管理员除此之外还能录入 ...

  4. java程序计时器_求完整简单java计时器小程序代码,急!!

    放肆丶小侽人 回答时间:2019-12-05 向TA提问 import java.awt.Button; import java.awt.Color; import java.awt.FlowLayo ...

  5. 简单java socket_基于Java Socket实现一个简易在线聊天功能(一)

    最近做了一个项目,其中有一个在线网页交流的需求,好久没写代码了,手都生疏了,于是先写demo练练手,分享到脚本之家平台,以此做个记录,方便自己和大家使用. 先给大家说下实现步骤分这样几大步: 1.使用 ...

  6. java udp简单聊天程序_Java基于UDP协议实现简单的聊天室程序

    最近比较闲,一直在抽空回顾一些java方面的技术应用. 今天没什么事做,基于udp协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对java网络编程方面的一个简单回忆. ...

  7. 在线测试c语言程序代码,C语言在线测评系统的使用

    系统学习请关注公众号:C简简 一.在线测评系统 Online Judge系统(简称OJ)是一个在线的判题系统.用户可以在线提交程序源代码,系统对源代码进行编译和执行,并通过预先设计的测试数据来检验程序 ...

  8. java udp 聊天室_Java基于UDP协议实现简单的聊天室程序

    最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. ...

  9. java毕业设计在线测评系统2021Mybatis+系统+数据库+调试部署

    java毕业设计在线测评系统2021Mybatis+系统+数据库+调试部署 java毕业设计在线测评系统2021Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语言: ...

最新文章

  1. Runtime-消息发送和消息转发
  2. 当ABAP遇到OLE
  3. win10任务管理器快捷键_你都知道吗?Win10任务管理器到底藏了多少秘密
  4. 【小技巧积累】设置ListView控件的Item不在Tab键导航序列中
  5. Hibernate懒加载
  6. TI CC2480 -- Z-Accel介绍
  7. 图的表示方法和C++实现
  8. CV算法助理 | 华为外包招聘
  9. linux怎么判断全局符号,Linux下全局符号覆盖有关问题
  10. java 线程安全 计数_java – 实现线程安全共享计数器的功能方法
  11. java 环境变量_Win10系统配置Java环境变量
  12. 190421每日一句
  13. linux命令行添加管理员用户,Linux基础命令---添加用户useradd
  14. Python安装教程(新手)
  15. 南京大学计算机考研复试名单,2017南京大学计算机科学与技术系考研复试名单...
  16. 游戏是怎么赚钱的 - 科普篇
  17. Mac屏幕截图快捷键
  18. 【DSGN 解读】用于三维目标检测的深度立体几何网络
  19. 金彩教育:如何提升店铺的信誉
  20. iOS应用的游戏中心和排行榜

热门文章

  1. dynamo python修改多个参数_40岁小白学了30天python发现,编程真的其乐无穷
  2. tomcat启动成功 未加载项目_喜讯!济宁医学院附属医院SPD项目成功启动
  3. 判断是否包含大写字符_Python最常用的数据类型中字符串基础函数使用知识点讲解...
  4. uniapp 仿钉钉考勤统计页面的日历组件,通过日历展示每日考勤打卡情况,支持在日历上打两种不同类型的点,大致适配各种分辨率
  5. el-table中奇偶行背景色显示不同的颜色
  6. SpringBoot2 整合 XFIRE 服务端和客户端
  7. JavaScript-字符串
  8. html-表单的应用
  9. curl查看swift状态命令_前端应该会的23个linux常用命令
  10. pythonxml库_对python 生成拼接xml报文的示例详解