Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当套接字被取消引用时,它们是否被垃圾收集_Java_Multithreading_Sockets_Networking_Garbage Collection - Fatal编程技术网

Java 当套接字被取消引用时,它们是否被垃圾收集

Java 当套接字被取消引用时,它们是否被垃圾收集,java,multithreading,sockets,networking,garbage-collection,Java,Multithreading,Sockets,Networking,Garbage Collection,我试图理解SO_超时、线程资源和垃圾收集的概念 在我的项目中,我看到了一个编码错误,一个集合被错误地取消引用,而没有关闭 使用Java1.6,它们可以在几分钟内关闭,但使用Java1.8,它们需要几个小时才能关闭。[仅在linux平台上测试] 所以我想更深入地研究这个问题 我创建了这个程序,在其中我创建了10个套接字,但正如您所看到的,其中9个是去激磁的,然后线程进入长睡眠时间: import java.net.Socket; /** * Created by 212477559 o

我试图理解SO_超时、线程资源和垃圾收集的概念

在我的项目中,我看到了一个编码错误,一个集合被错误地取消引用,而没有关闭

使用Java1.6,它们可以在几分钟内关闭,但使用Java1.8,它们需要几个小时才能关闭。[仅在linux平台上测试]

所以我想更深入地研究这个问题

我创建了这个程序,在其中我创建了10个套接字,但正如您所看到的,其中9个是去激磁的,然后线程进入长睡眠时间:

    import java.net.Socket;

/**
 * Created by 212477559 on 5/30/16.
 */
public class TestClientSocket {

    public static void main(String args[])
    {
        try
        {
            Socket socket;
            for(int j=0;j<10;j++)
            {
                socket =new Socket("localhost",9090);
                socket.setKeepAlive(false);
            }


            Thread.sleep(900000);

        }
       catch(Exception e)
        {
            System.out.println("throws");
            e.printStackTrace();
        }
    }
}

垃圾收集与这些套接字仍然打开这一事实无关

简单地说一下

垃圾收集是查看堆内存的过程, 识别哪些对象正在使用,哪些未使用,并删除 未使用的对象。正在使用的对象或引用的对象表示 程序的某个部分仍然保持指向该部分的指针 对象未使用的对象或未引用的对象不再是 被程序的任何部分引用。那么一个 可以回收未引用的对象

现在,虽然套接字对象使用的内存可能会被回收,但这并不意味着操作系统对套接字的句柄会随着JVM回收内存的过程而被破坏(这是两件不同的事情)

这就是为套接字提供方法的原因。这是确保操作系统释放套接字句柄的唯一方法

不再需要插座时,应始终关闭插座

使用Java1.6,但使用Java1.8,它们会在几分钟内关闭 他们需要几个小时才能关门


如果它们关闭,这甚至不应该成为讨论点。

当本机资源由java对象表示时,可以在资源保持分配状态的同时对该对象进行垃圾收集。为了提供安全网,java对象可以覆盖其finalize()方法来实现释放资源

我假设在具体的套接字实现的某个地方有一个finalize,在这里处理这个问题,尽管我在快速浏览源代码时找不到它的位置

finalize的问题是,它仅在实际收集对象时执行,而不是在对象符合GC条件时执行。在您的示例代码中,您的套接字符合GC的条件,但由于您所做的只是睡眠,因此VM没有压力实际执行GC


编辑:我没有强调或提及的一点,因为这对我来说是很自然的:使用套接字(或任何真正获取OS级资源的方法)的唯一正确方法是遵循资源提供的close()/dispose()协议。只有在完成后立即显式关闭资源,才能确保资源已释放。在JVM堆和垃圾收集经过精细调整的场景中,对象可能在较长时间内(几天或几周,可能永远不会)不会被收集。

我深入研究了这个问题,并找到了一个有趣的答案,@Durandal和@Michael Markidis也暗示了这一点。 发生的事情是,由于我的代码中的编码错误,对象被延迟了。 现在的问题是,为什么这个被解除引用的对象没有在Java1.8中关闭套接字,而是在Java1.6中关闭

我发现的是

  • 默认情况下,我的系统中的Java1.6只为survior空间分配了12MB
  • 默认情况下,我的系统中的Java1.8为survior空间分配了50MB
由于较小的生存空间,我的旧版本开始快速填充,这导致了Java1.6中频繁的主要垃圾收集。 但在Java1.8中,主要的垃圾收集发生在几个小时之后,就在那之后,我的套接字被关闭

因此,这个问题被发现是因为通过不同的JVM版本分配新的_比率和幸存者_比率的行为发生了变化。
当我在java 1.8中使用相同的新\u比率和幸存者\u比率(在java 1.6中分配)进行测试时,我可以看到我的套接字经常关闭。

关闭套接字是关闭套接字的唯一正确方法。垃圾收集不是一种资源清理机制,超时也不是。您可能想为此编写
finalize()
方法,但不要这样做。垃圾收集器在堆中的可用空间不足时运行。它不会运行,因为其他资源不足。@zapl&james我知道关闭套接字是正确的方法。我只是想了解我的项目问题,在不同的java版本中哪里出了问题。因此,我想了解套接字、线程和垃圾回收之间的关系。您的问题只是没有关闭套接字。它与线程无关,当线程休眠时,测试代码中引用的唯一套接字是最后一个创建的套接字,因为
socket
仍然指向它。其余的可以是GC的,但是您的测试程序产生0个垃圾,所以GC不需要运行。超时不会导致清理。当您调用读或写方法时,它们会给您异常。垃圾收集器没有理由在您的程序中运行。创建10个对象,然后永远睡眠。之后不会创建任何垃圾。在那一点之后也不需要内存。内存需求是垃圾收集的驱动力。从你的回答中,我得到了一个线索,解除防护的对象和套接字处理程序是不同的。我也同意关闭插座是唯一好的选择。但我现在想了解的是,当拥有相同的平台时,为什么拥有两个不同版本的java会改变这种行为。如果你能给出任何可能出错的提示,那将非常有用。在1.6和1.8之间的多次比较中,这种行为是否一致?是的,它是一致的。套接字计数在两个版本中都可以完成。但是对于Java1.8,它需要几个小时
   1. close the sockets?
   2. Thread which created those sockets must exit?
   3. SO_TIMEOUT should expire?