Java 如何销毁SelectionKey附件?附加(空)不';行不通

Java 如何销毁SelectionKey附件?附加(空)不';行不通,java,tcp,memory-leaks,nio,Java,Tcp,Memory Leaks,Nio,我的java应用程序有内存泄漏——当我的资源清理代码执行任务管理器时,显示内存使用情况没有改变。我的代码 while (isRunning) { try { selector.select(); long sum=0; Set keys = selector.selectedKeys(); Iterator it = keys.iterator();

我的java应用程序有内存泄漏——当我的资源清理代码执行任务管理器时,显示内存使用情况没有改变。我的代码

while (isRunning) {
      try 
      {

             selector.select(); 

             long sum=0;

             Set keys =  selector.selectedKeys();
             Iterator it = keys.iterator(); 
             while(it.hasNext())
             {
                 SelectionKey key = (SelectionKey)it.next();
                 if (key.isReadable())
                 { 
                      SocketChannel sc = (SocketChannel) key.channel();

                      ByteBuffer bb;
                      if(key.attachment()==null)
                      {
                          bb = ByteBuffer.allocate(1024*1024);
                          key.attach(bb);
                      }
                      else
                      {
                          bb = (ByteBuffer)key.attachment();
                          bb.clear();
                      }

                      int x =  sc.read(bb); 

                       System.out.println(x +" bytes were read");
                       if(x==-1)
                       {
                           key.attach(null); //doesn't work
                           sc.close();
                           //bb = null; // also doesn't work
                       }
                 } 
             }
           keys.clear();
      } 
      catch (Exception ex) 
      {     
          ex.printStackTrace(new PrintStream(System.out));
      }
      finally
      { 
            //stopServer();
      }
    }
测试逻辑——我编写了简单的TCP客户端java程序,向服务器发送100条消息。我特意为每个连接分配了1MB的大缓冲区。当客户完成其工作时
int x=sc.read(bb)返回-1,执行以下代码:

if(x==-1)
                           {
                               key.attach(null); //doesn't work
                               sc.close();
                               //bb = null; // also doesn't work
                           }
我用调试输出检查了它,这段代码确实执行了,但是任务管理器仍然显示了大量的内存使用。问题出在哪里?

当然
键。附加(空)
有效。否则,附加一个非空对象也不会起作用。相同的代码


但是,在任何情况下,关闭
SocketChannel
都会取消该密钥,这会将其从它注册的所有
选择器的所有密钥集中删除,因此您无论如何都不会再看到该密钥,因此它符合GC的条件,附件也符合GC的条件,无论您是否调用
key.attach(null)
,这是多余的。要么您在其他地方有另一个对附件的引用,要么您的内存使用问题在其他地方。

内存探查器显示连接的对象确实消失了—“最大已用堆大小”在客户端应用程序完成时减小。但是还有一个“最大堆大小”仍然很大,TaskManager显示了这个参数。如何减少“最大堆大小”?“使用的堆大小”减少了,但“堆大小”没有减少,这看起来很奇怪。现在你的问题是关于堆和垃圾收集。我建议你重新开始。这一个已经有了。