Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7181793

Socket getOutputStream create streams that cannot be GC'ed until Socket is closed

    Details

    • Subcomponent:
    • Resolved In Build:
      b63
    • CPU:
      x86
    • OS:
      os_x
    • Verification:
      Verified

      Description

      FULL PRODUCT VERSION :
      openjdk version "1.7.0-jdk7u6-b16"
      OpenJDK Runtime Environment (build 1.7.0-jdk7u6-b16-20120704)
      OpenJDK 64-Bit Server VM (build 23.2-b08, mixed mode)


      A DESCRIPTION OF THE PROBLEM :
      FileDescriptor keeps a hard reference to Closeables associated with the FD causing applications to leak memory. This is regression from version <= 1.7u5 caused by the fix to a different bug.

      A very common pattern for systems that pool sockets is to ask for an outputstream along with each request. Long running processes with pooling will consume more and more memory until they run out.

      If you execute the test case like this:

      /Library/Java/JavaVirtualMachines/1.7.0u6.jdk/Contents/Home/bin/java -XX:+HeapDumpOnOutOfMemoryError -Xms32M -Xmx32M filedesc.Test

      It will output:

      100000
      200000
      300000
      java.lang.OutOfMemoryError: GC overhead limit exceeded
      Dumping heap to java_pid40237.hprof ...
      Heap dump file created [42914849 bytes in 0.539 secs]
      Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
      at java.net.Socket.getOutputStream(Socket.java:912)
      at filedesc.Test.main(Test.java:23)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

      Analyzing the heap dump you will find approximately:

      324339 instances of class [B
      323816 instances of class java.lang.Object
      323731 instances of class java.net.SocketOutputStream
      2079 instances of class [C
      2052 instances of class java.lang.String
      771 instances of class java.util.TreeMap$Entry
      757 instances of class [S
      570 instances of class java.lang.Class
      509 instances of class [I

      If you run the test case on any previous version of the JVM it will run indefinitely and not run out of memory.

      REGRESSION. Last worked in version 7

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Make a socket, getOutputStream, let the outputstream go out of scope, GC, notice that it isn't collected and is being held by the FileDescriptor.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      You should be able to ask for an outputstream from a socket without closing it and without that outputstream leaking.
      ACTUAL -
      The FileDescriptor adds each SocketOutputStream to an ArrayList with a hard reference.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package filedesc;

      import java.io.IOException;
      import java.net.ServerSocket;
      import java.net.Socket;

      public class Test {
        public static void main(String[] args) throws IOException {
          final ServerSocket serverSocket = new ServerSocket(2000);
          new Thread(new Runnable() {
            public void run() {
              try {
                serverSocket.accept();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          }).start();

          int i = 0;
          Socket socket = new Socket("localhost", 2000);
          while(true) {
            socket.getOutputStream();
            if (++i % 100000 == 0) System.out.println(i);
          }
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Replace FileDescriptor.class with a previous version that works correctly. Here is a suggested fix that uses weak references:

      https://gist.github.com/3041647

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                coffeys Sean Coffey
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: