How can I figure out what is holding on to unfreed objects?

前端 未结 11 995
忘了有多久
忘了有多久 2020-12-13 16:11

One of our programs is sometimes getting an OutOfMemory error on one user\'s machine, but of course not when I\'m testing it. I just ran it with JProfiler (on

相关标签:
11条回答
  • 2020-12-13 16:21

    I would look at Collections (especially static ones) in your classes (HashMaps are a good place to start). Take this code for example:

    Map<String, Object> map = new HashMap<String, Object>(); // 1 Object
    String name = "test";             // 2 Objects
    Object o = new Object();          // 3 Objects
    map.put(name, o);                 // 3 Objects, 2 of which have 2 references to them
    
    o = null;                         // The objects are still being
    name = null;                      // referenced by the HashMap and won't be GC'd
    
    System.gc();                      // Nothing is deleted.
    
    Object test = map.get("test");    // Returns o
    test = null;
    
    map.remove("test");               // Now we're down to just the HashMap in memory
                                      // o, name and test can all be GC'd
    

    As long as the HashMap or some other collection has a reference to that object it won't be garbage collected.

    0 讨论(0)
  • 2020-12-13 16:21

    If you're getting OOM errors in a garbage collected language, it usually means that there's some memory not being accounted by the collector. Maybe your objects hold non-java resources? if so, then they should have some kind of 'close' method to make sure that resource is released even if the Java object isn't collected soon enough.

    0 讨论(0)
  • 2020-12-13 16:23

    Try Eclipse Memory Analyzer. It will show you for each object how it is connected to a GC root - an object that is not garbage collected because it is held by the JVM.

    See http://dev.eclipse.org/blogs/memoryanalyzer/2008/05/27/automated-heap-dump-analysis-finding-memory-leaks-with-one-click/ for more information on how Eclipse MAT works.

    0 讨论(0)
  • 2020-12-13 16:25

    No silver bullet there, you have to use the profiler to identify collections that hold those unneeded objects and find the place in code where they should have been removed. As JesperE said, static collections are the first place to look at.

    0 讨论(0)
  • 2020-12-13 16:30

    Keep an eye out for static containers. Any objects in a static container will remain as long as the class is loaded.

    Edit: removed incorrect remark on WeakReference.

    0 讨论(0)
  • 2020-12-13 16:31

    Dump the heap and inspect it.

    I'm sure there's more than one way to do this, but here is a simple one. This description is for MS Windows, but similar steps can be taken on other operating systems.

    1. Install the JDK if you don't already have it. It comes with a bunch of neat tools.
    2. Start the application.
    3. Open task manager and find the process id (PID) for java.exe (or whatever executable you are using). If the PID's aren't shown by default, use View > Select Columns... to add them.
    4. Dump the heap using jmap.
    5. Start the jhat server on the file you generated and open your browser to http://localhost:7000 (the default port is 7000). Now you can browse the type you're interested in and information like the number of instances, what has references to them, etcetera.

    Here is an example:

    C:\dump>jmap -dump:format=b,file=heap.bin 3552
    
    C:\dump>jhat heap.bin
    Reading from heap.bin...
    Dump file created Tue Sep 30 19:46:23 BST 2008
    Snapshot read, resolving...
    Resolving 35484 objects...
    Chasing references, expect 7 dots.......
    Eliminating duplicate references.......
    Snapshot resolved.
    Started HTTP server on port 7000
    Server is ready.
    

    To interpret this, it is useful to understand some of the array type nomenclature Java uses - like knowing that class [Ljava.lang.Object; really means an object of type Object[].

    0 讨论(0)
提交回复
热议问题