内存泄露(OOM)现象及举例

一.HeapSize OOM(堆空间内存溢出)

A.eg:List.add(" ")在一个死循环中不断的调用add却没有remove。

B.并发导致。

解决方法有:1.代码提速。这样可以使得相同对象的生存时间更短。更快被GC。

                 2.I/O操作时候,objecft=null可以辅助GC,一旦方法脱离了作用域,相应的局部变量应用就会被注销。

                 3.程序跑的飞快,还是出现OOM,考虑到去修改参数配置。

                    eg:堆的大小,堆空间的大小,堆空间要设置的足够大(相对),如果太大,发生FULL GC会很恐怖

                  4.内存可能在某些情况增加几十字节空间但未能释放,每次被GC,很老的对象被GC的较慢。

                    eg:Session中放数据,Session回话消失才会被注销,但是会话要很长的时间才会被注销。

                     不断的FULLGC就是不抛出OOM的现象,出现这种现象通常是一些藏匿的Bug或配置导致。

                    eg:Tomcat的session导致,session信息保存在全局的currentHashMap中,大量的HTTPClient访问创建的临时session。

                        但并保存系统中为之分配的SessionKey中和相关的Cookies信息,导致每次请求都创建session(几十个字节),一般看不出来,是一个堆积如山的过程。

二.PermGen OOM(永久代内存溢出)

A.常量池(JDK1.6,JDK1.7以后常量池不会放在永久代中了。)

string常量对象会在常量池(包含类名,方法名,属性名等信息)中以hash方式存储和访问,hash表默认的大小为1009,当string过多时,可以通过修改-xx:stringtableSize参数来增加Hash元素的个数,减少Hash冲突。

eg:不断的循环调用string中的intern()方法,就会导致OOM.

B.class加载

由于class被卸载的条件十分的苛刻,这个class所对应的classLoader下面所有的class都没有活对象的应用才会被卸载。

解决方法:在每次CGlib动态创建时,都重新给它设置一个classLoader,这样在运行代码就不会出现OOM,会发现大量的class被卸载。

三.DirectBuffer OOM(直接内存内存溢出)

Java中普通I/O用输入/输出流方式实现,输入流InputStream(终端—>直接内存->JVM),输出流(JVM->直接内存->终端),这一过程中有kenel与JVM之间的拷贝(很多次),为了使用直接内存,Java是有一块区域叫DirectBuffer,不是JavaHeap而是cHeap的一部分。

eg:设置-xx:MaxDirectMemorysize:256

    分配一个ByteBufferallocateDirect(257*1024*1024)就会导致OOM。

四.StackOverflowError(栈内存溢出错误)

1.StackOverflowError,通常都是程序的问题,JVM对栈帧的大小设置已经很大了。

2.程序运行过程中,方法分派时,会分配frame来存放本地变量,栈,pc寄存器等信息,方法再调用方法会导致Java栈空间无止境的增长(死递归),Java的解决方法是:设置一个私有栈(不在堆内存,而是在NativeMemory),这个栈的空间大小,通过-Xss来设置,数量级在256K-1MB。如果使用空间超过了-Xss限制,就会出现StackOverflowError。

3.eg:死递归

死递归和死循环的区别:死循环类似于while(true)的操作,它的线程栈空间使用不会递增。而死递归需要记录退回的路径,递归过程中调用方法,每个方法运行过程中的本地变量。也就是要记录上下文信息。这些信息会随着内容的增加,占用很大的内存空间。

死递归:

eg:1.组件的复用。

     2.子类调用父类(复用父类的方法),父类调用子类(达到多态的效果),这中间要经过许多方法,可能形成环,进而形成死递归。

     3.三方框架的问题。

五.其他内存溢出

A.unable to creat new native thread

原因:物理内存不够用或者OS限制了单个进程使用的最大内存,大量的线程分配时,就有可能导致占用的Native Memory很多。

eg:死循环中创建线程并启动,线程内部申请变量,本身不退出。而且设置Os对进程内存的限制。

B.request{} byte for {}out of swap

地址空间不够用(不一定是物理地址,还有swap,显卡,网卡)

C.IoException:too many open files

打开太多的文件,也可能是本地的socket打开太多,而没有被关闭,太多没有关闭套接字导致。

 更多精彩内容请看:Java特种兵上册,136-146页的内容。

电子版的下载地址为:http://download.csdn.net/detail/lichunlin1994/7986285

 

 

 

 

 

                                   

 

转载于:https://www.cnblogs.com/hupp/p/4517369.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值