gpt4 book ai didi

java - Tomcat 在运行时更新 java 文件

转载 作者:行者123 更新时间:2023-11-28 22:48:11 25 4
gpt4 key购买 nike

我正在使用 servlet 和 JSP 构建一个动态 Web 项目(在 Eclipse 中,以 Tomcat 作为服务器)。该项目的总体目的是让用户解决小的代码问题。为了做到这一点,我采用了用户编写的方法,并使用它来构建一个 java 文件,我可以通过 Reflection 运行该文件。我似乎无法弄清楚的问题是 Tomcat(或 Eclipse?)不会在运行时更新文件。因此,当我使用当前用户的代码创建文件并尝试编译它时,我的程序总是执行文件,就像我使用前一个用户的代码启动服务器时一样。我如何告诉它在运行之前更新文件?

编辑:这就是我创建文件的方式:

public boolean writeFile() {
try {
PrintWriter writer = new PrintWriter(relativePath + "src\\testfiles\\TestFile.java");
writer.print(content);
writer.close();
return true; }...

在这里,我调用编写器并尝试运行该文件:

FileWriter writer = new FileWriter(content);        
if(writer.writeFile()){
Class<?> TestFile;
Method m;
try {
TestFile = cl.loadClass("testfiles.TestFile");
m = TestFile.getDeclaredMethod("testSolution");
m.invoke(null);

提前致谢!

最佳答案

好的,现在很清楚问题是什么了。您的问题不是 Tomcat 没有重新加载文件,而是类加载器没有重新加载类。

普通的类加载器只会加载一个类一次,并将其永久保存在缓存中。卸载类的唯一方法是通过其类加载器进行垃圾回收。要重新加载一个类,您必须每次都使用不同的类加载器(前一个类加载器会被垃圾收集,否则您将耗尽内存),或者使用不缓存的自定义加载器。

参见 this article用于执行您想要的自定义类加载器的实现。

从理论上讲,您每次都可以只拥有一个新类(class)(通过在每次保存时更改其名称),但您最终会耗尽内存。

也许最简单的方法是在方法本身中实例化一个新的类加载器,加载一个类,在其上运行该方法,并且不要保留对加载器或类的任何其他引用。这样,您每次都会获得一个新加载的类,并且类和加载器的旧实例都将被垃圾收集。

更新:我假设您已经知道如何在运行时编译类,但根据评论,情况并非如此。当然,类加载器只能加载已编译的类,因此直接加载源不是很有用。

Java内部在javax.tools.JavaCompiler下提供了一个编译器接口(interface),但是使用起来并不方便,而且需要对Java 9前后的Java版本做不同的处理。所以使用起来方便多了像jOOR这样的图书馆隐藏血淋淋的部分:

Class clazz = Reflect.compile("com.example.Test",
"package com.example;" +
"public class Test {\n" +
" public String hello() {\n" +
" return \"hello\";\n" +
" }\n" +
" }")
.type();

您实际上可以继续使用 jOOR 的流畅反射 API 来触发生成的类上的方法,或者您通常通过常规反射执行的任何操作,而不是简单地获取类的 type() .

对于直接 JavaCompiler 用法,参见例如this或者,更好的是,jOOR 的源代码。

关于java - Tomcat 在运行时更新 java 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50551213/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com