1.堆中内存溢出
Java堆中用于存储对象实例,只要不断在堆中创建新的对象,并且无法被GC回收,那么就可以做到OutOfMemoryError的出现
由于堆内存溢出是最常见的内存溢出情况,所以当Java堆内存溢出的时候,会先出现OutOfMemory,再出现Java heap space异常
要解决这个问题,则可以通过内存映像分析工具 例如Eclipse Memory Analyer,对应对内存溢出时候的异常快照进行分析即可,首先确定是内存泄漏还是内存溢出,在进行堆转储的分析
如果是内存泄漏,则利用工具进行定位,通过GC Roots的引用链,找到内存泄漏对象和GC引用链的信息,进行精确的定位,泄漏代码的位置
不存在泄漏的话,则是说明无法回收,这就必须从代码上检查,是否是某些对象的存活时间过长,尝试减少程序的运行期内存占用
2.虚拟机栈和本地方法栈的内存溢出
在整个HotSpot中,虚拟机栈和本地方法栈没有被区分开来的,所以实际的控制只由-Xss参数进行设置控制的
在这虚拟机栈和本地方法栈中,常见的异常有:
如果线程请求的栈深度大于虚拟机允许的栈深度,抛出StackOverflowError异常
如果想要设置深度,则还是需要-Xss参数
再说线程
如果扩展栈的空间时候无法申请到足够的内存大小,则抛出OutOfMemoryError异常
3.方法区和运行时常量池的溢出
虽然现在一直在说 “去永久代”这个概念,但是我们还是进行一些永久代,也就是方法区的内存溢出的举例
与之相对应的设置参数有: -XX:PermSize和-XX:MaxPermSize进行限制
在Jdk1.6中,通过String的intern方法加上while无限循环,可以直接爆出PermSize的问题
在Jdk1.7中和Jdk1.8中,则会出现OutOfMemoryError异常,这说明已经没有了永久代的概念,Jdk中将常量池移到了堆空间中
在Jdk 1.8中,则是将永久代放在本机内存中,称为了元空间
现在来说,还能导致内存溢出,常见的就在于我们进行动态代理类的生成的时候,由于生成的过于频繁,导致可能出现内存溢出的情况