如何查明客户端/服务器套接字连接的所有资源(线程、PrintWriters等)是否正确关闭



我正在编写一个客户端/套接字连接,并使用ThreadPools处理多个客户端。

在我的服务器启动后,我使用了几个资源。如果f.ex:服务器对客户端说它应该关闭,我想关闭所有的。

我仍然编码了一个基本的关闭功能:

public static void killClient() {
try {
threadpool.shutdown();
in.close();//client input
out.close();//client output
socket.close();
} catch(Exception e) {
System.out.println("Client has been shutdown! " + e);
e.printStackTrace();
}
}

我的问题是:

如何确保一切都已正常关闭,不再有任何东西运行?

如何确保一切都已正确关闭,并且不再运行?

我已经回答了下面的具体问题。

我认为"关闭"你的课程比集中精力关闭资源更重要。如果一个类(比如上面的Client类)封装了线程池和套接字等资源,那么它应该有一个close()方法(比如上面killClient())。如果服务器分叉客户端,那么它应该管理它们,以便server.close()调用各种client.killClient()方法。

如果您对正确关闭各种类、在任何地方使用try {} finally {}块持谨慎态度,则不必担心未关闭的资源和挂起的线程。


这很难做到,并且没有针对所有资源类型的一揽子答案。这里有几个想法可能会有所帮助。

  • 对于线程,您可以使用类似Threads.getAllStackTraces()的东西来显示剩余的线程。如果你在程序启动和结束时比较这个列表,你应该能够看到剩下的内容。

  • 文件描述符要难得多。如果您在Linux上运行,那么您可以查看/proc/self/fd目录,看看哪些描述符仍然打开。再次比较开始和结束。您还可以查看应用程序中的OpenFileDescriptorCountJMX变量(java.lang:type=OperatingSystem),但它只提供了没有上下文的描述符数量。

  • 没有简单的方法可以检测其他资源中的泄漏。您可以将ResourceManager类型的类封装在它们周围,从中"生成"one_answers"释放"资源,但这需要编程支持。如果您在管理器之外创建资源,则没有简单的方法来检测泄漏。

  • 这种机制的一个例子是我为ORMLite测试所做的工作。ORMLite打开和关闭了很多数据库连接,我想确保我的代码中没有泄漏它们。我为数据库连接创建了一个包装器,在创建数据库连接时,它会向管理器注册自己,在关闭数据库连接时取消注册自己。然后我可以确保assertTrue(connectionManager.isAllConnectionsClosed());。不确定这是否有帮助。

如果您使用Java7,那么您可以将try-with-resources构造用于所有可关闭的对象,如Socket、Connection、Statement等,一旦它们超出范围,就会自动关闭它们。

如果in.close()使out.close()失败,并且永远不会调用socket.colose(。

还要确保从finally块中调用方法killclient()。

最新更新