компиляция и рабочий пользователь кодирует с JavaCompiler и ClassLoder

Я пишу веб-приложение для изучения 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);
    }

Как я могу защитить свое приложение от бесконечного цикла и злых студентов ;)

  1. там какой-либо путь состоит в том, чтобы выполнить тот код со временем жизни?
  2. есть ли какой-либо риск с утечками памяти, и что я могу сделать для фиксации этого.
  3. это хорошее решение, или можно ли предложить что-то лучше?

спасибо. Tzim

6
задан skaffman 29 January 2010 в 14:48
поделиться

4 ответа

Как я могу защитить свое приложение от бесконечного цикла и злых учеников;)

Вы не можете в одном JVM. Злые студенты особенно трудно разобраться с тем, что умные будут понять какой-то способ подорвать ваши механизмы управления.

1) Есть ли способ запустить этот код с течением времени?

Нет, если вы не запустите его в отдельном JVM.

2) Есть ли риск с утечками памяти, и что я могу сделать, чтобы исправить это.

Да есть, и нет ничего, что вы можете сделать с ним (кроме отдельных JVMS). На самом деле, это было бы проблемой, даже если вы могли бы убить студенческих программ, которые застряли в петлях и т. Д. Существует множество способов, которыми приложение может вызвать библиотеки классов Java для утечки памяти / ресурсов ... даже после приложения Сама закончилась и была ГХ.

3) Это хорошее решение, или вы можете предложить что-то лучшее?

Запустите каждое студенческое приложение в отдельном JVM, который вы запускаете с вашего сервера, используя процесс и друзей. Вам нужно будет написать ведущую систему операционной системы, чтобы установить ограничения времени выполнения и убивать студенческих приложений, которые тупики. Кроме того, у вас есть все виды вопросов, убедившись, что вы не случайно разбиваете производительность хост-машины, стреляя слишком много JVMS.

Лучший ответ - предоставить каждому студенту настольный компьютер или виртуальную машину и позволить им сделать свою вещь.

2
ответ дан 17 December 2019 в 04:46
поделиться

Есть ли способ запустить этот код с течением времени?

Создайте процесс, который следит за ребенком процессы и завершает его, если он занимает слишком долго.

Есть ли риск с утечками памяти, и что я могу сделать, чтобы это исправить.

Вы должны быть в состоянии сделать это в некоторой степени, контролируя, сколько памяти выделено (например, -xmx параметр на Sun's JVM).

Это хорошее решение, или вы можете предложить что-то лучшее?

Я не уверен, что решение было предложено, но вот мысль. Установите SecurityManager , который значительно ограничивает то, что может сделать выполненный код, например, доступ к файловой системе, процессам появления и т. Д. Сочетают в себе, что с процессом, который мониторы для мониторов для тайм-аута, ограничивает выделенную память, запускает приложение под Отдельная учетная запись пользователя и т. Д., И я думаю, что вы можете иметь что-то относимое.

То, что вы ищете, возможно, но может быть полностью полностью, если вы ограничены только Java.

1
ответ дан 17 December 2019 в 04:46
поделиться

Наряду с ответом Тора Валамо можно заметить образец (3 * $ i) - 1

(3*1)-1 = 2
(3*2)-1 = 5
(3*3)-1 = 8
   ...
-121--4244684-

Я вижу иф-выражения в математической нотации довольно часто. Обычной вещью для цикла является рекуррентное отношение или эквивалентная функция, определенная рекурсивно.

Вот как функция Аккерманна определена в Википедии, например:

A(m, n) = n+1 if m=0; A(m-1, 1) if m>0 and n=0; and A(m-1, A(m, n-1)) if m>0 and n>0.

Эта картина хорошая, потому что она чувствует себя математически во аромате, и тем не менее вы можете четко ввести ее почти точно, как написано и иметь реализацию. Добиться этого не всегда возможно.

Другие математические обозначения, которые соответствуют циклам, включают в себя ∑-notation для суммирования и set-builder .

Надеюсь, это ответит на ваш вопрос! Но если ваша цель - описать, как что-то делается и кто-то понимает, я думаю, это, вероятно, ошибка предположить, что математики предпочли бы видеть уравнения. Я не думаю, что они взаимозаменяемые инструменты (несмотря на эквивалентность Тьюринга). Если ваш алгоритм включает изменяемые структуры данных, процедурный код, вероятно, будет лучше, чем уравнения для его объяснения.

-121--4585715-

Добавляя к ответу Калеба, обязательно запустите целевой JVM со строгим пределом кучи (например, - Xmx16M). И, конечно, вы хотите ограничить количество запущенных JVM.

1
ответ дан 17 December 2019 в 04:46
поделиться

Мое текущее решение выглядит так:

запустить код:

@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 .

1
ответ дан 17 December 2019 в 04:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: