Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 运行时代码生成和编译_Java_Code Generation_Classloader_Javac_Runtime Compilation - Fatal编程技术网

Java 运行时代码生成和编译

Java 运行时代码生成和编译,java,code-generation,classloader,javac,runtime-compilation,Java,Code Generation,Classloader,Javac,Runtime Compilation,假设我有一段代码,它使用一些输入(例如URL路径)通过反射来确定要运行的方法: // init map.put("/users/*", "viewUser"); map.put("/users", "userIndex"); // later String methodName = map.get(path); Method m = Handler.class.getMethod(methodName, ...); m.invoke(handler, ...); 这将使用反射,因此可以提高性

假设我有一段代码,它使用一些输入(例如URL路径)通过反射来确定要运行的方法:

// init
map.put("/users/*", "viewUser");
map.put("/users", "userIndex");

// later
String methodName = map.get(path);
Method m = Handler.class.getMethod(methodName, ...);
m.invoke(handler, ...);
这将使用反射,因此可以提高性能。可以这样做:

// init
map.put("/users/*", new Runnable() { public void run() { handler.viewUser(); } });
map.put("/users", new Runnable() { public void run() { handler.userIndex(); } });

// later
Runnable action = map.get(path);
action.run();
但是手动创建所有这些
Runnable
s都有它自己的问题。 我想知道,我能在运行时生成它们吗?因此,我有一个输入映射,如第一个示例中所示,并将动态创建第二个示例的映射。 当然,生成它只是构建一个字符串,但是编译和加载它呢


注意:我知道性能提升非常少,这是过早优化的完美例子。因此,这是一个学术问题,我对代码的运行时生成和编译感兴趣。

动态生成代码的唯一方法是生成源代码并编译,或者生成字节代码并在运行时加载。前者有模板解决方案,后者有字节码操作库。如果没有一个真实的案例和一些分析,我认为你真的不能说哪一个更好。从维护的角度来看,我认为反射是最好的选择。

好的,您可以将代码写入.java文件,用javac()编译它,然后用反射将其加载到java中


但是,作为一种权衡,您也可以在初始化期间获取方法对象,因此您只需为每个请求调用invoke()方法。

我认为您可以通过找到的代码实现这一点。这是一段时间以前我尝试过的,我不确定我在哪里找到了我正在使用的代码,但这似乎是一样的

基本上,您使用1.6编译器API,但使用“非传统”的方式查找源文件并编写类文件:
编译器采用
Iterable
,插入内存支持的实现,以及处理编写类文件的
JavaFileManager
,在内存中保存二进制编译器输出的位置

现在您的代码已经编译好了,您只需要一个自定义的
类加载器
,它可以从内存中读取字节码并用正确的FQCN等加载类


幸运的是,一切似乎都准备好了;)

实际上,如果您反复调用相同的方法,反射引擎将在内部生成类似的调用存根。(只需使用相同的
方法
对象,而不是一次又一次地重新创建它们。)