Я пишу веб-приложение для изучения Java. Используя который пользователи могут скомпилировать свой код моего сервера + выполненный тот код. Компиляция легка с 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);
}
Как я могу защитить свое приложение от бесконечного цикла и злых студентов ;)
спасибо. Tzim
Как я могу защитить свое приложение от бесконечного цикла и злых учеников;)
Вы не можете в одном JVM. Злые студенты особенно трудно разобраться с тем, что умные будут понять какой-то способ подорвать ваши механизмы управления.
1) Есть ли способ запустить этот код с течением времени?
Нет, если вы не запустите его в отдельном JVM.
2) Есть ли риск с утечками памяти, и что я могу сделать, чтобы исправить это.
Да есть, и нет ничего, что вы можете сделать с ним (кроме отдельных JVMS). На самом деле, это было бы проблемой, даже если вы могли бы убить студенческих программ, которые застряли в петлях и т. Д. Существует множество способов, которыми приложение может вызвать библиотеки классов Java для утечки памяти / ресурсов ... даже после приложения Сама закончилась и была ГХ.
3) Это хорошее решение, или вы можете предложить что-то лучшее?
Запустите каждое студенческое приложение в отдельном JVM, который вы запускаете с вашего сервера, используя процесс
и друзей. Вам нужно будет написать ведущую систему операционной системы, чтобы установить ограничения времени выполнения и убивать студенческих приложений, которые тупики. Кроме того, у вас есть все виды вопросов, убедившись, что вы не случайно разбиваете производительность хост-машины, стреляя слишком много JVMS.
Лучший ответ - предоставить каждому студенту настольный компьютер или виртуальную машину и позволить им сделать свою вещь.
Есть ли способ запустить этот код с течением времени?
Создайте процесс, который следит за ребенком процессы и завершает его, если он занимает слишком долго.
Есть ли риск с утечками памяти, и что я могу сделать, чтобы это исправить.
Вы должны быть в состоянии сделать это в некоторой степени, контролируя, сколько памяти выделено (например, -xmx
параметр на Sun's JVM).
Это хорошее решение, или вы можете предложить что-то лучшее?
Я не уверен, что решение было предложено, но вот мысль. Установите SecurityManager , который значительно ограничивает то, что может сделать выполненный код, например, доступ к файловой системе, процессам появления и т. Д. Сочетают в себе, что с процессом, который мониторы для мониторов для тайм-аута, ограничивает выделенную память, запускает приложение под Отдельная учетная запись пользователя и т. Д., И я думаю, что вы можете иметь что-то относимое.
То, что вы ищете, возможно, но может быть полностью полностью, если вы ограничены только Java.
Наряду с ответом Тора Валамо можно заметить образец (3 * $ i) - 1
(3*1)-1 = 2
(3*2)-1 = 5
(3*3)-1 = 8
...
-121--4244684- Я вижу иф-выражения в математической нотации довольно часто. Обычной вещью для цикла является рекуррентное отношение или эквивалентная функция, определенная рекурсивно.
Вот как функция Аккерманна определена в Википедии, например:
Эта картина хорошая, потому что она чувствует себя математически во аромате, и тем не менее вы можете четко ввести ее почти точно, как написано и иметь реализацию. Добиться этого не всегда возможно.
Другие математические обозначения, которые соответствуют циклам, включают в себя ∑-notation для суммирования и set-builder .
Надеюсь, это ответит на ваш вопрос! Но если ваша цель - описать, как что-то делается и кто-то понимает, я думаю, это, вероятно, ошибка предположить, что математики предпочли бы видеть уравнения. Я не думаю, что они взаимозаменяемые инструменты (несмотря на эквивалентность Тьюринга). Если ваш алгоритм включает изменяемые структуры данных, процедурный код, вероятно, будет лучше, чем уравнения для его объяснения.
-121--4585715-Добавляя к ответу Калеба, обязательно запустите целевой JVM со строгим пределом кучи (например, - Xmx16M). И, конечно, вы хотите ограничить количество запущенных JVM.
Мое текущее решение выглядит так:
запустить код:
@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 .