美文网首页30岁程序员的未来心路
Java基础-内存溢出是怎么回事?

Java基础-内存溢出是怎么回事?

作者: 夜暗殇 | 来源:发表于2021-08-25 16:12 被阅读0次

    内存溢出(out of memory)的意思是程序在申请内存时,没有足够的空间给其使用,出现out of memory ;例如创建了一个integer对象,单给这个对象存储数据的时候放了一个long类型的数据,这时就会出现内存溢出了。下面列举一下引起内存溢出的几种原因:

    1、内存中加载的数据量过于庞大;

    2、集合类中有对对象的引用,使用完后未清空,使得JVM不能回收,造成内存中大量的垃圾数据;

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

    4、启动参数内存值设定的过小

    5、程序中使用第三方软件中存在BUG;

    内存溢出常见的解决方案:

    1、最直接的办法就是修改JVM的启动参数,直接增加内存。(-Xms,-Xmx参数,具体请直接上网百度)

    2、检查错误日志,查看“OutOfMemory”错误前是否有其他异常或错误。

    3、对代码进行排查和分析,找出可能发生内存溢出的位置。

    4、使用内存查看工具动态查看内存使用情况。

    下面是从网上找到的关于内存溢出原因及解决方案的资料(自己进行了归纳精简):

    我们启动tomcat出现的内存溢出实际上就是JVM的内存溢出。对内存溢出进行深度剖析,首先需要对JVM有关内存方面的知识有一定的了解。

    JVM管理的内存可以分两种:堆和非堆。

    堆是运行时的数据区域,在Java虚拟机启动时创建,所有的类实例和数组的内存都在此处分配,简单的说就是Java代码可以用的内存,是给开发人员用的。

    堆内存的分配:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。

    非堆内存是JVM自己用的,所以方法区、JVM内部处理或优化所需的内存、每个类的结构以及方法和构造方法的代码都在非堆内存中,运行期间GC不会释放其空间。

    非堆内存的分配:JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

    三种内存溢出异常介绍

    1. OutOfMemoryError: Java heap space  堆溢出

    内存溢出主要存在问题就是出现在这个情况中。当在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。

    2. OutOfMemoryError: PermGen space   非堆溢出(永久保存区域溢出)

    这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。

    3. OutOfMemoryError: unable to create new native thread.   无法创建新的线程

    这种现象比较少见,也比较奇怪,主要是和jvm与系统内存的比例有关。这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。

    如何设置JVM的内存分配

    (1)当在命令提示符下启动并使用JVM时(只对当前运行的类Test生效):

    java -Xmx128m -Xms64m -Xmn32m -Xss16m Test

    (2)当在集成开发环境下(如eclipse)启动并使用JVM时:

    a. 在eclipse根目录下打开eclipse.ini,默认内容为(这里设置的是运行当前开发工具的JVM内存分配):  -vmargs -Xms40m -Xmx256m -vmargs表示以下为虚拟机设置参数,可修改其中的参数值,也可添加-Xmn,-Xss,另外,eclipse.ini内还可以设置非   堆内存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。

    b. 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效)  编辑当前使用的JRE,在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m –Xss16m。

    c. 打开eclipse-运行-运行-Java应用程序(只对所设置的java类生效)  选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m  注:如果在同一开发环境中同时进行了b和c设置,则b设置生效,c设置无效,如:  开发环境的设置为:-Xmx256m,而类Test的设置为:-Xmx128m -Xms64m,则运行Test时生效的设置为:  -Xmx256m -Xms64m。

    (3)当在服务器环境下(如Tomcat)启动并使用JVM时(对当前服务器环境下所以Java程序生效):

    a. 设置环境变量:  变量名:CATALINA_OPTS  变量值:-Xmx128m -Xms64m -Xmn32m -Xss16m。

    b. 打开Tomcat根目录下的bin文件夹,编辑catalina.bat,将其中的%CATALINA_OPTS%(共有四处)替换为:-Xmx128m -Xms64m -Xmn32m -Xss16m。

    c. 若没有catalina.bat,只有tomcat.exe,tomcat6w.exe;则可以在启动tomcat6w.exe 后 右键配置--Java--java option 下面输入:-Xmx256m –Xms64m

    也可以找到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions原值为 -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 6.0\common\endorsed" -Xrs 加入  -Xms300m  -Xmx350m  (我的是加入-Xmx350m,tomcat才能启动,加入-Xms300m  -Xmx350m反而tomcat都不能启动)重起tomcat服务,设置生效。

    以上内容摘自http://blog.csdn.net/thunder0709/article/details/16855195

    相关文章

      网友评论

        本文标题:Java基础-内存溢出是怎么回事?

        本文链接:https://www.haomeiwen.com/subject/kzipwxtx.html