简单java在线测评程序

简单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.程序所需内存通过RuntimefreeMemory()方法。

  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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单文本编辑器

一、前言 聚天地之灵气&#xff0c;集日月之精华&#xff01;一个简单的java文本编辑器由此而生。毕设所需&#xff0c;很是无奈&#xff01; 二、界面预览 三、实现思路 1.字体选择器的实现 (1).字体类 class MyFont{private Font font;private Color color;public Font getFo…

u-boot新增命令后出现data abort

&#xff08;一&#xff09;问题描述 u-boot下新增了一条update的命令&#xff0c;直接输入update没有报错&#xff0c;但是输入up按TAB键补全时发现出现data abort&#xff0c;而且输入不支持的命令也会有data abort &#xff08;二&#xff09;解决方法 最开始我包含的头…

core文件如何分析

目录(一&#xff09;什么是coredump(二)coredump产生的条件&#xff08;1&#xff09;coredump产生主要原因&#xff1a;&#xff08;2&#xff09;如何生成coredump(三&#xff09;gdb使用(四&#xff09;实例调试coredump文件(五&#xff09;总结(一&#xff09;什么是coredu…

SpringMVC+FreeMarker

前言&#xff1a; 最近在学习SpringMVC&#xff0c;模板引擎用的是FreeMarker&#xff0c;之前没有接触过。利用SpringMVC开发其实还有许多的步骤&#xff0c;比如控制层&#xff0c;服务层&#xff0c;持久化层&#xff0c;实体等等&#xff0c;先弄了一个小demo来总结一下Spr…

SpringMVC那点事

一、SpringMVC返回json数据的三种方式 1、第一种方式是spring2时代的产物&#xff0c;也就是每个json视图controller配置一个Jsoniew。 如&#xff1a;<bean id"defaultJsonView" class"org.springframework.web.servlet.view.json.MappingJacksonJsonView&q…

(一)最邻近插值python实现

这里写目录标题&#xff08;一&#xff09;原始图像&#xff08;二&#xff09;最邻近插值实现&#xff08;三&#xff09;python实现1. 安装库2. python程序编写3. 效果4. 工程文件&#xff08;一&#xff09;原始图像 &#xff08;二&#xff09;最邻近插值实现 一般情况下我…

(二)双线性插值python实现

这里写目录标题&#xff08;一&#xff09;原始图像&#xff08;二&#xff09;双线性插值原理&#xff08;三&#xff09;python实现1. 安装库2. python程序编写3. 效果4. 工程文件&#xff08;一&#xff09;原始图像 &#xff08;二&#xff09;双线性插值原理 一般情况下我…

(三)图像转灰度图Python实现

这里写目录标题&#xff08;一&#xff09;原始图像&#xff08;二&#xff09;转换原理&#xff08;三&#xff09;python实现1. 安装库2. python程序编写3. 效果4. 工程文件&#xff08;一&#xff09;原始图像 &#xff08;二&#xff09;转换原理 &#xff08;三&#xff…

java泛型上下限

前言&#xff1a; java的泛型上下限不是很好理解&#xff0c;尤其像我这种菜鸡。反反复复看了好几遍了...&#xff0c;真是... 一、简单的继承体系 class Person{}class Student extends Person{}class Worker extends Person{} 二、泛型上限&#xff08;extends 关键字&#x…

基于matlab的步进电机仿真(一)

这里写目录标题环境准备基础准备模型参数输入和输出仿真原理图仿真资源环境准备 MatLab2021b 基础准备 打开Matlab&#xff0c;在帮助文档里面搜索step motor,我们这里选择如下模型 该模型实现了一个通用的步进电机模型&#xff1a; 可变磁阻步进电机永磁或混合步进电机 …

java自定义类加载器

前言 java反射&#xff0c;最常用的Class.forName()方法。做毕设的时候&#xff0c;接收到代码字符串&#xff0c;通过 JavaCompiler将代码字符串生成A.class文件&#xff08;存放在classpath下&#xff0c;也就是eclipse项目中的bin目录里&#xff09;&#xff0c;然后通过jav…

repo介绍(一)

repo简介 Repo 是我们以 Git 为基础构建的代码库管理工具,可以组织多个仓库的上传和下载。它是由一系列的Python脚本组成&#xff0c;封装了一系列的Git命令&#xff0c;用来统一管理多个Git仓库 一个大型的项目可能由很多小的仓库组合而成的&#xff0c;为了方便统一管理各个…

hash长度扩展攻击

作为一个信息安全的人&#xff0c;打各个学校的CTF比赛是比较重要的&#xff01; 最近一个朋友发了道题目过来&#xff0c;发现有道题目比较有意思&#xff0c;这里跟大家分享下 这串代码的大致意思是&#xff1a; 这段代码首先引入了一个名为"flag.php"的文件&am…

repo介绍(二)

这篇文章来实例操作 安装repo&#xff0c;参考repo介绍这一节创建repo存放default.xml 的git仓库 初始化repo&#xff0c;repo init -u https://gitee.com/angerial/repo-test.git 这个时候会在当前目录生成如下文件 参考repo组成&#xff0c;修改.repo/manifest.xml,这里我的…

springmvc环境搭建以及常见问题解决

1.新建maven工程 a) 打开eclipse&#xff0c;file->new->project->Maven->Maven Project b) 下一步 c) 选择创建的工程为webapp&#xff0c;下一步 d) 填写项目的group id和artifact id。一般情况下&#xff0c;group id写域名的倒序&#xff0c;artifact id…

eclipse build workspace太慢或者 js出错问题解决

1.js文件错误解决办法 右键项目->properties->Builders(注&#xff1a;JavaScript Validator也会引起 build workspace太慢) 2.Eclipse 一直不停 building workspace完美解决总结&#xff08;来自: http://blog.163.com/shadow_wolf/blog/static/18346909720145279519222…

springmvc+jpa实现分页的两种方式

1.工具类 public final class QueryTool {public static PageRequest buildPageRequest(int pageNumber, int pageSize, String sortType){Sort sort null;if("auto".equals(sortType)) {sort new Sort(Direction.DESC, "ctime");} else {sort new Sort…

不使用session,借助redis实现验证码

1.首先看一下基本的流程 2.看一下代码 注&#xff1a;其中用到的一些工具类&#xff0c;可以到我的github上去下载 https://github.com/hjzgg/usually_util/tree/master/utils windows 下的 redis下载 https://github.com/hjzgg/redis 获取验证码的tooken RequestMapping(value…

PS批处理的使用

一、 前言 做开发的时候&#xff0c;最多的时候就是图片的使用了。有时候图片的处理都按照同样的步骤&#xff0c;比如说统一将图片的大小调整为固定大小&#xff0c;或者统一在所有的图片的的某个位置上加入文字或者小图片等等&#xff0c;这时候PS的批处理可以帮你完成这些重…

exe4j的使用

下载&#xff1a;http://download.cnet.com/exe4j/3000-2070_4-144405.html 参考&#xff1a;http://blog.chinaunix.net/uid-25749806-id-4380850.html 注&#xff1a;打包成jar包的一般就是src目录&#xff0c;其他目录放到目标文件夹中&#xff0c;目录结构如下 如何解决exe…