造成 OutOfMemoriError状况,一般都是发生在开启大型文件或跟数据库一次拿了太多的数据。这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。
1、java.lang.OutOfMemoryError:PermGenspace,堆是给开发人员用的上面说的就是JVM启动时创建;非堆是留给JVM自己用的用来存放类的信息的和堆不同,JVM管理两种类型的内存。运行期内GC不会释放空间。如果webapp用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermS设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热布置时侯不会清理前面加载的环境,只会将context更改为新部署的非堆存的内容就会越来越多。
这块内存主要是被JVM存放Class和Meta信息的,PermGenspace全称是PermanGenerspace,指内存的永久保管区域。Class被Loader时就会被放到PermGenspace中,和存放类实例(InstancHeap区域不同,GCGarbagCollect不会在主顺序运行期对PermGenspace进行清理,所以如果你应用中有很CLA SS话,就很可能出现PermGenspace错误,这种错误罕见在web服务器对JSP进行precompil时候。如果你WEBAPP下都用了大量的第三方jar,其大小超过了jvm默认的大小(4M那么就会发生此错误信息了
自从用此配置之后,一个最佳的配置例子:经过自己验证。再未出现过tomcat死掉的情况)
setJA VA _OPTS=-Xms800m-Xmx800m-XX:PermSize=128M-XX:MaxNewSize=256m-XX:MaxPermSize=256m
2、java.lang.OutOfMemoryError:Javaheapspace
其默认空间(即-Xm物理内存的1/64最大空间(-Xmx物理内存的1/4如果内存剩余不到40%,第一种情况是个补充。JVM就会增大堆到Xmx设置的值,内存剩余超越70%,JVM就会减小堆到Xm设置的值。所以服务器的Xmx和Xm设置一般应该设置相同防止每次GC后都要调整虚拟机堆的大小。假设物理内存无限大,那么JVM内存的最大值跟操作系统有关,一般32位机是1.5g3g之间,而64位的就不会有限制了
或者堆最大值和非堆最大值的总和超越了物理内存或者操作系统的最大限制都会引起服务器启动不起来。注意:如果Xm超越了Xmx值。
JVM调用GC频度还是很高的主要两种情况下进行垃圾回收:会不断调用GC若连续回收都解决不了内存堆不足的问题时,当应用顺序线程空闲;另一个是java内存堆不足时。就会报outofmemori错误。因为这个异常根据系统运行环境决定,所以无法预期它何时呈现。顺序的运行会引起系统运行环境的变化,根据GC机制增加GC触发机会。顺序的设计和编写就应防止垃圾对象的内存占用和GC开销。显示调用System.GC只能建议JVM需要在内存中对垃圾对象进行回收,为了防止这些问题。但不是必需马上回收,另外也会增加GC消耗。一个是并不能解决内存资源耗空的局面。
二、JVM内存区域组成
简单的说java中的堆和栈,另一种是堆内存java把内存分两种:一种是栈内存。函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;堆内存用来存放由new创立的对象和数组,java就在栈中为这个变量分配内存空间,函数(代码块)中定义一个变量时。当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;堆中分配的内存由java虚拟机的自动垃圾回收器来管理,生存期也不必事先告诉编译器,堆的优势是可以动态分配内存大小。因为它运行时动态分配内存的缺点就是要在运行时动态分配内存,存取速度较慢;缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。栈的优势是存取速度比堆要快。
java堆分为三个区:NewOld和Permanent
GC有两个线程:当该区被填满时会被GC辅助线程移到Old区,新创建的对象被分配到New区。当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn
java栈存放,栈调整:参数有+UseDefaultStackS-Xss256K表示每个线程可申请256k栈空间
每个线程都有他自己的Stack
提示:JVM中如果98%的时间是用于GC且可用的Heapsize缺乏2%的时候将抛出此异常信息。
一般的要将-Xm和-Xmx选项设置为相同,提示:HeapSize最大不要逾越可用物理内存的80%。而-Xmn为1/4-Xmx值。
默认是物理内存的1/64JVM最大分配的内存由-Xmx指定,提示:JVM初始分配的内存由-Xm指定。默认是物理内存的1/4
让引用变量在退出活动域后,1尽早释放无用对象的引用。好的方法是使用临时变量的时候。自动设置为null暗示垃圾收集器来收集该对象,防止发生内存泄露。
jvm就不会回收该资源,对于仍然有指针指向的实例。因为垃圾回收会将值为null对象作为垃圾,提高GC回收机制效率;
防止使用String应大量使用StringBuff每一个String对象都得独立占用内存一块区域;2顺序里不可防止大量使用字符串处理。
Stringstr="aaa";
Strstr2="bbb";
str2以后再不被调用,Stringstr3=str+str2;//假如执行此次之后str.那它就会被放在内存中等待Javagc去回收,顺序内过多的出现这样的情况就会报上面的那个错误,建议在使用字符串时能使用StringBuff就不要用String,这样可以省不少开销;
因为静态变量是全局的GC不会回收的3尽量少用静态变量。
JVM会突然需要大量内存,4防止集中创建对象尤其是大对象。这时肯定会触发GC优化系统内存环境;显示的声明数组空间,而且申请数量还极大。
这是一个案例想定供大家警戒
使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError错误。
检查之后发现问题:组件里的代码
m_totalByt=m_request.getContentLength;
m_binA rrai=newbyte[m_totalBytes];
导致该数组分配了很多内存空间,问题原因是totalByt这个变量得到数极大。而且该数组不能及时释放。解决方法只能换一种更合适的方法,至少是不会引发outofMemoryError方式解决。
JVM就会增大堆直到-Xmx最大限制;空余堆内存大于70%时,默认空余堆内存小于40%时。JVM会减少堆直到-Xm最小限制。因此服务器一般设置-Xm-Xmx相等以避免在每次GC后调整堆的大小。
JVM内存的最大值跟操作系统有很大的关系。提示:假设物理内存无限大的话。
简单的说就32位处置器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制。
这个限制一般是2GB-3GB一般来说Window系统下为1.5G-2GLinux系统下为2G-3G而64bit以上的处置器就不会有限制了
或者堆最大值和非堆最大值的总和超越了物理内存或者操作系统的最大限制都会引起服务器启动不起来。提示:注意:如果Xm超越了Xmx值。
"new"大小最好不要大于"old"一半,提示:设置NewSizMaxNewS相等。原因是old区如果不够大会频繁的触发"主"GC大大降低了性能
默认是物理内存的1/64JVM使用-XX:PermSiz设置非堆内存初始值。
默认是物理内存的1/4由XX:MaxPermS设置最大非堆内存的大小。
解决方法:手动设置Heapsize
修改TOMCA T_HOME/bin/catalina.bat
echo"UsingCA TA LINA _BA SE:$CA TA LINA _BA SE"上面加入以下行:
JA VA _OPTS="-server-Xms800m-Xmx800m-XX:MaxNewSize=256m"
定位内存泄漏:随时监视垃圾回收,JProfil工具主要用于检查和跟踪系统(限于Java开发的性能。JProfil可以通过时时的监控系统的内存使用情况。线程运行状况等手段,从而很好的监视JVM运行情况及其性能。内存经常处于高位占用,应用服务器内存临时不合理占用。很难回收到低位;几乎每两天重新启动一次,应用服务器极为不稳定。有时甚至每天重新启动一次;大约需要30-40秒,应用服务器经常做FullGCGarbagCollect而且时间很长。应用服务器在做FullGC时候是不响应客户的交易请求的非常影响系统性能。导致该问题发生有时会在产品环境中发生,因为开发环境和产品环境会有不同。通常可以使用工具跟踪系统的内存使用情况,有些个别情况下或许某个时刻确实是使用了大量内存导致outofmemori这时应继续跟踪看接下来是否会有下降。例如大集合对象拥有大数据量的业务对象的时候,尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏。可以考虑分块进行处理,然后解决一块释放一块的战略。尤其是忌讳在循环中创建对象。可以适当的使用hashtablvector创建一组对象容器,6不要在经常调用的方法中创建对象。然后冷静器中去取那些对象,而不用每次new之后又丢弃