Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

1. Java垃圾回收机制(GC)

1.1 GC机制作用 

---JVM自动检测和释放不再使用的对象内存。

 

1.2 堆内存3代分布(年轻代、老年代、持久代) 


Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
 关于Java堆3代分布情况,可通过命令:jmap –heap pid 查看:

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
 

 

1.3 GC过程

(1) 新生成的对象在Eden区完成内存分配

(2) 当Eden区满,再创建对象,会因为申请不到空间触发YGC,进行young(eden+1survivor)区的垃圾回收(为什么是eden+1survivor:两个survivor中始终有一个survivor是空的,空的那个被标记成To Survivor)

(3) YGC时,Eden不能被回收的对象被放入到空的survivor(也就是放到To Survivor,此时Eden被清空),另一个survivor(From Survivor)里不能被GC回收的对象也会被放入To Survivor,始终保证一个survivor是空的(YGC完成之后,To Survivor 和 From Survivor的标记互换)

(4) YGC结束后,若存放对象的survivor满,则这些对象被copy到old区,或者survivor区没有满,但是有些对象已经足够Old(超过XX:MaxTenuringThreshold),也被放入Old区

(5) 当Old区被放满的之后,进行完整的垃圾回收,即 FGC

(6) FGC后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现OOM错误

 

2. Java应用内存问题分析 

2.1 Java内存划分 

 2.1.1 堆内存

存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。

Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
 2.1.2 
栈内存

 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配(更准确地说是保存了引用的堆内存空间的地址,java中的“指针”)。

 

 2.1.3 永久保存区、方法区(Permanent Generation)

用于存储已被虚拟机加载的类信息、常量、静态变量等。

 

2.2 Java常见内存问题 

---OutOfMemory:内存溢出

---Memory Leak:内存泄露 

 

二者共同点:

(1) 通常最终的状态就会导致OOM错误

(2) 在Java堆或本地内存中都可能发生

 

二者不同点:

(1) ML是已经分配好的内存或对象,当不再需要,没有得到释放 而OOM则是没有足够的空间来供jvm分配新的内存块

(2) ML的内存曲线总体上是一条斜向上的曲线而OOM不是,反之未必

 

2.3 内存溢出类型及解决方法:

2.3.1 java.lang.OutOfMemoryError: Java heap space

堆内存溢出

优化:通过-Xmn(最小值)–Xms(初始值) -Xmx(最大值)参数手动设置 Heap(堆)的大小。

 

2.3.2 java.lang.OutOfMemoryError: PermGen space

PermGen Space溢出(方法区溢出、运行时常量池溢出)

优化:通过MaxPermSize参数设置PermGen space大小。

 

2.3.3 java.lang.*Error

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

优化:通过Xss参数调整