Java 如果对ServerSocket进行垃圾收集,其关联的端口绑定会发生什么情况?

Java 如果对ServerSocket进行垃圾收集,其关联的端口绑定会发生什么情况?,java,networking,serversocket,Java,Networking,Serversocket,我想创建一个可以检测自身其他实例并阻止它们运行的应用程序。为了实现这一点,我正在考虑在一些特定于应用程序的端口上打开一个新的ServerSocket,然后依赖于如果我多次尝试绑定到同一端口以“检测”并杀死重复的应用程序实例时应引发的异常。我知道我可以做一些事情,比如将一个文件写入当前的工作目录并“检测”它,以实现相同的行为,但我真的不想这样做(如果应用程序死亡并且无法删除该文件会发生什么情况?),所以我选择了ServerSocket路由 假设我有以下代码: public class MyClas

我想创建一个可以检测自身其他实例并阻止它们运行的应用程序。为了实现这一点,我正在考虑在一些特定于应用程序的端口上打开一个新的
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/SE上可能会解除绑定(最好对此进行测试)

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

好吧,让我试着从我以前的错误理解中解脱出来。您提到的文件锁和套接字技术被广泛使用,但还有另一种技术——拥有一个观察器,它将保持yor程序的当前实例(通过方法register和deregister)

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


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

这听起来是个可怕的主意。如果你真的想保留一个类的实例,我会考虑使用d-bus。我肯定windows也有类似的功能。@Falmari,你错了。这个想法不是一个单例类,而是一个单例程序。我想确保特定的main()方法在每台机器上执行不超过一次,而不是在每台JVM上执行。@falmari这是标准技术。与外部产品相对的两行代码?没问题。@BenLawry OTOH我不认为一行静态变量声明会害死你。@EJP你是对的,不是。我想我只是希望ServerSocket和垃圾收集的行为定义得更好一点。再说一次,我认为任何编写过Java代码的人都希望Java垃圾收集的定义更好一点;)我不知道你是如何理解这个问题的,所以让我澄清一下——我宁愿让这个特定的套接字靠近JVM和底层O/S的退出,而不是垃圾收集器,我只是好奇如果我这样编写程序,垃圾收集器会做些什么。以一种侮辱开始你的回答,并假设我没有使用“明智的编程实践”回避了这个问题,也没有太大的帮助。“不能保证套接字会立即解除绑定,尽管在最近的O/SE上很可能(最好测试一下)”。操作系统在我使用25年以上(Netware除外)的所有情况下都提供了这一保证。@EJP祝贺您所使用的操作系统提供了这一保证,并且它一直为您工作。我用过其中一个条件不成立的例子…:-)[包括至少一个名为“Windows”的操作系统版本]@NeilCoffey您错过了关于Netware的部分:它没有发布某些资源,这就是我提到它的原因。我从3.0开始使用的所有Windows版本都应该在进程退出时释放所有进程资源。如果他们没有,那就是一只虫子。这不需要Java来保证。更重要的是,
ServerSocket
似乎直接扩展了
Object
,但没有覆盖
finalize()
。似乎在垃圾收集之前没有显式关闭的
ServerSocket
实例实际上并没有放弃它们的本机r