如果ServerSocket被垃圾收集,它的相关端口绑定会发生什么?

时间:2012-05-21 23:40:57

标签: java networking 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实例是否会在所有非守护程序线程退出之前收集垃圾(假设应用程序没有失败或以其他方式退出),如果是这样,其关联端口是否会因此而未绑定?

2 个答案:

答案 0 :(得分:4)

我很困惑:你是一个“整洁的怪人”,但是在正常退出的情况下,在应用程序控制下有一个关闭程序,而不是将套接字关闭到垃圾收集器的异想天开? (我认为情况就是如此,因为要建立这样的机制,你需要持有一个参考,从而消除你的感知问题。)

对于它的价值,如果你不坚持参考,我认为在实践中确实存在问题:

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

但是,我真的建议为你的应用程序干净地关闭的情况编写一个“干净”的关闭机制,为此你需要保持对套接字的引用。所以我认为你真的为自己创造了一个问题,如果你只是使用合理的编程实践而不需要存在。

答案 1 :(得分:1)

好的,让我试着从我之前错误的理解中拯救自己。你提到的文件锁和套接字技术被广泛使用,但还有另一个 - 有一个观察者将保持你的程序的当前实例(通过方法注册和注销)。

如果新实例在另一个实例运行时尝试注册,则注册过程将失败,您的应用程序可以正常关闭。

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