Выполнить код из строки в Java

По причинам отладки, я хочу, чтобы иметь возможность запускать код, который вводится через консоль. Например:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(true){
    String str = br.readLine(); //This can return 'a = 5;','b = "Text";' or 'pckg.example.MyClass.run(5);'
    if(str == null)
        return;
    runCode(str); //How would I do this?
}

Ответ 1

Если код находится в JavaScript, вы можете запустить его с помощью JavaScript-движка:

Object res = new ScriptEngineManager().getEngineByName("js").eval(str);

JavaScript-движок является частью Java SE с версии 1.6. Подробнее см. Это руководство http://download.java.net/jdk8/docs/technotes/guides/scripting/programmer_guide/index.html

Ответ 2

ПОЖАЛУЙСТА, НЕ ИСПОЛЬЗУЙТЕ ЭТОТ

Я был в предположении, что вы хотите оценить строку как Java-код, а не какой-то скриптовый движок, такой как Javascript, поэтому Я создал это по прихоти после прочтения этого, используя упомянутый значок API компилятора. Это, вероятно, очень плохая практика, но она (несколько) работает так, как вы этого хотели. Я сомневаюсь, что это будет очень полезно при отладке, поскольку он запускает код в контексте нового класса. Использование образца включено внизу.

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

public class main {
    public static void runCode(String s) throws Exception{
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);
        File jf = new File("test.java"); //create file in current working directory
        PrintWriter pw = new PrintWriter(jf);
        pw.println("public class test {public static void main(){"+s+"}}");
        pw.close();
        Iterable fO = sjfm.getJavaFileObjects(jf);
        if(!jc.getTask(null,sjfm,null,null,null,fO).call()) { //compile the code
            throw new Exception("compilation failed");
        }
        URL[] urls = new URL[]{new File("").toURI().toURL()}; //use current working directory
        URLClassLoader ucl = new URLClassLoader(urls);
        Object o= ucl.loadClass("test").newInstance();
        o.getClass().getMethod("main").invoke(o);

    }
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while(true){
            try {
            String str = br.readLine(); //This can return 'a = 5;','b = "Text";' or 'pckg.example.MyClass.run(5);'
            if(str == null)
                return;

            runCode(str); //How would I do this?
            } catch(Exception e) {
                e.printStackTrace();
            }
        }

    }
}
//command line
>  System.out.println("hello");
hello
>  System.out.println(3+2+3+4+5+2);
19
>  for(int i = 0; i < 10; i++) {System.out.println(i);}
0
1
2
3
4
5
6
7
8
9

С SimpleJavaFileObject вы действительно можете избежать использования файла, как показано здесь, но синтаксис кажется немного громоздким, поэтому я просто выбрал файл в текущем рабочем каталоге.

EDIT: Преобразование String в код предлагает аналогичный подход, но он не полностью конкретизирован

Ответ 3

Вы можете использовать API сценариев Java, который находится в пакете javax.script. Там вы можете включить несколько языков сценариев, например bsh.

Вы можете найти руководство программиста на веб-странице Oracle.

Rhino, который является своего рода JavaScript, уже включен в JVM Oracle.

Ответ 4

Для этого вы можете посмотреть в Java Compiler API. Я мало разбираюсь в том, как это работает, но позволяет загружать java файл, компилировать и загружать класс в уже запущенную систему. Возможно, он может быть переназначен в прием ввода с консоли.

Ответ 5

Для общего компилятора вы можете использовать Janino, который позволит вам скомпилировать и запустить Java-код. оценщик выражений может помочь в вашем примере.

Если вы просто хотите оценить выражения во время отладки, тогда Eclispe имеет Display view, который позволяет выполнять выражения. См. этот вопрос.