内存泄露与内存溢出

Posted yumingxing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存泄露与内存溢出相关的知识,希望对你有一定的参考价值。

一、什么是内存泄露

内存泄露是指一个不在被程序使用的对象或变量还在内存中占有存储空间。

1. 内存泄露主要有两种情况:

       (1). 在堆中申请的空间没有释放

       (2.) 该对象已经不再使用,却还在内存中保留着

一般垃圾回收机制可以有效的解决第一种情况。

Java内存泄露主要是第二种情况。

1 Vector v = new Vector();
2 for ( int i=0 ;i<10; i++ ){
3     Object o = new Object();
4     v.add(o);
5 }

在循环中不断创建对象加入到Vector对象中,退出循环后o的作用域将会结束,

在v中使用这些对象,垃圾回收器无法回收,造成内存泄露。只有将这些对象从

vector中删除才能释放这些对象。

2. 泄露原因

(1)静态集合类。例如 HashMap 和 Vector 。如果这些容器为静态的static,他们

的生命周期和程序一致,那么容器中的对象在程序结束之前不能被释放,从而造成

内存泄露。也就是长生命周期对象持有短生命周期的对象。

(2)各种连接。如数据库连接、IO连接、网络连接等。需要先建立连接,不使用时

要使用 close() 释放连接,只有关闭连接后垃圾回收器才会回收对应的对象,否则会

有大量对象无法回收二造成内存泄露。

(3)监听器。通常一个应用中用到多个监听器,当释放对象时,往往没有删除相应

的监听器,而造成内存泄露。

(4)变量作用域不合理。如果一个变量的作用域大于其使用的范围,可能会造成内

存泄露。如:

1 Class Server{
2      private String msg;
3      public void receiveMsg(){
4          readFromNet();//从网络中接收msg
5          saveDB();//保存msg到数据库
6     }
7 }

从网络中接收msg然后保存到数据库之后msg就没用了,但是msg生命周期和对象的

生命周期相同,所以不会立刻被回收,造成内存泄露。

(5)单例模式可能会造成内存泄露。

 1 public class BigClass{
 2   //code
 3 }
 4 public class Singleton {
 5     private Singleton(BigClass bc){
 6         this.bc = bc;
 7     }
 8     private BigClass bc;
 9     private static Singleton instance = new Singleton(new BigClass());
10     public Singleton getInstance(){
11         return instance;
12     }
13 }

单例模式Singleton存在一个对对象 bc 的引用,但是单例instance对象以静态方式存储,它

在JVM整个生命周期都存在,bc无法被回收,导致内存泄露。

3. 内存泄露的解决方案:

(1)避免在循环中创建对象

(2)最早释放无用对象

(3)尽量少用静态变量,因为静态变量在永久代,很少参加垃圾回收。

(4)使用字符串处理避免使用String,而用StringBuffer。

4.如何查找内存泄露

使用Jconsole。

二、什么是内存溢出

指的是程序运行过程中无法申请到足够的内存空间而导致的一种错误。

1. 内存溢出的几种情况:

除了程序计数器外,虚拟机其他几个运行时区域都可能发生OutOfMemorryError(OOM)异常。

 

(1)虚拟机栈和本地方法栈溢出

  如果线程请求的栈深度大于虚拟机所允许的最大深度, 将抛出
  StackOverflowError 异常。
  如果虚拟机在扩展栈时无法申请到足够的内存空间, 则抛出
  OutOfMemoryError 异常。

(2)堆溢出

  一般的异常信息:java.lang.OutOfMemoryError:Java heap spaces。

  检查虚拟机的参数(-Xmx 与-Xms)的设置是否适当

(3)方法区溢出
  异常信息:java.lang.OutOfMemoryError:PermGen space。
(4)运行时常量池溢出
  异常信息:java.lang.OutOfMemoryError:PermGen space。
  如果要向运行时常量池中添加内容, 最简单的做法就是使用
  String.intern()这个Native 方法。该方法的作用是:如果池中已经包含一个
  等于此String 的字符串,则返回代表池中这个字符串的String 对象;否则,
  将此String 对象包含的字符串添加到常量池中,并且返回此String 对象的引
  用。

 












以上是关于内存泄露与内存溢出的主要内容,如果未能解决你的问题,请参考以下文章

内存泄露与内存溢出

Java学习---内存泄露与溢出的区别

Andorid 内存溢出与内存泄露,几种常见导致内存泄露的写法

内存泄露与内存溢出的区别

Andfroid 内存溢出与内存泄漏的简单分析与解决

转载:内存泄露与内存溢出的区别