java内存溢出是什么情况?

java内存溢出是什么情况?,第1张

首先先说一下JVM内存结构问题,JVM为两块:PermanentSapce和HeapSpace,其中\x0d\x0aHeap = }。PermantSpace负责保存反射对象,一般不用配置。JVM的Heap区可以通过-X参数来设定。\x0d\x0a 当一个URL被访问时,内存申请过程如下:\x0d\x0aA. JVM会试图为相关Java对象在Eden中初始化一块内存区域\x0d\x0aB. 当Eden空间足够时,内存申请结束。否则到下一步\x0d\x0aC. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收), 释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区\x0d\x0aD. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区\x0d\x0aE. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)\x0d\x0aF. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”\x0d\x0a\x0d\x0aJVM调优建议:\x0d\x0a\x0d\x0ams/mx:定义YOUNG+OLD段的总尺寸,ms为JVM启动时YOUNG+OLD的内存大小;mx为最大可占用的YOUNG+OLD内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。\x0d\x0aNewSize/MaxNewSize:定义YOUNG段的尺寸,NewSize为JVM启动时YOUNG的内存大小;MaxNewSize为最大可占用的YOUNG内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。\x0d\x0aPermSize/MaxPermSize:定义Perm段的尺寸,PermSize为JVM启动时Perm的内存大小;MaxPermSize为最大可占用的Perm内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。\x0d\x0aSurvivorRatio:设置Survivor空间和Eden空间的比例\x0d\x0a\x0d\x0a内存溢出的可能性\x0d\x0a\x0d\x0a1. OLD段溢出\x0d\x0a这种内存溢出是最常见的情况之一,产生的原因可能是:\x0d\x0a1) 设置的内存参数过小(ms/mx, NewSize/MaxNewSize)\x0d\x0a2) 程序问题\x0d\x0a单个程序持续进行消耗内存的处理,如循环几千次的字符串处理,对字符串处理应建议使用StringBuffer。此时不会报内存溢出错,却会使系统持续垃圾收集,无法处理其它请求,相关问题程序可通过Thread Dump获取(见系统问题诊断一章)单个程序所申请内存过大,有的程序会申请几十乃至几百兆内存,此时JVM也会因无法申请到资源而出现内存溢出,对此首先要找到相关功能,然后交予程序员修改,要找到相关程序,必须在Apache日志中寻找。\x0d\x0a当Java对象使用完毕后,其所引用的对象却没有销毁,使得JVM认为他还是活跃的对象而不进行回收,这样累计占用了大量内存而无法释放。由于目前市面上还没有对系统影响小的内存分析工具,故此时只能和程序员一起定位。\x0d\x0a\x0d\x0a2. Perm段溢出\x0d\x0a通常由于Perm段装载了大量的Servlet类而导致溢出,目前的解决办法:\x0d\x0a1) 将PermSize扩大,一般256M能够满足要求\x0d\x0a2) 若别无选择,则只能将servlet的路径加到CLASSPATH中,但一般不建议这么处理\x0d\x0a\x0d\x0a3. C Heap溢出\x0d\x0a系统对C Heap没有限制,故C Heap发生问题时,Java进程所占内存会持续增长,直到占用所有可用系统内存\x0d\x0a\x0d\x0a参数说明:\x0d\x0a\x0d\x0aJVM 堆内存(heap)设置选项 \x0d\x0a 参数格式 \x0d\x0a 说明 \x0d\x0a \x0d\x0a设置新对象生产堆内存(Setting the Newgeneration heap size) \x0d\x0a -XX:NewSize \x0d\x0a 通过这个选项可以设置Java新对象生产堆内存。在通常情况下这个选项的数值为1 024的整数倍并且大于1MB。这个值的取值规则为,一般情况下这个值-XX:NewSize是最大堆内存(maximum heap size)的四分之一。增加这个选项值的大小是为了增大较大数量的短生命周期对象 \x0d\x0a\x0d\x0a增加Java新对象生产堆内存相当于增加了处理器的数目。并且可以并行地分配内存,但是请注意内存的垃圾回收却是不可以并行处理的 \x0d\x0a \x0d\x0a设置最大新对象生产堆内存(Setting the maximum New generation heap size) \x0d\x0a -XX:MaxNewSize \x0d\x0a 通过这个选项可以设置最大Java新对象生产堆内存。通常情况下这个选项的数值为1 024的整数倍并且大于1MB \x0d\x0a\x0d\x0a其功用与上面的设置新对象生产堆内存-XX:NewSize相同\x0d\x0a\x0d\x0a设置新对象生产堆内存的比例(Setting New heap size ratios) \x0d\x0a -XX:SurvivorRatio \x0d\x0a 新对象生产区域通常情况下被分为3个子区域:伊甸园,与两个残存对象空间,这两个空间的大小是相同的。通过用-XX:SurvivorRatio=X选项配置伊甸园与残存对象空间(Eden/survivor)的大小的比例。你可以试着将这个值设置为8,然后监控、观察垃圾回收的工作情况\x0d\x0a\x0d\x0a设置堆内存池的最大值(Setting maximum heap size) \x0d\x0a -Xmx \x0d\x0a 通过这个选项可以要求系统为堆内存池分配内存空间的最大值。通常情况下这个选项的数值为1 024的整数倍并且大于1 MB \x0d\x0a\x0d\x0a一般情况下这个值(-Xmx)与最小堆内存(minimum heap size _Xms)相同,以降低垃圾回收的频度 \x0d\x0a \x0d\x0a取消垃圾回收 \x0d\x0a -Xnoclassgc \x0d\x0a 这个选项用来取消系统对特定类的垃圾回收。它可以防止当这个类的所有引用丢失之后,这个类仍被引用时不会再一次被重新装载,因此这个选项将增大系统堆内存的空间 \x0d\x0a \x0d\x0a设置栈内存的大小 \x0d\x0a -Xss \x0d\x0a 这个选项用来控制本地线程栈的大小,当这个选项被设置的较大(>2MB)时将会在很大程度上降低系统的性能。因此在设置这个值时应该格外小心,调整后要注意观察系统的性能,不断调整以期达到最优 \x0d\x0a \x0d\x0a最后说一句,你的机器的连接数设置也至关重要,连接的关闭最好把时间设置的少些,那些连接非常耗费资源。也是引起内存泄露的主要原因。

使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space

在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。

JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。

例如:java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar

如果Heap Size设置偏小,除了这些异常信息外,还会发现程序的响应速度变慢了。GC占用了更多的时间,而应用分配到的执行时间较少。

Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

Heap size的 -Xms -Xmn 设置不要超出物理内存的大小。否则会提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。

这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个.

1.可以在windows 更改系统环境变量加上JAVA_OPTS=-Xms64m -Xmx512m

2,如果用的tomcat,在windows下,可以在C:\tomcat5.5.9\bin\catalina.bat 中加上:

set JAVA_OPTS=-Xms64m -Xmx256m

位置在: rem Guess CATALINA_HOME if not defined 这行的下面加合适.

3.如果是linux系统

Linux 在{tomcat_home}/bin/catalina.sh的前面,加 set JAVA_OPTS='-Xms64 -Xmx512'

第一对所有的代码包括页面中的java代码都进行一遍彻底的回顾检查,

1.对那些静态(static)的对象要特别留神,特别是类型为Map,List,Set的,静态的变量会一直驻存在内存中,生命周期比较长,不会被垃圾器回收。

2.对于代码,要审查是否生成了大量的冗余的对象,还有一些逻辑业务处理的类,

算法是否过于复杂,调整算法,对于代码认真审查,再仔细重构一遍代码,能提高代码质量,提高程序运行稳定性。

3.Java中的内存溢出大都是因为栈中的变量太多了。其实内存有的是。建议不用的尽量设成null以便回收,多用局部变量,少用成员变量。

1),变量所包含的对象体积较大,占用内存较多。

2),变量所包含的对象生命周期较长。

3),变量所包含的对象数据稳定。

4),该类的对象实例有对该变量所包含的对象的共享需求。

4.在我的程序中对静态变量的优化后,使程序占用内存量至少提升了5k-10k。所以也不容忽视。

第二还有就是String类相关的东西:

1.字符串累加的时候一定要用StringBuffer的append方法,不要使用+ *** 作符连接两个字符串。差别很大。而且在循环或某些重复执行的动作中不要去创建String对象,因为String对象是要用StringBuffer对象来处理的,一个String对象应该是产生了 3个对象(大概是这样:))。

2.字符串length()方法来取得字符串长度的时候不要把length放到循环中,可以在循环外面对其取值。(包括vector的size方法)。特别是循环次数多的时候,尽量把length放到循环外面。

int size = xmlVector.size()

for (int i = 2i <sizei++) {

。。。

}

3 写代码的时候处理内存溢出

try{

//do sth

....

}catch (outofmemoryerror e){//可以用一个共通函数来执行.

system.out.print (“no memory! ”)

system.gc()

//do sth again

....

} 4.对于频繁申请内存和释放内存的 *** 作,还是自己控制一下比较好,但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。 Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8335941.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-15
下一篇 2023-04-15

发表评论

登录后才能评论

评论列表(0条)

保存