java memory 泄露 溢出

要点java

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

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

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

3) 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者因为算法上的缺陷,致使总会有一块仅且一块内存发生泄漏。好比,在类的构造函数中分配内存,在析构函数中却没有释放该内存,因此内存泄漏只会发生一次。数据库

4) 隐式内存泄漏。程序在运行过程当中不停的分配内存,可是直到结束的时候才释放内存。严格的说这里并无发生内存泄漏,由于最终程序释放了全部申请的内存。可是对于一个服务器程序,须要运行几天,几周甚至几个月,不及时释放内存也可能致使最终耗尽系统的全部内存。因此,咱们称这类内存泄漏为隐式内存泄漏。数组

  • 内存溢出类型:

1) java.lang.OutOfMemoryError: PermGen spacetomcat

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

 

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

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

 

该错误常见场合:jsp

a) 应用中有不少Class,web服务器对JSP进行precompile时。

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。   

 

 

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

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

         异:

         1) 内存泄露是致使内存溢出的缘由之一;内存泄露积累起来将致使内存溢出。

         2) 内存泄露能够经过完善代码来避免;内存溢出能够经过调整配置来减小发生频率,但没法完全避免。

        

 

3. 如何检测内存泄露?   

 

     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. // 假如程序中存在过多的相似状况就会出现内存错误;   

 

         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   

   

 

        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  

 

怎样解决内存溢出

 

 1、内存溢出类型

  一、java.lang.OutOfMemoryError:PermGen space

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

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

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

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

  二、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的消耗。

  2、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

  3、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"

  4、性能检查工具使用

  定位内存泄漏:

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

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

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

  3. 应用服务器常常作Full GC(GarbageCollection),并且时间很长,大约须要30-40秒,应用服务器在作Full GC的时候是不响应客户的交易请求的,很是影响系统性能。

  由于开发环境和产品环境会有不一样,致使该问题发生有时会在产品环境中发生,一般可使用工具跟踪系统的内存使用状况,在有些个别状况下或许某个时刻确实是使用了大量内存致使out of memory,这时应继续跟踪看接下来是否会有降低,

  若是一直居高不下这确定就由于程序的缘由致使内存泄漏。

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

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

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

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

  String str = "aaa";

  String str2 = "bbb";

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

  三、尽可能少用静态变量,由于静态变量是全局的,GC不会回收的;

  四、避免集中建立对象尤为是大对象,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

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

  六、不要在常常调用的方法中建立对象,尤为是忌讳在循环中建立对象。能够适当的使用hashtable,vector 建立一组对象容器,而后从容器中去取那些对象,而不用每次new以后又丢弃

  七、通常都是发生在开启大型文件或跟数据库一次拿了太多的数据,形成 Out OfMemory Error 的情况,这时就大概要计算一下数据量的最大值是多少,而且设定所需最小及最大的内存空间值。

相关文章
相关标签/搜索