如果 ServerSocket 被垃圾回收,则其关联的端口绑定会发生什么情况



我想创建一个应用程序,它可以检测自身的其他实例并阻止它们运行。 为此,我正在考虑在某个特定于应用程序的端口上打开一个新ServerSocket,然后依靠如果我尝试多次绑定到同一端口以"检测"和终止重复的应用程序实例时应引发的异常。 我知道我可以做一些事情,比如将文件写入当前工作目录并"检测"它来完成相同的行为,但我真的不想这样做(如果应用程序死机并且无法删除文件会发生什么?(,所以这就是我选择ServerSocket路线的原因。

假设我有以下代码:

public class MyClass{
    public static void main(String[] args) throws IOException{
        new ServerSocket(1234);
        new Thread(){
            //This is a non-daemon thread. Assume its run() method never returns.
        }.start();
    }
}

问题

除了创建ServerSocket,我的应用程序永远不会真正需要再次使用它,因为它的存在允许我检测我的应用程序的另一个实例何时尝试启动。 因此,保存对所述ServerSocket的引用将导致编译警告(未使用的引用(。 我是一个整洁的怪胎,所以如果我能避免它,我宁愿不保存引用。 我的问题是,这个ServerSocket实例是否会在所有非守护进程退出之前被垃圾回收(假设应用程序没有失败或以其他方式退出(,如果是这样,它的关联端口是否会因此而不受绑定?

我很

困惑:你是一个"整洁的怪胎",但宁愿让套接字关闭听从垃圾收集器的突发奇想,而不是在正常退出的情况下在应用程序的控制下有一个关闭程序?(我认为情况确实如此,因为要建立这样的机制,您需要保留一个参考,从而消除您感知到的问题。

就其价值而言,如果您不坚持参考,我认为在实践中实际上不会有问题:

  • 在内部,很可能在绑定套接字时会保留引用
  • ServerSocket 的 close(( 方法很可能会在垃圾回收时被调用。它是在 AbstractPlainSocketImpl 的 finalize(( 方法中调用的,所以原则上会被调用,条件是不能保证任何 finalize 方法都会被调用。
  • 如果应用程序异常终止,则无法保证套接字将立即解除绑定,尽管在最近的 O/Ses 上很可能是(最好对此进行测试(。

但是,我真的建议为您的应用程序完全关闭的情况编写一个"干净"的关闭机制,为此您需要保留对套接字的引用。所以我认为你真的在为自己发明一个问题,如果你只是使用合理的编程实践,这个问题就不需要存在。

好吧,让我试着从我以前的错误理解中救赎自己。您提到的文件锁定和套接字技术被广泛使用,但还有另一种技术 - 拥有一个观察器来保留 yor 程序的当前实例(通过方法寄存器和取消注册(。

如果新实例尝试注册,而另一个实例正在运行,则注册过程将失败,并且应用程序可能会正常关闭。

然后,您的应用程序可以实现一个接口 Observable,该接口将包含一个方法 beObserve ,以便您的观察者知道您的应用程序仍然处于活动状态。因此,如果应用程序崩溃,定期检查将失败,并且会自动取消注册崩溃的应用程序。

相关内容

最新更新