java memory leak and memory overflow difference

Although jvm can automatically reclaim useless memory through GC, there is still the risk of memory overflow if the code is not good.

I have recently collected some information on the Internet, and are now organized as follows:

 ——————————————————————————————————————————

 

1. Why should you understand memory leaks and memory overflows?

 

1. Memory leaks are generally caused by flaws in code design. By understanding the scenarios of memory leaks, you can avoid unnecessary memory overflows and improve your code writing level;

 

2. By understanding several common situations of memory overflow, you can quickly locate the location of the problem when memory overflow occurs, and shorten the time to solve the fault.

 

 

 2. Basic Concepts

 

It is very important to understand these two concepts.

 

Memory leak : refers to the dynamic allocation of memory to some temporary objects in the program, but the object will not be reclaimed by GC, it always occupies memory. That is , the allocated object is reachable but useless .

 

Memory overflow : refers to an error caused by the inability to apply for enough memory during the running of the program. Memory overflow usually occurs when there is still no memory space to accommodate new Java objects after the OLD segment or Perm segment is garbage collected.

 

By definition, it can be seen that memory leaks are a cause of memory overflow , not the only factor.

 

 

Three, several scenarios of memory leaks:

 

1. Long-lived objects hold references to short-lived objects

 

            This is the most common scenario for memory leaks, and it is also a frequent problem in code design.

            For example, if local variables are cached in the global static map, and there is no clearing operation, the map will become larger and larger over time, causing memory leaks.

 

2. Modify the parameter value of the object in the hashset, and the parameter is the field for calculating the hash value

 

             当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段,否则对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中删除当前对象,造成内存泄露。

 

3、机器的连接数和关闭时间设置

 

            长时间开启非常耗费资源的连接,也会造成内存泄露。

 

 

 

 四、内存溢出的几种情况:

 

1、堆内存溢出outOfMemoryError:java heap space

       在jvm规范中,堆中的内存是用来生成对象实例和数组的。

       如果细分,堆内存还可以分为年轻代和年老代,年轻代包括一个eden区和两个survivor区。

       当生成新对象时,内存的申请过程如下:

          a、jvm先尝试在eden区分配新建对象所需的内存;

          b、如果内存大小足够,申请结束,否则下一步;

          c、jvm启动youngGC,试图将eden区中不活跃的对象释放掉,释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;

          d、Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;

          e、 当OLD区空间不够时,JVM会在OLD区进行full GC;

          f、full GC后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”:

                                   outOfMemoryError:java heap space

 

代码举例:

 

Java代码   收藏代码
  1. <span style="font-size: 11px;">/** 
  2. * 堆内存溢出 
  3. * 
  4. * jvm参数:-Xms5m -Xmx5m -Xmn2m -XX:NewSize=1m 
  5. * 
  6. */  
  7. public class MemoryLeak {  
  8.      
  9.     private String[] s = new String[1000];  
  10.    
  11.     public static void main(String[] args) throws InterruptedException {  
  12.         Map<String,Object> m =new HashMap<String,Object>();  
  13.         int i =0;  
  14.         int j=10000;  
  15.         while(true){  
  16.             for(;i<j;i++){  
  17.                 MemoryLeak memoryLeak = new MemoryLeak();  
  18.                 m.put(String.valueOf(i), memoryLeak);  
  19.             }  
  20.         }  
  21.     }  
  22. }</span>  

 

 

           

2、方法区内存溢出outOfMemoryError:permgem space

       在jvm规范中,方法区主要存放的是类信息、常量、静态变量等。

       所以如果程序加载的类过多,或者使用反射、gclib等这种动态代理生成类的技术,就可能导致该区发生内存溢出,一般该区发生内存溢出时的错误信息为:

             outOfMemoryError:permgem space

 

代码举例:

 

Java代码   收藏代码
  1. <span style="font-size: 11px;">jvm参数:-XX:PermSize=2m -XX:MaxPermSize=2m  
  2.   
  3. 将方法区的大小设置很低即可,在启动加载类库时就会出现内存不足的情况</span>  

 

 

 

3、线程栈溢出java.lang.StackOverflowError

       线程栈时线程独有的一块内存结构,所以线程栈发生问题必定是某个线程运行时产生的错误。

       一般线程栈溢出是由于递归太深或方法调用层级过多导致的。

       发生栈溢出的错误信息为:

              java.lang.StackOverflowError

 

代码举例:

 

Java代码   收藏代码
  1. <span style="font-size: 11px;">/** 
  2. * 线程操作栈溢出 
  3. * 
  4. * 参数:-Xms5m -Xmx5m -Xmn2m -XX:NewSize=1m -Xss64k 
  5. * 
  6. */  
  7. public class StackOverflowTest {  
  8.      
  9.     public static void main(String[] args) {  
  10.         int i =0;  
  11.         digui(i);  
  12.     }  
  13.      
  14.     private static void digui(int i){  
  15.         System.out.println(i++);  
  16.         String[] s = new String[50];  
  17.         digui(i);  
  18.     }  
  19.   
  20. }  
  21. </span>  

 

 

 

 

五、为了避免内存泄露,在编写代码的过程中可以参考下面的建议:

 

1、尽早释放无用对象的引用

 

2、使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域

 

3、尽量少用静态变量,因为静态变量存放在永久代(方法区),永久代基本不参与垃圾回收

 

4、避免在循环中创建对象

 

5、开启大型文件或从数据库一次拿了太多的数据很容易造成内存溢出,所以在这些地方要大概计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。 

 

参考:

 

http://zhidao.baidu.com/question/263477119.html    

https://www.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/  Java的内存泄漏

http://jelly-x.iteye.com/blog/1120406 JVM内存分析及导致内存溢出

 

http://wenku.baidu.com/view/ef3158fc04a1b0717fd5ddda.html java内存泄露和内存溢出

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327078461&siteId=291194637