`
rq2_79
  • 浏览: 234962 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java内存溢出类型

    博客分类:
  • java
 
阅读更多

一、内存溢出类型

  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 的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。

分享到:
评论

相关推荐

    Java内存溢出

    Java内存溢出类型及java内存溢出解决办法

    关于java堆内存溢出的几种情况

     java.lang.OutOfMemoryError: Java heap space:这种是java堆内存不够,一个原因是真不够,另一个原因是程序中有死循环;  如果是java堆内存不够的话,可以通过调整JVM下面的配置来解决:  <jvm>-Xms3062m ...

    java内存溢出

    Java是如何管理内存 为了判断Java中是否有内存泄露,我们首先...在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。

    Java内存区域与内存溢出

     Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区。下面详细...

    java内存分配详解

    Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的 栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当...

    Java 内存区域与内存溢出

     Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器,Java虚拟机栈,本地方法栈,Java堆,方法区。下面详细...

    java核心面试技术点

    栈内存:存放对象:函数中基本类型的变量和对象的引用变量、静态类方法 ;特点:栈有一个很重要的特殊性,就是存在栈中的数据可以共享。 堆内存:存放对象:用来存放由new创建的对象和数组;特点:在堆中分配的...

    Java 自学宝典 第二章 数据类型

    Java的整数数据类型:内存和长度 12 2. 3. 2. 整数计算 12 2. 3. 3. 二进制和十进制值表 12 2. 3. 4. 十六进制数和相应的十进制和二进制值 13 2. 4. 字节 13 2. 4. 1.使用字节数据类型 13 2. 5. Short 14 2. 5. 1. ...

    java核心面试

    栈内存:存放对象:函数中基本类型的变量和对象的引用变量、静态类方法 ;特点:栈有一个很重要的特殊性,就是存在栈中的数据可以共享。 堆内存:存放对象:用来存放由new创建的对象和数组;特点:在堆中分配的...

    125集专攻JAVA基础 JAVA零基础入门学习视频教程 动力节点JAVA视频教程.txt

    北京动力节点-Java编程零基础教程-122-Java基本语法-方法递归调用-栈溢出错误.avi 北京动力节点-Java编程零基础教程-123-Java基本语法-方法递归调用-不使用递归解决阶乘问题.avi 北京动力节点-Java编程零基础教程...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    第2章 Java内存区域与内存溢出异常 / 24 2.1 概述 / 24 2.2 运行时数据区域 / 25 2.2.1 程序计数器 / 25 2.2.2 Java虚拟机栈 / 26 2.2.3 本地方法栈 / 27 2.2.4 Java堆 / 27 2.2.5 方法区 / 28 2.2.6 运行...

    Java开发技术大全(500个源代码).

    overflowExample.java 演示溢出 precedence.java 演示自加运算符的优先级 primeNumber.java 输出100-200之间的所有素数 ranking.java 评定成绩等级 rankingBySwitch.java 用switch语句评定成绩等级 ...

    Java GC笔记总纲1

    1 . 1 常见的内存溢出 1 . 2 内存溢出的常见原因 1 . 3 系统的线程划分 1 .4 Java 的四种引用类型 2 . 2 内存堆 2 . 3 内存

    Java虚拟机

    第2章 Java内存区域与内存溢出异常 2.1 概述 2.2 运行时数据区域 2.2.1 程序计数器 2.2.2 Java虚拟机栈 2.2.3 本地方法栈 2.2.4 Java堆 2.2.5 方法区 2.2.6 运行时常量池 2.2.7 直接内存 2.3 HotSpot...

    Java 导出大批量数据excel(百万级).pdf

    目前java框架中能够生成excel文件的的确不少,但是,能够生成大数据量的excel框架,我倒是没发现,一般数据量大了都会出现内存溢出,所以,生成大数据量的excel文件要返璞归真,用java的基础技术,IO流来实现。...

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第4节jvm初体验-内存溢出问题的分析与解决 [免费观看] 00:17:59分钟 | 第5节jvm再体验-jvm可视化监控工具 [免费观看] 00:21:17分钟 | 第6节杂谈 [免费观看] 00:12:37分钟 | 第7节Java的发展历史00:27:24分钟 | ...

    Java常见面试问题整理.docx

    线程共享:异常:OOM 内存溢出 1.Java堆:对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,...

    java编程常见问题

    33.java.lang.OutOfMemoryError 内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。 34.java.lang.StackOverflowError 堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出时抛出该...

    JAVA面试题最全集

    1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别。 2.字符串的操作: 写一个方法,实现字符串的反转,如:输入abc,输出cba 写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出...

    java 面试题 总结

    比如说内存溢出。不可能指望程序能处理这样的情况。 exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。 16、同步和异步有何异同,在什么情况下分别使用他们?举例说明。 ...

Global site tag (gtag.js) - Google Analytics