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

时间:2023-01-06 19:16:22

I want to create an application that can detect other instances of itself and prevent them from running. To accomplish this, I'm thinking of opening up a new ServerSocket on some application-specific port, and then relying on the exception that should be thrown if I try to bind to the same port more than once to "detect" and kill duplicate application instances. I know I could do something like write a file into the present-working-directory and "detect" it to accomplish the same sort of behavior, but I really don't want to do this (what happens if the app dies and can't remove the file?), so that's why I've chosen the ServerSocket route.

我想创建一个可以检测自身的其他实例并阻止它们运行的​​应用程序。为了实现这一点,我正在考虑在某个特定于应用程序的端口上打开一个新的ServerSocket,然后依赖于应该抛出的异常,如果我尝试多次绑定到同一个端口来“检测”并终止重复应用实例。我知道我可以做一些事情,比如将文件写入当前工作目录并“检测”它以完成相同的行为,但我真的不想这样做(如果应用程序死了会发生什么事情'删除文件?),这就是为什么我选择了ServerSocket路由。

Let's say I have the following code:

假设我有以下代码:

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();
    }
}

Question

Short of creating the ServerSocket, my application never really needs to use it again, because its mere existence allows me to detect when another instance of my app attempts to start up. Thus, saving a reference to said ServerSocket will result in a compile warning (unused reference). I'm a neat-freak, so I'd rather not save a reference if I can avoid it. My question is, will this ServerSocket instance get garbage collected before all non-daemon threads exit (assuming the app doesn't fail or exit some other way), and if so, will its associated port become unbound as a result?

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

2 个解决方案

#1


4  

I'm confused: you're a "neat freak" but would rather leave socket closing to the whims of the garbage collector than have a close procedure under the control of the application in the case of a normal exit? (I assume this to be the case, because to put such a mechanism in place you would need to hold a reference, thus eliminating your perceived problem.)

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

For what it's worth, I don't think that there'll actually be a problem in practice if you don't hold on to the reference:

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

  • internally, it is likely that a reference will be held while the socket is bound
  • 在内部,很可能在套接字绑定时将保持引用
  • it is likely that the ServerSocket's close() method will be called on garbage collection. It is called in the finalize() method of AbstractPlainSocketImpl, so in principle will be called, with the proviso that there is no guarantee that any finalize method will actually get called.
  • 很可能在垃圾收集时调用ServerSocket的close()方法。它在AbstractPlainSocketImpl的finalize()方法中调用,因此原则上将被调用,条件是不能保证任何finalize方法实际上都会被调用。
  • if the application terminates abnormally, there is no guarantee that the socket will be unbound immediately, though on recent O/Ses it is likely to be (best to test this).
  • 如果应用程序异常终止,则无法保证套接字将立即解除绑定,但在最近的O / Ses中可能是(最好对此进行测试)。

However, I would really recommend coding a "clean" shutdown mechanism for the case where your app is shut down cleanly, and for that you will need to hold on to a reference to the socket. So I think you're really inventing a problem for yourself that need not exist if you just use sensible programming practice instead.

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

#2


1  

OK, let me try to redeem myself from my previous wrong understanding. The file lock and socket techniques that you mention are widely used but there is another one - having an observer that will keep the current instance of yor program (through methods register and deregister).

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

If a new instance tries to register while there is another one running, the registration process will fail and your application could close gracefully.

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

Your application could then implement an interface Observable that would contain one method beObserved in order for your observer to know that your application is still alive. Therefore, if your application crashes, the periodic check would fail and it would deregister the crashed application automatically.

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

#1


4  

I'm confused: you're a "neat freak" but would rather leave socket closing to the whims of the garbage collector than have a close procedure under the control of the application in the case of a normal exit? (I assume this to be the case, because to put such a mechanism in place you would need to hold a reference, thus eliminating your perceived problem.)

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

For what it's worth, I don't think that there'll actually be a problem in practice if you don't hold on to the reference:

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

  • internally, it is likely that a reference will be held while the socket is bound
  • 在内部,很可能在套接字绑定时将保持引用
  • it is likely that the ServerSocket's close() method will be called on garbage collection. It is called in the finalize() method of AbstractPlainSocketImpl, so in principle will be called, with the proviso that there is no guarantee that any finalize method will actually get called.
  • 很可能在垃圾收集时调用ServerSocket的close()方法。它在AbstractPlainSocketImpl的finalize()方法中调用,因此原则上将被调用,条件是不能保证任何finalize方法实际上都会被调用。
  • if the application terminates abnormally, there is no guarantee that the socket will be unbound immediately, though on recent O/Ses it is likely to be (best to test this).
  • 如果应用程序异常终止,则无法保证套接字将立即解除绑定,但在最近的O / Ses中可能是(最好对此进行测试)。

However, I would really recommend coding a "clean" shutdown mechanism for the case where your app is shut down cleanly, and for that you will need to hold on to a reference to the socket. So I think you're really inventing a problem for yourself that need not exist if you just use sensible programming practice instead.

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

#2


1  

OK, let me try to redeem myself from my previous wrong understanding. The file lock and socket techniques that you mention are widely used but there is another one - having an observer that will keep the current instance of yor program (through methods register and deregister).

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

If a new instance tries to register while there is another one running, the registration process will fail and your application could close gracefully.

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

Your application could then implement an interface Observable that would contain one method beObserved in order for your observer to know that your application is still alive. Therefore, if your application crashes, the periodic check would fail and it would deregister the crashed application automatically.

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