前言
小时候记得印象最喜欢的应该就是小智的卡比兽了。然而不论是金,银还是其他版本中,卡比兽都好弱啊~~~不过,卡比兽的“内存”是真的大呢,好像永远都不会溢出
或者泄漏
呢,等等,这什么意思!!
内存溢出
解释
所谓的内存溢出,从字面上的意思即jvm
内存不够用了,目前无法存放创建的对象。
原因
- JVM分配的内存相对较小,也许是机器的内存本来就小,也可以是
jvm
参数xmx
设置的较小。 - 某段代码进行了死循环,导致对象疯狂产生,但是又不会触发GC,所以就内存溢出了。
public void 创建GC的方法(){
List list = new ArrayList<>();
while(true){
Person p1 = new Person(); # p1变量总是指向不同的对象,应该会Gc
p1.setAge("23");
list.add(p1); # 但是list原理是数组,又指向了创建的对象,导致无法GC
}
}
其实这也能算是一种内存泄漏了。
复制代码
- 创建的对象太大,最典型的就是IO了。对象太大导致新生代存放不下,只能存放到老年代。而老年代也存放不下,只能
OOM
了。
解决(对应上述的解释)
- 增大服务器内存,设置
xmx
和xms
。 - 这时候是一定会GC的,通过线程dump和堆dump。分析出现问题的代码
- 增大jvm内存,及时关闭流,及时GC。
内存泄露
解释
不再会被使用的对象不能被回收,就是内存泄露。说的通俗点就是:该对象已经需要被GC了,却没有这么做。
原因
看一段代码:
public class Simple {
Object o1;
public void method1(){
o1 = new Object();
//...其他代码
}
在Simple的实例没有被回收之前,object对象就不会被回收。原因就是因为o1是实例变量
复制代码
解决
public class Simple {
Object o1;
public void method1(){
o1 = new Object();
//...其他代码
o1 = null
}
不管是采用引用计数,或者是GC Root判断是否应该GC,当o1 指向 null后,o1这个对象都会被GC
复制代码
public class Simple {
public void method1(){
Object o1 = new Object();
//...其他代码
o1 = null
}
o1 的生命周期就只是这个方法了,所以o1这个对象将会被GC。
所以需要记住,设置实例变量时或者类变量 初始化时,想一下GC问题
复制代码
什么是OOM
引用一段话:
OOM
,全称Out Of Memory
,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError
。
看下关于的官方说明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector
.
意思就是说,当JVM
因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error
(注:非exception
,因为这个问题已经严重到不足以被应用处理)。
结语
内存溢出是一定会产生OOM
的。而内存泄漏到达一定程度会导致内存溢出,产生OOM
,如上述的list.add()
。 参考自:链接
真羡慕卡比兽的肚子啊~~~