java内存溢出怎么解决?

java内存溢出怎么解决?,第1张

第一对所有的代码包括页面中的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发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。

一,jvm内存区域

1, 程序计数器

一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器。

2, java栈

与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同。通常存放基本数据类型,对象引用(一个指向对象起始地址的引用指针或一个代表对象的句柄),reeturnAddress类型(指向一条字节码指令的地址)

栈区域有两种异常类型:如果线程请求的栈深度大于虚拟机所允许的深度,将抛StrackOverflowError异常;如果虚拟机栈可以动态扩展(大部分虚拟机都可动态扩展),当扩展时无法申请到足够的内早让弊存时会抛出OutOfMemoryError异常。

3, 本地方法栈

与虚拟机栈作用很相似,区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则是为虚拟机用到的Native方法服务。和虚拟机栈一样可能抛出StackOverflowError和OutOfMemoryError异常。

4, java堆

java

Heap是jvm所管理的内存中最大的区域。JavaHeap是被所有线程共享的一块内存区域,在虚拟机启动时创建。主要存放对象实例。JavaHeap

是垃圾收集器管理的主要区域,其可细分为新生代和老年代。如果在堆中没有内存完成实例分配,并且也无法再扩展时,会抛出OutOfMemoryError

异常。

5, 方法区

与javaHeap一样是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息、常量、静态变量、及时编译器编译后的代码等数据。当方法区无滑肢法满足内

存分配的需求时,将抛出OutOfMemoryError异常。方法同时包含常听说的运行时陆族常量池,用于存放编译期生成的各种字面量和符号引用。

6, 直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,是jvm外部的内存区域,这部分区域也可能导致OutOfMemoryError异常。

二,jvm参数

-Xss(StackSpace)栈空间

-Xms ,-Xmx(heap memory

space)堆空间:Heap是大家最为熟悉的区域,他是jvm用来存储对象实例的区域,Heap在32位的系统中最大为2G,其大小通过-Xms和

-Xmx来控制,-Xms为jvm启动时申请的最小Heap内存,默认为物理内存的1/64,但小于1G,-Xmx为jvm可申请的最大的Heap内存,

默认为物理内存的1/4,一般也小于1G,默认当空余堆内存小于40%时,jvm会最大Heap的大小到-Xmx指定大小,可通过

-XX:MinHeapFreeRatio来指定这个比例,当空余堆内存大于70%时,JVM会将Heap的大小往-Xms指定的大小调整,可通过

-XX:MaxHeapFreeRatio来指定这个比例,但通常为了避免频繁调整HeapSize的大小,将-Xms和-Xmx的值设为相同。

-XX:PermSize -XX:MaxPermSize :方法区持久代大小: 方法区域也是全局共享的,在一定的条件下它也会被 GC ,当方法区域需要使用的内存超过其允许的大小时,会抛出 OutOfMemory 的错误信息。

三,常见内存溢出错误解决办法

1, OutOfMemoryError异常

除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能,

Java Heap 溢出

一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess

java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。

出现这种异常,一般手段是先通过内存映像分析工具(如Eclipse Memory

Analyzer)对dump出来的堆转存快照进行分析,重点是确认内存中的对象是否是必要的,先分清是因为内存泄漏(Memory

Leak)还是内存溢出(Memory Overflow)。

如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。于是就能找到泄漏对象时通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收。

如果不存在泄漏,那就应该检查虚拟机的参数(-Xmx与-Xms)的设置是否适当。

2, 虚拟机栈和本地方法栈溢出

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。

如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常

这里需要注意当栈的大小越大可分配的线程数就越少。

3, 运行时常量池溢出

异常信息:java.lang.OutOfMemoryError:PermGen space

如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的作用是:如果池中已经包含一个等于

此String的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String

对象的引用。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量

池的容量。

4, 方法区溢出

方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。

异常信息:java.lang.OutOfMemoryError:PermGen space

方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的。在经常动态生成大量Class的应用中,要特别注意这点。

1、首先得搞清楚什么叫内存泄露,简单来说就是一个东西放塌液在内存里的时间太长了,当你的程序都跑完了,它还存在那里。这时它是白白的占用了你的内存,累积起来占用的内存越来越多……最后就会导致JVM报错:out of memory。

2、一般情况下,别人如果能指出你的系统(程序)内存溢出,这个人应该还是挺厉害槐渗的。通常对于新人来说,喜欢把变量直接定义在class下(此时称之为实例变量,或者成员变量),那么在方法里调用后,这个实例变量是不会被释放的,大量的这样使用就可能会引发内存泄露。

3、把变量定义在方法里,当这个方法执行完毕后内存就得到释放了,这是个好习惯。

4、如果想要看到内存溢出,可以按这样的思路去尝试一下:定义一个静态的实例变量(list或其它集合),然后在一个方法里循环往这个静态变量塞东西,直到这个实例变量撑爆你的jvm内存。很团明物快你就能看到out of memory……

import java.util.ArrayList

import java.util.List

public class MemoryTest {

private static List list = new ArrayList()

private static int count = 0

public static void main(String[] args) throws InterruptedException {

System.out.println("申请前的可用内存 = "+getFreeMemory())

while(true){

list.add(new byte[1024*1024])//用实例变量申请1M内存,当方法执行完毕时,这个static的变量是不会被释放

count++

if (count % 100 == 0) {

System.out.println("当前list.size()="+list.size()+",可用内存 = "+getFreeMemory())

Thread.sleep(500)

}

}

}

public static long getFreeMemory() {

return Runtime.getRuntime().freeMemory() / (1024 * 1024)

}

}


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

原文地址: https://outofmemory.cn/yw/12442225.html

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

发表评论

登录后才能评论

评论列表(0条)

保存