Java Heap Sapce

ref:https://plumbr.eu/outofmemoryerror/java-heap-space

java.lang.outOfMemoryError  -> heap memory used up

1. Java Heap Space

Java applications are only allowed to used a limit amount of memory. This limit is specified during application startup. To 

make things more complex, Java memory is separated into two different regions. These regions are called Heap space and Permgen(for Permanent Generation)

The size of those regions is set during the Java Virtual Machine(JVM) launch can can be customized by specifying JVM parameters -Xmx and -XX:MaxPermSize. If you do not explicitly set the sizes, platform-specific defaults will be used.

 

2. What is causing it?

1. Spikes in usage/data volume. The application is designed to handle a certain amount of users pr certain amount of data. When the number of users or the volume of data suddenly spikes and crosses that expected threshold, the operation which functioned normally before the spike causes to operate and triggers the heap space error

 

2. Memory leak

 

3. Example

The following code tries to allocate an array of 2M integers. when you compile it and launch with 12MB of Java heap space

(java -Xmx12m OOM), it failed with the java.lang.OutOfMemoryError. With 13MB Java heap space, the program works fine

class OOM {
  static final int SIZE=2*1024*1024;
  public static void main(String[] a) {
    int[] i = new int[SIZE];
   }
}

we can use the the following code to check max, allocated/total and free memory when we launch the
application using (java -Xmx12m OOM) to see whether it is true

class OOM {
  public static void main(String[] a) {
    Runtime runtime = Runtime.getRuntime();
  long max = runtime.maxMemory();
  long allocated = runtime.totalMemory();
  long free = runtime.freeMemory();
 } }
output:
max:         12058624
allocated/total:  12058624
free:        11627576

  

memory leak eample

In Java, when developers create and use new objects, they dont have to allocate memory themselves - this is taken care of by JVM. During the life of the application the JVM periodically checks which objects in memory are still being referenced and which are not. This process is called GC. Memory leak in Java s a situation where some objects are no longer used by the application but GC failes to recognize it. As a result these unuses objects remian in Java heap space indefinitely. This pileup will eventually trigger the java.lang.OutOfMemoryError.

class KeylessEntry {
 
   static class Key {
      Integer id;
 
      Key(Integer id) {
         this.id = id;
      }
 
      @Override
      public int hashCode() {
         return id.hashCode();
      }
   }
 
   public static void main(String[] args) {
      Map m = new HashMap();
      while (true)
         for (int i = 0; i < 10000; i++)
            if (!m.containsKey(new Key(i)))
               m.put(new Key(i), "Number:" + i);
   }
}

When you execute the above code, you might expect it to run forever without any problems, assuming that the native caching solution only expands the underlying Map to 10,000 elements, as beyond that all the keys will already be present in the HashMap. However, in reality, the elements will keep being added as the Key class does not contain a proper equals() implementation next to its hashCode().

As a result, over time, with the leaking code constantly used, the "cached" result end up consuming a lot of java heap. And when the leaked memory fills all of the available memory in the heap region and GC is not able yo clean it. The java,OutOfMemoryError will be thrown.

Solution:

add the implementation of equal

@Override
public boolean equals(Object o) {
   boolean response = false;
   if (o instanceof Key) {
      response = (((Key)o).id).equals(this.id);
   }
   return response;
}

 

 

4. Solution of OutOfMemoryError

1. Get security clearance in order to perform a heap dump from you JVM. "Dumps" are basically snapshots of heap contents that you can analyze. These snapshot can thus conain confidential information such as password, credit card number etc, so acquiring such as dump might not even be possible for security reasons.

 

2. Get the dump at the right moment.Be prepared to get a few dumps, as when taken at the wrong time, heap dumps contain a significant amount of noise and can be practically useless. ON the other hand, every heap dump "freexes" the JVM entirely, so dont take too many of them or your end users start facing performance issues.

 

3. Find a machine that can load the dump. When your JVM-to-troubleshoot uses for example 8GB of heap,, you need a a mcahine with more than 8GB to be able to analyze heap contents. Fire up dumo analysis software (Eclipse MAT, for instance)

 

4. Detect the paths to C roots of the biggest consumers of heap. we have coverd this activity in a separate post. It is especially tough for beginners, but the practise will make you understand the structure and navigation mechanics.

 

5. Next, you need to figure out where in your source code the potentially hazardous large amount of objects is being allocated. If you have good knowledge of your application's source code you will be able to do this in a couple searches.

posted @ 2016-07-15 14:03  morningdew  阅读(628)  评论(0编辑  收藏  举报