【问题标题】:Run piece of code contained in a String运行包含在字符串中的一段代码
【发布时间】:2020-04-09 09:53:42
【问题描述】:

我在 String 中有一段 Java 代码。

String javaCode = "if(polishScreenHeight >= 200 && " +
    "polishScreenHeight <= 235 && polishScreenWidth >= 220) { }";

是否可以将此 Java 字符串转换为 Java 语句并运行它?可能使用 Java 反射?

【问题讨论】:

  • 你能举个例子,当你需要执行这段代码时,在什么上下文中?
  • Convert String to code in Java 的可能重复项
  • 好的,这是我从java类的main方法执行的完整方法-
  • private void getResolution(int PolishScreenHeight, int PolishScreenWidth){ if(polishScreenHeight >= 200 && PolishScreenHeight = 220) { System.out.println("
  • 希望对您有所帮助,我还能使用 Beanshell 吗?

标签: java reflection


【解决方案1】:

正如已经建议的那样,您可以使用Compiler API 即时编译、保存和运行代码。

另一个简洁的选择是使用beanshell。 Beanshell 不再积极开发,但我可以保证它的可靠性,我已在多个生产项目中成功使用它。

【讨论】:

【解决方案2】:

使用 BeanShell。 how to use it from Java上有一个页面。

【讨论】:

  • +1 这是一个很好的解决方案。一个笔记认为:初始化 BSH 解释器需要一些时间。
  • 初始化一次就可以共享了,虽然不知道是不是线程安全的。
【解决方案3】:

Beanshell(正如 Boris 建议的那样)是一种“执行”java 源代码的方法。但看起来,您想要“执行”可以与已编译类交互的片段。您的示例包含变量名称。

反射肯定无济于事,因为反射的目标是类(“类文件”)。

可以尝试定义一个完整的类(“有效的 java 源文件”),编译并加载它(url 类加载器)。然后您应该能够使用该“实时生成的类”中的方法。但是一旦一个类被加载,你就无法摆脱它(卸载),所以这只工作一次(AFAIK)。

【讨论】:

  • Beanshell 可以与已编译的类进行交互,只要将它们绑定到 beanshell 环境即可。
【解决方案4】:

据我所知,没有简单的方法可以做到这一点。

但是,从 Java 6 开始,您可以使用 javax.tools.Compiler 编译完整类的源代码。然后可以加载和执行编译的类。但我认为这不会达到你想要的效果。

【讨论】:

    【解决方案5】:

    另一种方法是将您的代码作为 Groovy 代码执行,请参阅 this 以获取示例。

    【讨论】:

      【解决方案6】:

      您可以使用此代码来运行使用此代码的方法 new Statement(Object target, String methodName, Object[] arguments).execute();

      import java.beans.Statement;
      
      public class HelloWorld {
      
        public void method_name(String name) {
            System.out.println(name);
        }
      
        public static void main(String[] args) throws Exception {
            HelloWorld h = new HelloWorld();
            new Statement(h, "method_name", new Object[]{"Hello world"}).execute();
        }
       }
      

      【讨论】:

      • 如果您提供了一些代码,请同时提供一些代码说明,以便其他人更好地理解。
      • Statement 类表示对单个方法的调用。 OP 想要运行的String 中的代码不仅仅是一个方法。因此,这不可能帮助他们。
      【解决方案7】:

      试试JavaCompiler API。

      其他人的回答比我好,但是: Convert String to Code

      在实际使用这样的东西之前要小心...

      【讨论】:

        【解决方案8】:

        它不是 Java,但正如 pgras 已经建议您可以像这样使用 GrooyScript:

            Binding binding = new Binding();
            GroovyShell shell = new GroovyShell(binding);
        
            String[] strings = new String[]{"World", "Groovy"};
            shell.setVariable("args", strings);
        
            String script = "return \"Hello \" + args[1]";
            String value = (String) shell.evaluate(script);
            System.out.println(value); // Hello Groovy
        

        【讨论】:

          【解决方案9】:
          1. 请重新评估您的设计,这应该是您最后的选择。
          2. 您应该验证将要执行的字符串的完整性以避免未来的注入攻击。

          现在,如果您可以将字符串作为 JavaScript,那么下面的代码应该会有所帮助,

          public class EvalScript {
          
                  public static void main(String[] args) throws Exception {
                      // create a script engine manager
                      ScriptEngineManager factory = new ScriptEngineManager();
                      // create a JavaScript engine
                      ScriptEngine engine = factory.getEngineByName("JavaScript");
          
                      // below JS function is executed.
                      /*
                       * student object value will be provided by the program as the JSON String.
                      function checkStudentElgibility(student){
                        if(student.age >= 10 && student.currentGrade >= 5){
                          return true;
                        }
                      }
                      // student object value will be provided by the program as the JSON String
          
                      checkStudentElgibility(student);
                      */
          
                      String studentJsonString = "{\n" + 
                              "  \"age\" : 10,\n" + 
                              "  \"currentGrade\" : 5\n" + 
                              "}";
                      String javaScriptFunctionString = "function checkStudentElgibility(student){\n" + 
                              "  if(student.age >= 10 && student.currentGrade >= 5){\n" + 
                              "    return true;\n" + 
                              "  }\n" + 
                              "}\n" + 
                              "checkStudentElgibility(student);";
          
                      StringBuilder javaScriptString = new StringBuilder();
                      javaScriptString.append("student=");
                          javaScriptString.append(studentJsonString);
                      javaScriptString.append("\n");
                      javaScriptString.append(javaScriptFunctionString);
          
                     Object object = engine.eval(javaScriptString.toString());
          
                     System.out.println(object);
          
                     // You can also pass the object as follows,
          
                     // evaluate JavaScript code that defines an object with one method
                      engine.eval("var obj = new Object()");
                      engine.eval("obj.hello = function(name) { print('Hello, ' + name) 
                        }");
          
                     // expose object defined in the script to the Java application
                       Object obj = engine.get("obj");
          
                   // create an Invocable object by casting the script engine object
                      Invocable inv = (Invocable) engine;
          
                // invoke the method named "hello" on the object defined in the
               // in js Object with "Script Method" as parameter 
          
                         inv.invokeMethod(obj, "hello", "Script Method!");
          
          
          
          
          
              // You can also use Java Objects as Java script object and you can also pass Objects as reference inside Java script function
          
          
                                      String jsString = "    var obj = new Object()\n" + 
                                  "    var ArrayList = Java.type(\"java.util.ArrayList\");\n" +
                                  "    var customSizeArrayList = new ArrayList(16);\n" + 
                                  "    obj.hello = function(name) { \n" + 
                                  "       customSizeArrayList(name);  \n" + 
                                  "       print('Hello, ' + name) \n" + 
                                  "    }";
                      }
          
          
          }
          

          参考: https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147187

          【讨论】:

          • 这实际上对他没有帮助,因为他在字符串中包含了 Java 定义的代码,而 javascript eval 无法访问这些代码。我知道我自己试过了。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-16
          • 2013-04-20
          • 1970-01-01
          • 2012-11-21
          • 1970-01-01
          相关资源
          最近更新 更多