Java server memory leak

Discussions

General J2EE: Java server memory leak

  1. Java server memory leak (9 messages)

    So I have this simple java server. Works great .. until I notice it gobbles up memory with every request. After some initial investigation, it appear as though the classes that are run as threads (to service the request) are not being reclaimed. I'm having trouble determining what is going on, so I wrote a simple base case (code listed below). When I run this, and connect to the server multiple times via telnet, I never see the output from the garb2's finalize method. I'm assuming this is because the class is never marked for garbage collection. How come? I must be missing something incredibly obvious here ...

    public class Garb1
    {
      public static void main(String[] args)
      {
        try
        {
          ServerSocket sc = new ServerSocket(9090);
          sc.setSoTimeout(30000);

          while(true)
          {
            try
            {
              Socket sock = sc.accept();
              System.out.println("Incomming connection received");
              Garb2 wt = new Garb2(sock);
              wt.run();

              System.out.println("Run() called, looping around");
            }
            catch(java.io.InterruptedIOException joi)
            {
              System.out.println("Interrupted exception caught");
            }
          }
        }
        catch(Exception e)
        {
          System.out.println("Error");
        }
      }
    }


    public class Garb2 extends Thread
    {
      public Garb2(Socket p_socket)
      {
        System.out.println("Garb2 constructing");
        _buffer = new int[90000];
        _socket = p_socket;
        setName("Garb2");
      }

    public void run()
    {
      System.out.println("Garb2 running. Closing socket ...");
      try
      {
        _socket.close();
      }
      catch(Exception e)
      {
        System.out.println("Error closing socket");
      }
      System.out.println("Garb2 exiting");
    }

    public void finalize () throws java.lang.Throwable
    {
      System.out.println("Garb2 finalize method called");
    }

    private Socket _socket;
    int[] _buffer;
    }

    Threaded Messages (9)

  2. Java server memory leak[ Go to top ]

    Rich,

    If you want to spawn a thread, you use the start() method instead of the run() method. (The run() method will be called from the new thread of execution.) With this modification your code works correctly. It appears that if you create a Thread but never execute it the garbage collector does not reclaim it.

      - Nathan
  3. Java server memory leak[ Go to top ]

    Take from Thinking in Java 2nd Edition by Bruce Eckel

    Your objects might not get garbage-collected.


    You might find that the storage for an object never gets released because your program never nears the point of running out of storage. If your program completes and the garbage collector never gets around to releasing the storage for any of your objects, that storage will be returned to the operating system en masse as the program exits. This is a good thing, because garbage collection has some overhead, and if you never do it you never incur that expense.
  4. Java server memory leak[ Go to top ]

    The problem might be that your server doesn't really need more memory, so it doesn't even try to release some.
    If you want to test this, you can pass -Xmx<size> to the java interpreter (works in Sun VMs). This sets the maximal heap size that the VM will use. Pass in a small value so that you run out of memory quickly, and see what happens.

    Gal
  5. Java server memory leak[ Go to top ]

    The code above, run on JDK 1.3.1, throws an OutOfMemory exception before any of the finalizers gets run. If the run() is changed to start(), then the finalizers run long before the system runs out of memory.
  6. Java server memory leak[ Go to top ]

    Nathan,
    Why would the code above run out of memory? It doesn't start a new thread, so everything will be single-thread. And...?
    All it does is create a socket, initialize some byte array, close the socket. Over and over again. It seems to me like this would use even less memory than the multi-thread case...

    Anyway, start() should be called instead of run(), obviously. Can you explain why you think this is the cause for this specific problem?

    Gal
  7. Java server memory leak[ Go to top ]

    Gal,

    I'm not sure why, I just observed that it did by running it and then connecting to it numerous times. I expected to see it approach 64 meg heap, then run the garbage collector and run the finalizers. What I observed was that it approached 64 meg heap (estimated as the total process size was in the upper 60's) then ran out of memory.

    I just poked around on developer.java.sun.com and I found bug 4508232 "Unborn Threads and not garbage collected" and bug 4203988 "threads are not garbage collected if Constructor fails with an exception", both of which are marked as "In progress, bug". The result of either of these bugs would be that the java.lang.Thread objects allocated after the accept() would never be garbage collected because they are never run.
     - Nathan
  8. Java server memory leak[ Go to top ]

    Oh well, another brilliant Java "feature"... heh :(
    Allmost as good as bug 4467968, where Selector.wakeup() simply does nothing :)
    Keep up the good work Sun.
  9. Java server memory leak[ Go to top ]

    That's one way to look at it. All software has problems (some more than others), but the ability to search Sun's database of bugs is a wonderful thing. Now if I could just figure out in which release of the JVM the fixes actually ended up...

     - Nathan
  10. Java server memory leak[ Go to top ]

    I have the same problem too ever I use Thread Pool to prevent Object over Creation. I have used JProde to profile the application and found that ServerSocket.accept() has hook up the memory resource and cannot release. I think this is the JVM bug. I have directly run the same byte code in JVM 5.0 and not occur this problem. The previous version I tried with OutOfMemory is JVM 1.4.2_05 and so do 1.4.2_06