Tomcat内存溢出分析及解决方法

第1篇:Tomcat内存溢出分析及解决方法

jvm管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在jvm启动时创建;非堆是留给jvm自己用的,用来存放类的信息的。它和堆不同,运行期内gc不会释放空间。

一、内存溢出类型

1、java.lang.outofmemoryerror:permgenspace

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

permgenspace的全称是permanentgenerationspace,是指内存的永久保存区域,这块内存主要是被jvm存放class和meta信息的,class在被loader时就会被放到permgenspace中,它和存放类实例(instance)的heap区域不同,gc(garbagecollection)不会在主程序运行期对permgenspace进行清理,所以如果你的应用中有很class的话,就很可能出现permgenspace错误,这种错误常见在web服务器对jsp进行prepile的时候。如果你的webapp下都用了大量的第三方jar,其大小超过了jvm默认的大小(4m)那么就会产生此错误信息了。

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

setjava_opts=-xms800m-xmx800m-xx:permsize=128m-xx:maxnewsize=256m-xx:maxpermsize=256m

在linux下在tomcathome/conf/catalina.sh中加上如标红所示的一句代码:可以增加tomcatjvm的内存,这样就不容易出现内存溢出的现象了!

#-----executetherequestedmand-----------------------------------------

java_opts="-server-xms512m-xmx2048m-xx:permsize=128m-xx:maxnewsize=256m-xx:maxpermsize=256m"

#bugzilla37848:onlyoutputthisifwehaveatty

2、java.lang.outofmemoryerror:javaheapspace

第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-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,若连续回收都解决不了内存堆不足的问题时,就会报outofmemory错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。

根据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且可用的heapsize不足2%的时候将抛出此异常信息。

提示:heapsize最大不要超过可用物理内存的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。

解决方法:手动设置heapsize

修改tomcat_home/bin/catalina.bat

在“echo"usingcatalina_base:$catalina_base"”上面加入以下行:

java_opts="-server-xms800m-xmx800m-xx:maxnewsize=256m"

第2篇:内存溢出的原因及解决方法

引起内存溢出的原因

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

2.*类中有对对象的引用,使用完后未清空,使得jvm不能回收;

3.代码中存在死循环或循环产生过多重复的对象实体;

4.使用的第三方软件中的bug;

5.启动参数内存值设定的过小

内存溢出的解决方案:

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

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

第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

重点排查以下几点:

1.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

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

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

4.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

5.检查list、map等*对象是否有使用完后,未清除的问题。list、map等*对象会始终存有对对象的引用,使得这些对象不能被gc回收。

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

第3篇:Windows内存出错的解决方法

计算机系统中运行一些容量较大的程序或者游戏时,系统常常会自动*出“xx内存不能为read或written”的错误提示,遇到这种故障信息时,我们该如何才能将它有效排除,下面是小编为大家整理的windows内存出错的解决方法,欢迎参考~

移除无效*件程序

在上网冲浪的过程中,许多*件程序会偷偷地安装到计算机系统中,而不少*件程序往往都有防删除的功能,因此这些*件很容易与其他的应用程序发生冲突,从而间接地引起系统内存读写错误的现象。为了给那些大容量的应用程序或游戏提供一个干净、稳定的工作环境,我们最好定期使用安全防护软件,来查看系统是否被偷偷安装了各种无效的垃圾*件程序,一旦发现的话,那可以直接将它们从系统中及时卸载干净。

手工修复系统服务

与系统内存读写*作有关的windowsmanagementinstrumentation服务要是发生错误的话,也会导致系统*出内存读写错误的提示,所以当我们遇到这种错误现象时,可以尝试手工修复一下windowsmanagementinstrumentation服务,下面就是具体的修复步骤:

首先,用鼠标右键单击系统桌面中的“我的电脑”图标,从*出的快捷菜单中执行“管理”命令,打开本地系统的计算机管理窗口,在该窗口的左侧显示区域,依次展开“服务和应用程序”/“服务”选项,在对应“服务”选项所在的右侧显示区域中,找到windowsmanagementinstrumentation服务,并用鼠标右键单击该服务选项,从*出的快捷菜单中执行“属*”命令,打开服务属*设置界面;

其次在该设置界面的“常规”标签页面中,单击“停止”按钮,将windowsmanagementinstrumentation服务暂时停止运行。之后,打开计算机系统的资源管理器窗口,在该窗口中依次展开“windows”、“system32”、“wbem”、“repository”文件夹,然后将“repository”文件夹窗口中的所有文件进行一下备份,备份完成后将该文件夹中的所有内容全部清除掉;

接下来,重新启动一下计算机系统,待系统启动成功后,按前面*作打开windowsmanagementinstrumentation服务的属*设置界面,单击该界面中的“启动”按钮,相信这么一来windowsmanagementinstrumentation服务就能正常运行了。

修复系统损坏文件

如果计算机系统不小心感染了病毒或者发生了误删除*作,那么与系统内存读写*作有关的系统文件很可能受到损坏,而这些系统文件一旦受到损坏的话,那么我们就很容易遭遇内存读写故障提示了。所以,我们一旦碰到内存读写错误的提示时,不妨按照如下步骤修复一下系统,看看系统是否存在损坏的文件:

首先使用最新版本的杀毒软件,来对计算机系统进行彻底地病毒查杀*作,因为计算机系统一旦感染了病毒而不进行清除的话,我们即使修复了系统文件,病毒仍然有可能会继续破坏系统文件,所以及时使用杀毒软件来将计算机中的病毒全部清除干净,可以确保系统文件不会继续受到病毒的威胁。

其次使用系统自带的“sfc”命令,来尝试将受到损坏的系统文件修复到正常状态。在修复受损系统文件时,只要在运行中输入“cmd”,打开“命令提示符”窗口,在其中输入字符串命令“sfc/scannow”,单击回车键后,该命令程序就会对系统每个角落处的系统文件进行搜索扫描,一旦发现系统文件的版本不正确或者系统文件已经损坏的话,它就能自动*出提示界面,要求我们*入windows系统的安装光盘,以便从中提取正常的系统文件来替代不正常的系统文件,从而达到修复系统文件的目的。要是系统修复*作成功的话,相信我们重新启动计算机系统时,就不会看到有什么不正常的现象了。

及时释放系统内存

我们知道,在运行一些容量较大的程序或者游戏时,需要消耗相当的系统内存资源,要是此时内存空间不够时,那么系统内存读写错误的故障提示很有可能就会发生。为了有效避免这种错误提示,我们最好在运行容量较大的程序或者游戏之前,应该先将计算机系统重新启动一下,这样能够将系统内存空间充分释放出来;如果计算机内存空间本身就比较小的话,那么我们建议各位最好及时升级内存,以便拓展内存的有效使用空间,以防止由于系统内存不足而造成系统内存读写错误的发生。

当然,在系统自身内存空间不足的情况下,我们应该先将那些随机启动的杀毒软件以及相关即时*的程序暂时关闭掉,之后再尝试运行容量较大的应用程序或者网络游戏,因为杀毒软件及相关*程序会在一定程度上消耗一些系统内存资源,将它们关闭可以节省不小的内存空间,从而能够有效避免内存读写错误现象的发生。当然,值得注意的是,我们在运行完大容量的程序或游戏之后,还必须记得及时将相关程序的*功能全部打开。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 yyfangchan@163.com (举报时请带上具体的网址) 举报,一经查实,本站将立刻删除