java 的内存溢出是一个非常恼人的问题,简要说说自己的理解。

为什么内存溢出不容易发现?

内存空间是有限的:

  • 你需要了解一下java的内存模型。
  • 事实上,电脑的内存是十分有限的,算上硬盘也不能无限量。所以java本身得到的内存可能也只是电脑内存的一部分。
  • 可能java做的稍微灵活一些,并不是分配固定的内存。而是可以动态变化的。
  • 但是操作体统不允许一个进程所占用的资源无限制的增长下去,java的内存分配需要有一个最大值。
  • 分配内存有限是造成内存溢出客观的原因。

不易定位:

  • 这里拿堆内存来举例。(堆区域用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。)
  • 当你new 出某个对象时,可能突然就会爆发 outofmemory。是因为你的这条new 语句存在错误吗?
  • 不一定,内存溢出时,所爆出的停止的点,不一定是真正存在问题的点,它只是一个触发点。之所以,在此处出问题,是因为在此语句之前,存在某种不合理的引用等等,导致了占据了大量的空间。
  • 所以当出现这类问题时,你不能根据异常信息迅速定位到出问题的位置。
  • 但是你可以做的是,从这点出发,找与之相关的涉及堆内存使用的环节。(往往会浪费大量时间)


出现内存溢出时处理办法:

  • 根据上面的分析,大概可以得到两种较大的办法。
  • 是java 虚拟机分配的问题,而程序并没有什么问题。(针对这一点你只需要调节java虚拟机相关的参数即可,这里不在赘述)
  • 另一个方面是程序本身就存在的问题。不合理的程序结构,造成了这个问题,使得程序中相关变量等预期的生命周期远远小于在java内存机制下的生命周期。
  • 程序本身常见问题,往往出现在循环处,链表处等等。
  • 在不合理的程序中,内存的使用量,是随着循环的次数增加,而增量增长的。(不断在上升,每次循环都有一些东西无法释放掉)