内存泄露和内存溢出的区别
一、内存泄露
由于不能正常进行垃圾回收,占用的内存一直不会被清除,例如:拥有一块20字节的内存空间,你将30字节的文件写入其中,就会造成内存溢出。由于内存泄漏,最终会导致内存溢出(OOM),导致系统崩溃
二、内存溢出
是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
1. 栈内存溢出(StackOverflowError)
public class Test001 { public static void main(String[] args) { Test001 test001 = new Test001(); test001.testMethod(); } public void testMethod(){ testMethod(); } }
递归调用方法,导致栈内存溢出,学过jvm我们可以知道,虚拟机栈是用于描述java方法执行的内存模型,一个方法从开始执行到执行完毕就对应该栈帧的入栈到出栈的过程,由于递归,一层嵌套一层,导致方法执行不完,只有入栈没有出栈,导致栈内存溢出。
2. 堆内存溢出(OutOfMemoryError:java heap space)
public class Test001 { private List<String> list = new ArrayList<>(); public static void main(String[] args) { Test001 test001 = new Test001(); while (true){ test001.list.add(UUID.randomUUID().toString()); } } }
在创建新的对象时, 堆内存中的空间不足以存放新创建的对象时发生。产生原因:程序中出现了死循环,不断创建对象;程序占用内存太多,超过了JVM堆设置的最大值。
3. 永久代溢出(OutOfMemoryError:PermGen sapce)
持久带中包含方法区,方法区包含常量池
因此持久带溢出有可能是运行时常量池溢出,也有可能是方法区中保存的class对象没有被及时回收掉或者class信息占用的内存超过了我们配置
用String.intern()触发常量池溢出
Class对象未被释放,Class对象占用信息过多,有过多的Class对象。可以导致持久带内存溢出