精华内容
下载资源
问答
  • 内存泄露和内存溢出

    2019-10-09 03:43:58
    不过他们还真有点关系,一般来说,内存泄露内存溢出的一个原因之一,当然,内存溢出还有很多原因。 内存泄露:是指程序在运行过程中动态申请的内存空间不再使用后没有及时释放,从而很可能导致应用程序内存无限...

    在以前我潜意思里面一直觉得内存溢出和内存泄露是一个意思...今天有人拿这个来问我,我才想起来这两个是有点区别的,真是有点不好意思哈哈。

    不过他们还真有点关系,一般来说,内存泄露是内存溢出的一个原因之一,当然,内存溢出还有很多原因。

     

    内存泄露:是指程序在运行过程中动态申请的内存空间不再使用后没有及时释放,从而很可能导致应用程序内存无限增长。更广义的内存泄露包括未对系统的资源的及时释放,比如不会再用的引用。

     

    内存溢出:用户在对其数据缓冲区操作时,超过了其缓冲区的边界;尤其是对缓冲区写操作时,缓冲区的溢出很可能导致程序的异常。

     

    内存泄露的原因

    1.数据库的cursor没有关闭。  
    操作Sqlite数据库时,Cursor是数据库表中每一行的集合,Cursor提供了很多方法,可以很方便的读取数据库中的值, 
    可以根据索引,列名等获取数据库中的值,通过游标的方式可以调用moveToNext()移到下一行 
    当我们操作完数据库后,一定要记得调用Cursor对象的close()来关闭游标,释放资源。 
    2.构造adapter没有使用缓存contentview。 
    在继承BaseAdapter时会让我们重写getView(int position, View   convertView, ViewGroup parent)方法, 
    第二个参数convertView就是我们要用到的重用的对象 

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        ViewHolder vHolder = null;  
                   //如果convertView对象为空则创建新对象,不为空则复用  
        if (convertView == null) {  
            convertView = inflater.inflate(..., null);  
            // 创建 ViewHodler 对象  
            vHolder = new ViewHolder();  
            vHolder.img= (ImageView) convertView.findViewById(...);  
            vHolder.tv= (TextView) convertView  
                    .findViewById(...);  
            // 将ViewHodler保存到Tag中  
            convertView.setTag(vHolder);  
        } else {  
                           //当convertView不为空时,通过getTag()得到View  
            vHolder = (ViewHolder) convertView.getTag();  
        }  
        // 给对象赋值,修改显示的值  
        vHolder.img.setImageBitmap(...);  
        vHolder.tv.setText(...);  
        return convertView;  
    }  
           //将显示的View 包装成类  
    static class ViewHolder {  
        TextView tv;  
        ImageView img;  
    }  

    这里只讲使用方法,具体性能测试文章请见: 

    ListView中getView的原理+如何在ListView中放置多个item 
    http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 
    Android开发之ListView适配器(Adapter)优化 
    http://shinfocom.iteye.com/blog/1231511 
    3.调用registerReceiver()后未调用unregisterReceiver(). 
    广播接收者(BroadcastReceiver)经常在应用中用到,可以在多线程任务完成后发送广播通知UI更新,也可以接收系统广播实现一些功能 
    可以通过代码的方式注册: 
    IntentFilter postFilter = new IntentFilter(); 
    postFilter.addAction(getPackageName() + ".background.job"); 
    this.registerReceiver(receiver, postFilter); 
    当我们Activity中使用了registerReceiver()方法注册了BroadcastReceiver,一定要在Activity的生命周期内调用unregisterReceiver()方法取消注册 
    也就是说registerReceiver()和unregisterReceiver()方法一定要成对出现,通常我们可以重写Activity的onDestory()方法: 

    @Override  
    protected void onDestroy() {  
          this.unregisterReceiver(receiver);  
          super.onDestroy();  
    }  

    4.未关闭InputStream/OutputStream。 
    这个就不多说了,我们操作完输入输出流都要关闭流 


    5.Bitmap使用后未调用recycle()。 
    图片处理不好是造成内存溢出的又一个头号原因,(在我们的产品中也有体现), 
    当我们处理完图片之后可以通过调用recycle()方法来回收图片对象 

    if(!bitmap.isRecycled())  
    {  
        bitmap.recycle()  
    } 

    除此之外: 
    直接使用ImageView显示bitmap会占用较多资源,特别是图片较大的时候,可能导致崩溃。 
    使用BitmapFactory.Options设置inSampleSize, 这样做可以减少对系统资源的要求。 
    属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。 
    BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();  
    bitmapFactoryOptions.inJustDecodeBounds = true;  
    bitmapFactoryOptions.inSampleSize = 2;  
    // 这里一定要将其设置回false,因为之前我们将其设置成了true  
    // 设置inJustDecodeBounds为true后,decodeFile并不分配空间,即,BitmapFactory解码出来的Bitmap为Null,但可计算出原始图片的长度和宽度  
    options.inJustDecodeBounds = false; 
    Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, options);  
    6.Context泄漏。 
        这是一个很隐晦的OutOfMemoryError的情况。先看一个Android官网提供的例子: 

    private static Drawable sBackground;  
    @Override  
    protected void onCreate(Bundle state) {  
      super.onCreate(state);  
      
      TextView label = new TextView(this);  
      label.setText("Leaks are bad");  
      
      if (sBackground == null) {  
        sBackground = getDrawable(R.drawable.large_bitmap);  
      }  
      label.setBackgroundDrawable(sBackground);  
      
      setContentView(label);  
    }  

    这段代码效率很快,但同时又是极其错误的; 

    在第一次屏幕方向切换时它泄露了一开始创建的Activity。当一个Drawable附加到一个 View上时, 
    View会将其作为一个callback设定到Drawable上。上述的代码片段,意味着Drawable拥有一个TextView的引用, 
    而TextView又拥有Activity(Context类型)的引用,换句话说,Drawable拥有了更多的对象引用。即使Activity被 销毁,内存仍然不会被释放。 
    另外,对Context的引用超过它本身的生命周期,也会导致Context泄漏。所以尽量使用Application这种Context类型。 
    这种Context拥有和应用程序一样长的生命周期,并且不依赖Activity的生命周期。如果你打算保存一个长时间的对象, 
    并且其需要一个 Context,记得使用Application对象。你可以通过调用Context.getApplicationContext()或 Activity.getApplication()轻松得到Application对象。 
    最近遇到一种情况引起了Context泄漏,就是在Activity销毁时,里面有其他线程没有停。 
    总结一下避免Context泄漏应该注意的问题: 
    1.使用Application这种Context类型。 
    2.注意对Context的引用不要超过它本身的生命周期。 
    3.慎重的使用“static”关键字。 
    4.Context里如果有线程,一定要在onDestroy()里及时停掉。 
    7.static关键字 
    当类的成员变量声明成static后,它是属于类的而不是属于对象的,如果我们将很大的资源对象(Bitmap,context等)声明成static,那么这些资源不会随着对象的回收而回收, 
    会一直存在,所以在使用static关键字定义成员变量的时候要慎重。

     

    引用地址:http://zhanhao.iteye.com/blog/1463350

    转载于:https://www.cnblogs.com/ian-fix/p/3897913.html

    展开全文
  • 主要从以下几部分来说明,关于内存和内存泄露、溢出的概念,区分内存泄露和内存溢出;内存的区域划分,了解GC回收机制;重点关注如何去监控和发现内存问题;此外分析出问题还要如何解决内存问题。下面就开始本篇的...
  • 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
    内存泄露、内存溢出
    

    · 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用的情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。 

    · 内存泄漏可以分为4类: 

    1) 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

    2) 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

    3) 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。

    4) 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

    · 内存溢出类型

    1) java.lang.OutOfMemoryError: PermGen space

    PermGen space 的全称是 Permanent Generation space, 是指内存的永久保存区域。这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC不会在主程序运行期对PermGen space进行清理。

     

    JVM由XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;

    JVM由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

     

    该错误常见场合:

    a) 应用中有很多Class,web服务器对JSP进行pre compile时。

    b) Webapp下用了大量的第三方jar, 其大小超过了JVM默认的大小(4M)时。

     

    2) java.lang.OutOfMemoryError: Java heap space

     

    在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

    JVM初始分配的内存由-Xms指定,默认是物理内存的1/64; 

    JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。 

    JVM内存的最大值跟操作系统有很大的关系。32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。

    注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。 

    该错误常见场合:

    a) Web上传文件时。

    b) 开启大型文件或从数据库中一次取了太多的数据。 
     

     

    相关问题

    1. Q: Java中会存在内存泄漏吗?
        A:  Java中也存在内存泄露。当被分配的对象可达但已无用(未对作废数据内存单元的引用置null)即会引起。

             如:

    Java代码 

    1. Vector v=new Vector(10);    

    2. for (int i=1;i<100; i ) {    

    3.     Object o=new Object();    

    4.     v.add(o);    

    5.     o=null;    

    6. }    

    7. // 此时,所有的Object对象都没有被释放,因为变量v引用这些对象。    

    8. // 对象加入到Vector后,还必须从Vector中删除,最简单释放方法就是将Vector对象设置为null。   

    Vector v=new Vector(10); for (int i=1;i<100; i ) { Object o=new Object(); v.add(o); o=null; } // 此时,所有的Object对象都没有被释放,因为变量v引用这些对象。 // 对象加入到Vector后,还必须从Vector中删除,最简单释放方法就是将Vector对象设置为null。

     

     

    2. Q: 内存泄露、溢出的异同? 

         A: 同:都会导致应用程序运行出现问题,性能下降或挂起。

             异:

             1) 内存泄露是导致内存溢出的原因之一;内存泄露积累起来将导致内存溢出。

             2) 内存泄露可以通过完善代码来避免;内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。

            

     

    3. Q:如何检测内存泄露?   

     

         A: 可以通过一些性能监测分析工具,如 JProfiler、Optimizeit Profiler。

     

    4. Q: 如何避免内存泄露、溢出?
         A: 1) 尽早释放无用对象的引用。

              好的办法是使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

              2) 程序进行字符串处理时,尽量避免使用String,而应使用StringBuffer。

              因为每一个String对象都会独立占用内存一块区域,如:

     

    Java代码 

    1. String str = "aaa";    

    2. String str2 = "bbb";    

    3. String str3 = str   str2;    

    4. // 假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收;    

    5. // 假如程序中存在过多的类似情况就会出现内存错误;   

    String str = "aaa"; String str2 = "bbb"; String str3 = str str2; // 假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收; // 假如程序中存在过多的类似情况就会出现内存错误;

     

     

             3) 尽量少用静态变量。

             因为静态变量是全局的,GC不会回收。

             4) 避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。

             JVM会突然需要大量内存,这时会触发GC优化系统内存环境; 一个案例如下: 

     

    Java代码 

    1. // 使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误,    

    2. // 检查之后发现问题:组件里的代码    

    3. m_totalBytes = m_request.getContentLength();    

    4. m_binArray = new byte[m_totalBytes];    

    5. // totalBytes这个变量得到的数极大,导致该数组分配了很多内存空间,而且该数组不能及时释放。    

    6. // 解决办法只能换一种更合适的办法,至少是不会引发outofMemoryError的方式解决。    

    7. // 参考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747   

    // 使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误, // 检查之后发现问题:组件里的代码 m_totalBytes = m_request.getContentLength(); m_binArray = new byte[m_totalBytes]; // totalBytes这个变量得到的数极大,导致该数组分配了很多内存空间,而且该数组不能及时释放。 // 解决办法只能换一种更合适的办法,至少是不会引发outofMemoryError的方式解决。 // 参考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747

       

     

            5) 尽量运用对象池技术以提高系统性能。

             生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

             6) 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。

             可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃。

             7) 优化配置。

     

     

     

     

    5. Q: 内存溢出的解决方案? 
         A: 一是从代码层面进行优化完善,尽量避免该情况发生;

             二是调整优化服务器配置: 

             1) 设置-Xms、-Xmx相等;

             2) 设置NewSize、MaxNewSize相等;

             3) 设置Heap size, PermGen space:

                 Tomcat 的配置示例:修改 %TOMCAT_HOME%/bin/catalina.bat or catalina.sh

                 在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:

                

    Cmd代码 

    1. set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m  

    -----------------------------/

    内存泄露与溢出区别,何时产生内存泄露?



    下面,我们就可以描述什么是内存泄漏。在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。 

    在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。 

    通过分析,我们得知,对于C++,程序员需要自己管理边和顶点,而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式,Java提高了编程的效率。 


    因此,通过以上分析,我们知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语言上保证,任何对象都是可达的,所有的不可达对象都由GC管理。 

    对于程序员来说,GC基本是透明的,不可见的。虽然,我们只有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义, 该函数不保证JVM的垃圾收集器一定会执行。因为,不同的JVM实现者可能使用不同的算法管理GC。通常,GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存,例如将垃圾回收分解为一系列的小步骤执行,Sun提供的HotSpot JVM就支持这一特性。 

    下面给出了一个简单的内存泄露的例子。在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个Vector中,如果我们仅仅释放引用本身,那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。 

    Java代码  

    1. Vector v=new Vector(10);   

    2. for (int i=1;i<100; i++)   

    3. {   

    4.     Object o=new Object();   

    5.     v.add(o);   

    6.     o=null;    

    7. }   

    Vector v=new Vector(10);

    for (int i=1;i<100; i++)

    {

    Object o=new Object();

    v.add(o);

    o=null;


    //此时,所有的Object对象都没有被释放,因为变量v引用这些对象 

    怎样解决内存溢出

     一、内存溢出类型

      1、java.lang.OutOfMemoryError: PermGen space

      JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。

      PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

      一个最佳的配置例子:(经过本人验证,自从用此配置之后,再未出现过tomcat死掉的情况)

      set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

      2、java.lang.OutOfMemoryError: Javaheap space

      第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40%,JVM就会增大堆到Xmx设置的值,内存剩余超过70%,JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。假设物理内存无限大,那么JVM内存的最大值跟操作系统有关,一般32位机是1.5g到3g之间,而64位的就不会有限制了。

      注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

      垃圾回收GC的角色

      JVM调用GC的频度还是很高的,主要两种情况下进行垃圾回收:

      当应用程序线程空闲;另一个是java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。

      根据GC的机制,程序的运行会引起系统运行环境的变化,增加GC的触发机会。

      为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和GC的开销。显示调用System.GC()只能建议JVM需要在内存中对垃圾对象进行回收,但不是必须马上回收,

      一个是并不能解决内存资源耗空的局面,另外也会增加GC的消耗。

      二、JVM内存区域组成

      简单的说java中的堆和栈

      java把内存分两种:一种是栈内存,另一种是堆内存

      1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;

      2。堆内存用来存放由new创建的对象和数组

      在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理

      堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;

      栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。

      java堆分为三个区:New、Old和Permanent

      GC有两个线程:

      新创建的对象被分配到New区,当该区被填满时会被GC辅助线程移到Old区,当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn

      java栈存放

      栈调整:参数有+UseDefaultStackSize -Xss256K,表示每个线程可申请256k的栈空间

      每个线程都有他自己的Stack

      三、JVM如何设置虚拟内存

      提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

      提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

      提示:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。

      默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

      提示:假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。

      简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,

      这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了

      提示:注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

      提示:设置NewSize、MaxNewSize相等,"new"的大小最好不要大于"old"的一半,原因是old区如果不够大会频繁的触发"主" GC ,大大降低了性能

      JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;

      由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

      解决方法:手动设置Heap size

      修改TOMCAT_HOME/bin/catalina.bat

      在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:

      JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"

      四、性能检查工具使用

      定位内存泄漏:

      JProfiler工具主要用于检查和跟踪系统(限于Java开发的)的性能。JProfiler可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视JVM运行情况及其性能。

      1. 应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位;

      2. 应用服务器极为不稳定,几乎每两天重新启动一次,有时甚至每天重新启动一次;

      3. 应用服务器经常做Full GC(Garbage Collection),而且时间很长,大约需要30-40秒,应用服务器在做Full GC的时候是不响应客户的交易请求的,非常影响系统性能。

      因为开发环境和产品环境会有不同,导致该问题发生有时会在产品环境中发生,通常可以使用工具跟踪系统的内存使用情况,在有些个别情况下或许某个时刻确实是使用了大量内存导致out of memory,这时应继续跟踪看接下来是否会有下降,

      如果一直居高不下这肯定就因为程序的原因导致内存泄漏。

      五、不健壮代码的特征及解决办法

      1、尽早释放无用对象的引用。好的办法是使用临时变量的时候,让引用变量在退出活动域后,自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

      对于仍然有指针指向的实例,jvm就不会回收该资源,因为垃圾回收会将值为null的对象作为垃圾,提高GC回收机制效率;

      2、我们的程序里不可避免大量使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域;

      String str = "aaa";

      String str2 = "bbb";

      String str3 = str + str2;//假如执行此次之后str ,str2以后再不被调用,那它就会被放在内存中等待Java的gc去回收,程序内过多的出现这样的情况就会报上面的那个错误,建议在使用字符串时能使用StringBuffer就不要用String,这样可以省不少开销;

      3、尽量少用静态变量,因为静态变量是全局的,GC不会回收的;

      4、避免集中创建对象尤其是大对象,JVM会突然需要大量内存,这时必然会触发GC优化系统内存环境;显示的声明数组空间,而且申请数量还极大。

      这是一个案例想定供大家警戒

      使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误,

      检查之后发现问题:组件里的代码

      m_totalBytes = m_request.getContentLength();

      m_binArray = new byte[m_totalBytes];

      问题原因是totalBytes这个变量得到的数极大,导致该数组分配了很多内存空间,而且该数组不能及时释放。解决办法只能换一种更合适的办法,至少是不会引发outofMemoryError的方式解决。参考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747

      5、尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

      6、不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃

      7、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out Of Memory Error 的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值

    展开全文
  • 1、内存泄露:是指程序在申请内存后,无法释放已申请内存空间,一次内存泄漏似乎不会有大影响,但内存泄漏堆积后后果就是内存溢出。 2、内存溢出:指程序申请内存时,没有足够内存供申请者使用,或者说,给...

    1、内存泄露:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

    2、内存溢出:指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

    3、二者的关系:

    1、内存泄漏的堆积最终会导致内存溢出
    2、内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。
    3、内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。就相当于你租了个带钥匙的柜子,你存完东西之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么结果就是这个柜子将无法供给任何人使用,也无法被垃圾回收器回收,因为找不到他的任何信息。
    4、内存溢出:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错。
    4、内存溢出的原因及解决方法:

    (1) 内存溢出原因:

    1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
    2. 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
    3. 代码中存在死循环或循环产生过多重复的对象实体;
    4. 使用的第三方软件中的BUG;
    5. 启动参数内存值设定的过小

    (2)内存溢出的解决方案:

    第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)

    第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。

    第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。 
    重点排查以下几点: 
    1.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

    2.检查代码中是否有死循环或递归调用。

    3.检查是否有大循环重复产生新对象实体。

    4.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

    第四步,使用内存查看工具动态查看内存使用情况

    原文:https://blog.csdn.net/mashuai720/article/details/79557670 
     

     

     

    展开全文
  • 内存溢出和内存泄露

    2021-03-24 19:57:30
    内存泄露是指某个程序在申请了一些内存之后,长时间占用,无法释放已经申请内存空间,一次的内存泄露没有什么大影响,但是当多次内存泄露堆积起来就发展成了内存溢出(out of memory) **内存溢出(out of ...

    内存泄露是指某个程序在申请了一些内存之后,长时间占用,无法释放已经申请的内存空间,一次的内存泄露没有什么大的影响,但是当多次内存泄露堆积起来就发展成了内存溢出(out of memory)
    **内存溢出(out of memory)**指的是在程序申请内存的时候,没有足够的内存空间给他;或者需要的是int类型的数,却放入了long类型的数。这些情况都会报错的;
    二者的关系

    内存泄漏的堆积最终会导致内存溢出
    内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。
    内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

    内存溢出:比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错。

    展开全文
  • 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
  • 一:定义内存泄漏:(Memory Leak) 不再会被使用对象内存不能被回收,就是内存泄露强引用所指向对象不会被回收,可能导致内存泄漏,虚拟机宁愿抛出OOM也不会去回收他指向对象意思就是你用资源时候为他开辟了...
  • 在用C++做底层驱动时,经常会遇到内存不足警告,往往是因为内存出现溢出、泄露或者越界等原因。...二者关系:内存泄漏堆积最终会导致内存溢出内存溢出,就是你要内存空间超过了系统实际分配给你...
  • 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
  • 内存泄露内存溢出

    2017-08-14 09:23:43
    内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
  • 程序在运行时候一般分配数据堆,把局部临时变量都放进去,生命周期进程有关系。但是如果程序员声明了static变量,就直接在栈中运行,进程销毁了,不一定会销毁static变量。  另外为了保证java内存不...
  • 一 内存泄漏和内存溢出分别是什么?它们有什么关系? 1.内存泄露是指保存了不可能再被访问变量引用,导致垃圾回收器无法回收内存。 也就是说:在Java中有些对象生命周期是有限,当它们完成了特定逻辑后...
  • 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
  • 方法区、栈、堆三者的关系 方法区如果保存了过多的类就会导致OOM 比如1、加载了大量的第三方jar包 2、tomcat服务器部署了过多工程(30-50个) 3、大量动态生成反射类 hotspot方法区的演进 如果方法区是接口,那么...
  • Java基础恶补——内存泄露内存溢出

    万次阅读 多人点赞 2013-11-19 09:29:28
    内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起。...
  • 程序在运行时候一般分配数据堆,把局部临时变量都放进去,生命周期进程有关系。但是如果程序员声明了static变量,就直接在栈中运行,进程销毁了,不一定会销毁static变量。  另外为了保证java
  • 内存溢出OOM区别内存问题常发生区域说明:堆内存配置参数-Xms,-Xmx不能配置太小,配置太小话,程序运行一段时间可能导致内存溢出------出现内存问题概率较大进程内存出现问题:开发沟通减少启动进程...
  • 内存溢出并不一定跟内存分配有什么关系,因为还有一种情况是缓冲区溢出。 内存泄露 memory leak 是指程序在申请内存后,无法释放已申请内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无
  • 内存泄露是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是...
  • 内存溢出 泄露

    2017-05-23 17:52:00
    泄露:软件设计上的问题,硬件没有关系内存泄露可以通过完善代码来避免;内存泄露积累起来将导致内存溢出。 Q:内存溢出的解决方案?A:一是从代码层面进行优化完善,尽量避免该情况发生; 二是调整优化...

空空如也

空空如也

1 2 3 4
收藏数 78
精华内容 31
关键字:

内存泄露和内存溢出的关系