深入理解Java虚拟机---(3)内存溢出与内存泄漏

 2019-12-22 10:56  阅读(707)
文章分类:JVM

写在前面:

内存溢出和内存泄漏都是程序中,我们要极力避免出现的异常,二者在字面上看上去相似,但实际上是不一样的异常情况,在这篇博客中,我们会总结内存溢出与内存泄漏的区别。

内存溢出和内存泄漏的定义:

内存溢出:Out Of Memory,指程序在申请内存时,没有足够的内存空间供其使用。

内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间。

用通俗一点的话来解释,内存溢出类似于数组索引越界,超出了数组存储的上限。内存泄漏是指内存使用完毕后,不能释放内存,并回收使用。

内存溢出和内存泄漏所导致的结果:

内存溢出时,程序将会终止,并且抛出Java.lang.OutOfMemoryError异常

内存泄漏时,程序并不会立刻终止,但是效率会降低,直到没有剩余内存,最终也会导致内存溢出。

内存溢出的类型:

(1)Java堆溢出

Java堆用于存储堆实例,不断的创建对象,那么在对象数量到达最大堆限制时,就会产生内存溢出。

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

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError 异常。
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

public class JavaVMStackSOF {
            private int stackLength = 1;

            public void stackLeak() {
                stackLength++;// 累加变量
                stackLeak();// 调用自身
            }
        }

上述代码是在单线程中调试,程序会报
StackOverflowError 异常。 而如果是于多线程之中,程序不断增加线程,并且为每一个线程扩大内存,则会报OutOfMemoryError异常。

(3)方法区和运行时常量池溢出

运行时常量池是方法区的一部分。方法区用于存放的Class信息,如类名,访问修饰符,常量池,字段描述,方法描述等。

对于非-常量池部分,运行时生成大量的动态类填满方法区。

对于常量池部分,如果无限循环调用String的intern()方法产生不同的String对象实例,并在List中保存其引用,以防止被GC回收,最终会产生内存溢出。

(4)本机直接内存溢出

而此类内存溢出一个明显的特征是在Heap Dump文件中不会看见明显的异常,如果发现OOM之后Dump文件很小,而程序中又直接或间接使用了NIO,可以考虑一下是不是这方面原因。

注:在JDK1.4之后加入了NIO,引入了一种基于通道与缓冲区的I/O方式。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> 深入理解Java虚拟机---(3)内存溢出与内存泄漏

相关推荐