我正在为java学习编写web应用程序。使用哪些用户可以在我的服务器上编译他们的代码+运行该代码。 使用JavaCompiler编译很容易:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, prepareFile(nazwa, content));
task.call();
List<String> returnErrors = new ArrayList<String>();
String tmp = new String();
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
tmp = String.valueOf(diagnostic.getLineNumber());
tmp += " msg: " + diagnostic.getMessage(null);
returnErrors.add(tmp.replaceAll("\n", " "));
}
我设法用代码加载类:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
try {
URL[] urls = {new URL("file:///root/"), new URL("file://C:\\serv\\Apache Tomcat 6.0.20\\bin\\")};
ClassLoader cl_old = Thread.currentThread().getContextClassLoader();
ClassLoader cl_new = new URLClassLoader(urls, cl_old);
Class compiledClass = cl_new.loadClass(CLASS_NAME);
Method myMethod = compiledClass.getMethod(METHOD_NAME);
Object tmp = myMethod.invoke(null);
} catch (Exception ex) {
Logger.getLogger(ITaskCompile.class.getName()).log(Level.SEVERE, null, ex);
}
我如何保护我的应用程序免受无限循环和邪恶的学生的影响;)
THX。 Tzim
答案 0 :(得分:2)
我如何保护我的应用程序免受无限循环和邪恶的学生的影响;)
你不能在一个JVM中。邪恶的学生特别难以应对,因为聪明的学生会想出一些方法来颠覆你的控制机制。
1)有没有办法运行生命周期的代码?
不,除非您在单独的JVM中运行它。
2)是否存在内存泄漏的风险,我该怎么做才能解决这个问题。
是的,没有什么可以做的(除了单独的JVM)。事实上,即使您可以杀死陷入循环等的学生程序,这也是一个问题。应用程序可能有很多方法导致Java类库泄漏内存/资源......即使在应用程序之后本身已经完成并且已经过GC。
3)这是一个很好的解决方案,还是你可以提出更好的建议?
在使用Process
和朋友从服务器启动的单独JVM中运行每个学生应用程序。您将需要编写主机操作系统特定的东西来设置执行时间限制,并杀死死锁的学生应用程序。此外,您还有各种各样的问题,确保您不会通过触发太多JVM来意外地破坏主机性能。
更好的答案是为每个学生提供台式计算机或虚拟机,让他们自己做。
答案 1 :(得分:1)
有没有办法在终身运行该代码?
创建一个监视子进程的进程,如果进程太长则终止进程。
是否存在内存泄漏的风险,我该怎么做才能解决这个问题。
您应该能够在某种程度上通过控制分配的内存量来实现这一点(例如Sun的JVM的-Xmx
参数)。
这是一个很好的解决方案,还是可以提出更好的建议?
我不确定是否已提出解决方案,但这是一个想法。安装SecurityManager可以极大地限制执行的代码可以执行的操作,例如访问文件系统,生成进程等。将其与监视超时的进程相结合,限制分配的内存,在单独的用户下运行应用程序帐户等,我认为你可以有一些可行的东西。
您正在寻找的是可能的,但如果仅限于Java,则可能不完全如此。
答案 2 :(得分:1)
添加Kaleb的答案,请确保以严格的堆限制运行目标JVM(例如-Xmx16M)。当然,您需要限制运行的JVM数量。
答案 3 :(得分:1)
我目前的解决方案如下:
运行代码:
@RequestMapping("/student/runITask.action")
public String student_runITask(@ModelAttribute(value = "program") ProgramToCompile program, ModelMap map) {
//1. code compile
ITaskCompile itcompile = new ITaskCompile();
List<String> errorList = itcompile.compileTask(program.getClassname(), program.getProgram());
Date tmp = new Date();
this.setPathName(program.getClassname() + tmp.hashCode());
//2. if compiled...
if (errorList.size() < 1) {
try {
String[] cmd = {"/bin/sh", "-c", "java -Xmx16M -Xms2M -cp /root/ " + program.getClassname() + "> " + getPathName() + ".data"};
Runtime rt = Runtime.getRuntime();
final Process proc = rt.exec(cmd);
Thread.sleep(1000);
proc.destroy();
if (proc.exitValue() > 0) {
try {
killJavaProcesses();
map.addAttribute("comment", "Endless LOOP!");
} catch (Exception ex1) {
Logger.getLogger(CompileITaskControler.class.getName()).log(Level.SEVERE, null, ex1);
}
} else {
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(new FileReader("/root/" + getPathName() + ".data"));
char[] buf = new char[1024];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
fileData.append(buf, 0, numRead);
}
reader.close();
map.addAttribute("comment","Output: <br/><br/><br/><pre>"+fileData.toString()+"</pre>");
}
} catch (Exception ex) {
try {
killJavaProcesses();
map.addAttribute("comment", "Endless LOOP!");
} catch (Exception ex1) {
Logger.getLogger(CompileITaskControler.class.getName()).log(Level.SEVERE, null, ex1);
}
}
} else {
map.addAttribute("errorList", errorList);
map.addAttribute("comment", "PROGRAM NIE ZOSTAŁ URUCHOMIONY");
} //3. return
return DISPLAY_COMP_MSG;
}
其中killJavaProcesses()看起来像那个
public void killJavaProcesses() throws IOException, InterruptedException {
String[] getProcessList = {"/bin/sh", "-c", "ps | grep java"};
String[] killProcessByIdList = {"/bin/sh", "-c", "kill -9 "};
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(getProcessList);
InputStream inputstream = proc.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line2;
String kill = new String();
while ((line2 = bufferedreader.readLine()) != null) {
kill += line2 + "\n";
}
proc.destroy();
String arraykill[] = kill.split("\n");
String element2kill = "";
String[] tmp;
if (arraykill.length >= 1) {
element2kill = arraykill[arraykill.length - 1].trim().split(" ")[0];
}
killProcessByIdList[2] += element2kill;
Process proc2 = rt.exec(killProcessByIdList);
proc2.waitFor();
}
我不能杀死不同的进程。使用proc.destroy()在Ubuntu / Win XP机器上无法正常工作。 现在我将尝试配置并使用SecurityManager。