Garbage Collector와 Memory Leak

지니🧸·2023년 4월 14일
0

Java

목록 보기
8/13

Memory Leak

Memory leak: GC fails to remove from the memory the objects present in the heap that are no longer used.

The unnecessarily maintained objects block memory resources and degrades system performance over time. This problem will eventually lead the application to exhaust its resources and reach the java.lang.OutOfMemoryError.

  • Referenced objects: objects that still have active references within the application
  • Unreferenced objects: objects that don't have any active references

The GC removes unreferenced objects periodically, but it never collects the objects that are still being referenced.

Symptoms of memory leak

  • severe performance degradation when application is continuously running for a long time
  • OutOfMemoryError
  • spontaneous & strange application crashes
  • application occasionally runs out of connection objects
    • connection object: represents a unique session with a data source
      • equivalent of an actual network connection to server in a client/server database system

Types of memory leaks in Java

Through static fields

Heavy use of static variables can cause a potential memory leak.

In Java, static fields have a life that usually matches the entire lifetime of the running application. So, if collections or large objects are declared as static, then they remain in the memory throughout the lifetime of the application, thus blocking vital memory taht could be used elsewhere.

Prevent this type of memory leak by:

  • minimize the use of static variables
  • when using singletons, rely upon an implementation that lazily loads the object (instead of eagerly loading)
    • singleton: a class has only one instance that provides a global access point

Through unclosed resources

When we make a new connection or open a stream, the JVM allocates memory for these resources, including database connections, input streams, and session objects. Forgetting to close these resources can block the memory and prevent the GC from reaching these resources. Even if you added lines to close these resources, if the program execution can't reach those lines due to exceptions, then the resources are not closed.

Open connections consume memory and will eventually deteriorate performance and/or result in an OutOfMemoryError.

Prevent this type of memory leak by:

  • use finally block to close resources (try-catch-finally)
  • code that closes resources shouldn't have any exceptions itself

Through improper equals() & hashCode() implementations

Improper overriding of equals() and hashCode() methods may cause memory leaks.

(ex) Without a proper overriding method of equals() in hashmap, the hashmap will not be able to detect objects of same key being added to the hashmap and thus fail to prevent these objects from being added onto the map.

Through inner classes that reference outer classes

Non-static inner classes always require an instance of the enclosing class for initialization, so every non-static inner class has an implicit reference to its enclosing class by default.

If we use the inner class's object, then even after we no longer use the enclosing object, the enclosing class won't be garbage collected. Since the inner class object implicitly holds a reference to the outer class object, the outer class cannot be subject to garbage collection.

Prevent this type of memory leak by: turning the inner class into a static class if the inner class doesn't have to have access to the enclosing class.

Same goes for anonymous classes.

Through finalize() methods

If a class's finalize() method is overriden, the objects of that class are not instantly garbage collected but rather queued by the GC for finalization that will occur later on.

Also, if the code that overrides finalize() isn't optimal & the finalizer queue can't keep up with the GC, the application will eventually meet OutOfMemoryError.

Prevent this type of memory leak by: avoid finalizers

Finalizers

Finalizer - finalize()

  • invoked when JVM finds out that this instance should be garbage collected
  • can perform any operations, including bringing object back to life
  • purpose: to release resources used by objects before they're removed from memory
  • the time the GC calls finalizers depend on the JVM's implementation & system conditions
    • out of programmers' control

Avoid finalizers:

  • we might run out of resources before finalizers clean up
  • if finalizer throws an exception, the finalization process stops & leaves object in a corrupted state w/o notificatin

Through Interned Strings, ThreadLocals, etc.

Java's Garbage Collector

Java operates on an automated memory management, thanks to the built-in garbage collector. The GC implicitly takes care of allocating and freeing up memory, preventing most memory leak issues, but it is not flawless. Memory leak issues can still happen in Java.

Java's GC is a Mark and Sweep algorithm, which knows whether the object is alive by keeping track of references from the root. So, it does not count the number of references.


References:

profile
우당탕탕

0개의 댓글