Java 动态代码执行

Java 动态代码执行,java,Java,类似于动态SQL,其中字符串在运行时作为SQL执行,我们可以让Java代码动态运行吗?就像我返回一个字符串,它是Java代码,然后在运行时执行。这可能吗?是,使用反射: 还有另一篇来自Javassist的教程 为了运行运行时提供的任意字符串,您需要使用字节码操纵库(如())。Javassist允许您基于表示源代码的字符串创建CtClass;然后可以通过特定的类加载器将其转换为编译的类对象,这样该类就可以用于您的应用程序。其他库需要执行类似于这两个步骤的操作,以实现相同的目标 所以这是可能的,但它

类似于动态SQL,其中字符串在运行时作为SQL执行,我们可以让Java代码动态运行吗?就像我返回一个字符串,它是Java代码,然后在运行时执行。这可能吗?

是,使用反射:

还有另一篇来自

Javassist的教程 为了运行运行时提供的任意字符串,您需要使用字节码操纵库(如())。Javassist允许您基于表示源代码的字符串创建
CtClass
;然后可以通过特定的类加载器将其转换为编译的
对象,这样该类就可以用于您的应用程序。其他库需要执行类似于这两个步骤的操作,以实现相同的目标


所以这是可能的,但它非常重,可能使您的应用程序很难推理。如果可能的话,考虑静态地设计一个非常灵活的类,并让它接受控制其行为的参数。它提供了一个类似java语法的解释器。

如果您不想动态调用现有方法,您可能需要将字符串编译成字节码。一种简单的方法是在类路径中包含Eclipse/JDT编译器jar,然后您可以使用它将字符串编译成类,然后可以加载该类

这种类型的动态代码生成和执行用于将JSP文件转换为servlet,并在其他包(如JasperReports)中使用,以将报表规范转换为一个类,然后调用该类


请记住,与SQL一样,如果任何字符串包含用户指定的数据,则必须小心防止代码注入安全问题。

对于真正的Java代码,可以使用接口。然而,使用它非常不方便,因为它只是一个真正Java编译器的接口,该编译器需要编译文件中的整个类定义

执行运行时提供的代码的最简单方法是使用


这两个选项都只在Java 6中出现过,尽管我相信脚本接口以前就存在过,因此如果您下载Rhino并将其添加到类路径中,您可以在早期的JRE中使用Rhino。

是的,这是可能的。看看Java编译器API。请看这里:


您可能还想了解Java 6脚本支持:

以下是hello world的一个版本,它创建字符串数组并打印第一个字符串:


导入javax.script.*;
公共类EvalScript{
公共静态void main(字符串[]args)引发异常{
ScriptEngine=new ScriptEngineManager().getEngineByName(“JavaScript”);
eval(“var a=java.lang.reflect.Array.newInstance(java.lang.String,1);a[0]=“Hello World”;print(a[0]);
}
}

您有具体的例子吗?这不是真正的动态执行;反射仅允许基于运行时标识符访问(现有类的)方法和字段。您不能在运行时通过反射创建新类,也不能执行任意Java代码。+1--对于可能的库的全面列表:提及“注入”问题很有意义,尽管我敢说整个体系结构是按定义注入的-您试图执行此任意代码,因此,我希望不用说,源代码应该得到隐式信任。Java的一个好处是,您也可以以有限的权限运行注入的代码。+1在此基础上,我在一些应用程序中添加了Javascript解释,它相当轻松而且功能强大。Rhino JavaScript引擎无法在运行时执行Java代码。@AndersonGreen:实际上,您可以导入Java类并将它们用作JavaScript对象,但我写的主要是针对那些重点在于能够轻松地动态运行代码的情况,而不是必须是Java代码。

import javax.script.*;
public class EvalScript { 
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
        engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
    }
}