考虑一个非常简单的Spring Boot / Jersey应用程序设置:
JerseyConfig.java
std::vector
TestController.java
package com.example.unload;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JerseyConfig extends ResourceConfig {
JerseyConfig() { register(TestController.class); }
}
package com.example.unload;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Component @Path("test")
public class TestController {
@GET public String test() {
return "test";
}
}
任务并将WAR部署到Tomcat(在我的情况下为8.5)。每当我想取消部署(例如重新部署)WAR时,我都会收到以下错误消息
war
罪魁祸首是lib目录中的jersey-server-2.25.1.jar,显然某些类加载器必须有一个引用。我也无法手动删除该文件,因为Java会对其进行锁定。
有趣的是,在手动执行GC运行(外部通过jvisualvm)后,我我能够删除jersey-server.jar。 因此,我怀疑流未正确关闭(但在最终确定期间会关闭)。
当然,在生产环境中不能手动执行GC运行。
我尝试在Oct 23, 2017 8:13:11 AM org.apache.catalina.startup.ExpandWar deleteDir
FATAL: […\apache-tomcat-8.5.20\webapps\unload-0.0.1-SNAPSHOT\WEB-INF\lib] could not be completely deleted. The presence of the remaining files may cause problems
的{{1}}回调中调用System.gc()
,但是在仍有实时引用时会调用它。
我也知道contextDestroyed
文件中的ServletContextListener
选项,但这会在临时目录中创建整个WAR内容的副本,而不会删除它(这可能是一个cron job)。但是,这更像是一种解决方案,而不是一种高效的解决方案。
第三种可能的选择是提取所有Spring,Jersey和相关的依赖项并将其移动到Tomcat的共享antiResourceLocking
目录,但我更喜欢捆绑所有必需的依赖项以简化客户的部署。
我还有其他选择,根本原因是什么? 我没有找到任何关于Tomcat,Spring和Jersey的错误的引用。
我可以用Jersey 2.26和jersey-hk2 2.26重现这个问题。