当前位置:  开发笔记 > 编程语言 > 正文

在Servlet的destroy()方法中调用System.exit()

如何解决《在Servlet的destroy()方法中调用System.exit()》经验,为你挑选了2个好方法。

这是我之前的问题的后续跟进.

Tomcat 5.0.28有一个错误,即关闭时容器没有调用Servlet的destroy()方法.这在Tomcat 5.0.30中得到修复,但如果Servlet的destroy()方法有一个System.exit(),则会导致Tomcat windows服务抛出错误1053并拒绝正常关闭(有关详细信息,请参阅上面的链接)这个错误)

任何人都知道是否:

在Servlet的destroy()方法中调用System.exit()强制终止任何非守护进程线程是一个好主意?

如果Servlet的destroy()方法中存在System.exit(),为什么Tomcat 5.0.30和(包括Tomcat 6.xx的更高版本)无法正常关闭.

matt b.. 16

在Servlet的destroy()方法中调用System.exit()强制终止任何非守护进程线程是一个好主意?

这绝对不是一个好主意 - 这是一个可怕的想法.destroy()当servlet停止服务时调用该方法,这可能由于多种原因而发生:servlet/webapp已停止,webapp正在取消部署,webapp正在重新启动等.

System.exit()关闭整个JVM!为什么要简单地因为卸载一个servlet而强行关闭整个服务器?

如果Servlet的destroy()方法中存在System.exit(),为什么Tomcat 5.0.30和(包括Tomcat 6.xx的更高版本)无法正常关闭.

可能是为了防止这样的危险行为.

您不应该编写代码,假定您的代码/应用程序是服务器上运行的唯一内容.



1> matt b..:

在Servlet的destroy()方法中调用System.exit()强制终止任何非守护进程线程是一个好主意?

这绝对不是一个好主意 - 这是一个可怕的想法.destroy()当servlet停止服务时调用该方法,这可能由于多种原因而发生:servlet/webapp已停止,webapp正在取消部署,webapp正在重新启动等.

System.exit()关闭整个JVM!为什么要简单地因为卸载一个servlet而强行关闭整个服务器?

如果Servlet的destroy()方法中存在System.exit(),为什么Tomcat 5.0.30和(包括Tomcat 6.xx的更高版本)无法正常关闭.

可能是为了防止这样的危险行为.

您不应该编写代码,假定您的代码/应用程序是服务器上运行的唯一内容.


在任何情况下都不应该在servlet中调用System.exit().期.

2> Jared..:

你问了两个问题:

问题1:在Servlet的destroy()方法中调用System.exit()强制杀死任何非守护进程线程是个好主意吗?

在任何与servlet相关的方法中调用System.exit()总是100%不正确.您的代码不是JVM中运行的唯一代码 - 即使您是唯一运行的servlet(servlet容器具有在JVM真正退出时需要清理的资源.)

处理这种情况的正确方法是在destroy()方法中清理线程.这意味着以允许您以正确方式轻轻地停止它们的方式启动它们.这是一个例子(MyThread是你的一个线程,并扩展了ServletManagedThread):

 public class MyServlet extends HttpServlet {
    private List threads = new ArrayList();     

     // lots of irrelevant stuff left out for brevity

    public void init() {
        ServletManagedThread t = new MyThread();
        threads.add(t);
        t.start();
    }

    public void destroy() {
        for(ServletManagedThread thread : threads) {
           thread.stopExecuting();
        }
    }
 }

 public abstract class ServletManagedThread extends Thread {

    private boolean keepGoing = true;

    protected abstract void doSomeStuff();
    protected abstract void probablySleepForABit();
    protected abstract void cleanup();

    public void stopExecuting() {
       keepRunning = false;
    }

    public void run() {
       while(keepGoing) {
            doSomeStuff();
            probablySleepForABit();
       }
       this.cleanup();
    }
}

还有值得注意的是,有一些线程/并发库可以帮助解决这个问题 - 但如果你真的有一些在servlet初始化时启动并且应该运行直到servlet被销毁的线程,这可能就是你需要的全部内容.

问题2:如果Servlet的destroy()方法中存在System.exit(),为什么Tomcat 5.0.30和(包括Tomcat 6.xx的更高版本)无法正常关闭?

没有更多的分析,很难确定. 微软表示,当Windows要求服务关闭时,会出现错误1053,但请求超时.这将使Tomcat内部发生的事情变得非常糟糕.我当然会怀疑你的电话System.exit(可能是罪魁祸首.Tomcat(特别是Catalina)确实在VM上注册了一个关闭钩子(see org.apache.catalina.startup.Catalina.start()至少在5.0.30中).当你调用时,JVM会调用那个关闭钩子System.exit().关闭挂钩委托给正在运行的服务,因此可能需要每个服务执行大量工作.

如果关闭hooks(triggered by your System.exit())无法执行(它们死锁或类似的东西),那么很容易理解错误1053发生的原因,给定Runtime.exit(int)方法的文档(从中调用System.exit()):

如果在虚拟机开始其关闭序列后调用此方法,则如果正在运行关闭挂钩,则此方法将无限期地阻塞.如果已经运行了关闭挂钩并且已启用了退出终结,则此方法如果状态为非零,则使用给定的状态代码暂停虚拟机; 否则,它会无限期地阻止.

这种"无限期阻塞"行为肯定会导致错误1053.

如果您想要比此更完整的答案,您可以下载源代码并自行调试.

但是,我愿意打赌,如果你正确处理线程管理问题(如上所述),你的问题就会消失.

简而言之,将System.exit()调用留给Tomcat - 这不是你的工作.


@Geoff - 是的.如果您正在编写需要操作退出代码的命令行实用程序,则需要调用System.exit().如果您需要操作与servlet相关的进程中的退出代码,我会严重质疑您的系统设计.System.exit()仅在您对整个系统拥有非常严格的控制的情况下才有用 - servlet不是那种情况 - 其他人(容器)负责系统,而不是您的servlet.
推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有