内存溢出、内存泄漏
2018-04-15 本文已影响0人
kindol
堆溢出
Java堆唯一的作用就是存储对象实例,只要保证不断创建对象并且对象不被回收,那么对象数量达到最大堆容量限制后就会产生内存溢出异常了。
这种异常很容易发现,因为都提示了“java.lang.OutOfMemoryError: Java heap space”了,异常定位问题行号有指示。
解决方案:
- 调大堆的大小
- 从代码上检视是否存在某些对象生命周期过长、持有状态时间过长,长时间少程序运行期间的内存消耗。
栈溢出:
若线程中方法调用的深度太深就会产生栈溢出(比如无限调用自己)。
通过不断创建线程的方式也可以产生OutOfMemoryError,因为每个线程都有自己的栈空间。不过这个操作有危险,原因是Windows平台下,Java的线程是直接映射到操作系统的内核线程上的,如果写个死循环无限产生线程,那么可能会造成操作系统的假死。
无限产生线程,换种说法,就是为每个线程的栈分配的内存空间越大,反而越容易产生内存溢出。
在不能减少线程数或者更换64位虚拟机的情况下,就只能通过减小最大堆容量和减小栈容量来换取更多的线程。
方法区和运行时常量池溢出:
对HotSpot而言,方法区=永久代,OutOfMemoryError的区域是“PermGen space”,即永久代,其实也就是方法区溢出了。
内存溢出和内存泄漏的区别:
- 内存溢出指程序在申请内存时,没有足够的空间可以分配了。
- 内存泄露指的是程序在申请内存之后,没有办法释放掉已经申请到的内存,它始终占用着内存,即被分配的对象可达但无用。
内存泄露终将导致内存溢出。
定位虚拟机内存问题第一步就是要判断到底是内存溢出还是内存泄露,前者跟踪堆栈信息就可以了;后者比较复杂一点,一般都是老年代中的大对象没释放掉,要通过各种办法找出老年代中的大对象没有被释放的原因。