简单java在线测评程序
大家过年好!今年的第一篇博客啊!家里没有网,到处蹭无线!日子过得真纠结!因为毕设的需求,简单写了一个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.程序所需内存: 通过Runtime的freeMemory()方法。
9.异常信息的获取:StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw, true)); sw.toString();
v三.问题解决
1. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 出现NullPointerException。
查看部分源码如下:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 ClassLoader (cl); return Class.forName(toolClassName, false, cl); }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
打印 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四.代码
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 JavaFileObject oDiagnosticCollector = new DiagnosticCollector JavaFileObject (); 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 ? 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 //将行号减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; }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
(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六.测试程序
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 ++i) array[i] = scan.nextInt(); for(int i=0; i ++i) System.out.print(array[i] + " "); System.out.println(); //array[n+1] = 0; //fun(); }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
【源码】基层医院云HIS系统 java版his云系统 本套云HIS系统采用主流成熟技术开发,软件结构简洁、代码规范易阅读,SaaS应用,全浏览器访问前后端分离,多服务协同,服务可拆分,功能易扩展。多集团统一登录患者主索引建立、主数据管理,统一对外接口管理
基于Java的在线购书系统 本次分享的系统框架采用servlet,前端使用bootstrap、css、js等,适合基础中等或以下。主要功能包括:书籍检索、分类查看、加入购物车、下单,以及管理员管理功能等。
基于Java的体育场地预约系统 该系统基于Java,mysql数据库,具有完整的业务逻辑,适用于基础中等及以下,要求界面美观的学生。主要功能:查看每个场馆信息、以及每个场馆的场地,进行预约场地,付款后等待管理员审核,管理员可以对场馆、场地进行管理,也可以审核订单等。
推荐一款阿里开源的 Java 诊断工具,好用到爆! Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题。 Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux、Mac、Windows 操作系统,命令还支持使用 tab 键对各种信息的自动补全,诊断起来非常利索。
平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常觉得帮助很大的工具,大家一起进步。
相关文章
- Java 7: 全面教程-1.3 集成开发环境(IDEs)
- java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseSelectProvider.<init>()
- 使用eclipse创建java程序可执行jar包
- JAVA Eclipse如何开发Android的多页面程序
- Java实现 LeetCode 522 最长特殊序列 II(查找最长的非子序列的长度)
- Java实现 蓝桥杯 历届试题 地宫取宝
- Java实现 蓝桥杯 算法训练 Multithreading
- java 获取数组(二维数组)长度实例程序
- 编写高质量代码:改善Java程序的151个建议 --[0~25]
- 认识程序的执行:从高级语言到二进制,以java为例
- linux系统部署Java程序获取ip时报Caused by: java.net.UnknownHostException: XXXXXXXXXX: XXXXXXXXXX: Name or service not known
- 【JAVA】java中的length和length()
- Java SimpleDateFormat 线程不安全问题及解决方法
- 一段使用Java程序和JCO(Java connector)连接SAP ABAP Netweaver系统的代码
- SAP BSP, Java Web Project,Android和微信小程序的初始页面设置
- paip.java win程序迁移linux的最佳实践
- 华为OD机试 - 静态扫描(Java & JS & Python)
- Java Persistence with Hibernate中文版Hibernate实战第2版勘误
- java程序调用xfire发布的webService服务(二)
- java程序调用xfire发布的webService服务
- 1小时学会通过Java Swing Design设计java图形化
- Java //PP1.4 按照以下要求编写一个程序,显示句子Knowledge is Power: a.一行显示 b.每行一词,分三行显示,每个词都相对居中 c.显示在一个由字符“=“和“|“。。。
- Java //PP1.8 编写一个程序,显示自选小说中的一个自然段的文字。
- 一文详解java线程池 详解Java线程池的七个参数 详解池化技术 java如何选择核心线程数 详解Java线程池的拒绝策略
- 《Java程序性能优化》之设计优化
- java-JProfiler(三)-进行本地JVM的性能监控-监视本地java程序
- JAVA学习第十九课(java程序的异常处理 (二))
- 简单说明什么是递归?什么情况会使用?并使用java实现一个简单的递归程序。
- java.io.File详解
- 【java】Java 继承
- Java语言基础(环境搭建、语法、变量、类型转换、运算符、控制语句、数组)
- JAVA开发讲义(二)-Java程序设计之数据之谜一