问题 从Java中的字符串运行代码[重复]


这个问题在这里已有答案:


3213
2017-07-12 06:03


起源

真正的问题是: 为什么 你想这样做吗? - Dariusz
让我们假设一瞬间这是可能的......但是想想Java如何编译你的运行时代码? - AurA
你需要的可能是一个 Java解释器。 - LaurentG
+1一个交互式Java控制台?我有点喜欢这个主意。 - Alex Gittemeier
@couling它不应该 为什么?,它很棒 为什么哦,为什么有人会这样做呢? 拜托,这似乎是一种暴行。 - Dariusz


答案:


如果代码是在JavaScript中,那么您可以使用JavaScript引擎运行它:

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

自1.6以来,JavaScript引擎是Java SE的一部分。请参阅本指南 http://download.java.net/jdk8/docs/technotes/guides/scripting/programmer_guide/index.html  详情


3
2017-07-12 06:16



还有其他脚本语言,如BeanShell,java子集。 - Joop Eggen
如果脚本是选项,那么为什么要远离java?有Scala,Groovy也是JRuby,每个人似乎都喜欢JRuby的表现。 - Bnrdo
如果你在java8上,我会使用nudge4j lorenzoongithub.github.io/nudge4j - Zo72


请不要实际使用这个

我假设您想要将字符串评估为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 你实际上可以避免使用文件,如图所示 这里,但语法似乎有点麻烦,所以我只选择了当前工作目录中的文件。

编辑将字符串转换为代码 提供类似的方法,但它没有完全充实


4
2017-07-12 07:13





您可以使用位于Package中的Java脚本API javax.script。在那里你可以包括几种脚本语言 BSH 例如。

你可以找到一个 程序员指南 在Oracle的网页上。

Rhino,它是某种JavaScript,已经包含在Oracle JVM中。


3
2017-07-12 06:15





为此你可能想要研究一下 Java编译器API。我没有研究过它是如何工作的,但它允许你加载一个java文件,在已经运行的系统中编译和加载该类。也许它可以重新用于接受来自控制台的输入。


0
2017-07-12 06:11



这个方法意味着创建一个文件,编写类和代码,编译它,打开它,运行代码......似乎不是运行一行代码的最佳方法...... - user2555349


对于可以使用的通用编译器 JANINO 这将允许您编译和运行Java代码。该 表达评估员 可以帮助您的例子。

如果你只是想在调试时评估表达式,那么Eclispe就有了 显示视图 它允许您执行表达式。看到 这个问题


0
2017-07-12 06:36