zl程序教程

您现在的位置是:首页 >  后端

当前栏目

简单java在线测评程序

JAVA程序 简单 在线 测评
2023-09-14 08:57:56 时间

大家过年好!今年的第一篇博客啊!家里没有网,到处蹭无线!日子过得真纠结!因为毕设的需求,简单写了一个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。

 查看部分源码如下:

 

复制代码
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);

}
复制代码

 

打印 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 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;

}
复制代码

(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 ++i)

 array[i] = scan.nextInt();

 for(int i=0; i ++i)

 System.out.print(array[i] + " ");

 System.out.println();

 //array[n+1] = 0;

 //fun();

}
复制代码
【源码】基层医院云HIS系统 java版his云系统 本套云HIS系统采用主流成熟技术开发,软件结构简洁、代码规范易阅读,SaaS应用,全浏览器访问前后端分离,多服务协同,服务可拆分,功能易扩展。多集团统一登录患者主索引建立、主数据管理,统一对外接口管理
基于Java的在线购书系统 本次分享的系统框架采用servlet,前端使用bootstrap、css、js等,适合基础中等或以下。主要功能包括:书籍检索、分类查看、加入购物车、下单,以及管理员管理功能等。
基于Java的体育场地预约系统 该系统基于Java,mysql数据库,具有完整的业务逻辑,适用于基础中等及以下,要求界面美观的学生。主要功能:查看每个场馆信息、以及每个场馆的场地,进行预约场地,付款后等待管理员审核,管理员可以对场馆、场地进行管理,也可以审核订单等。
推荐一款阿里开源的 Java 诊断工具,好用到爆! Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题。 Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux、Mac、Windows 操作系统,命令还支持使用 tab 键对各种信息的自动补全,诊断起来非常利索。
平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常觉得帮助很大的工具,大家一起进步。