Java内存泄漏的方式
Java 会有内存泄漏么?
我们都知道 Java 是自动管理内存的,且核心的就是GC机制,即然提出这个问题,那就是肯定是存在内存泄漏的问题的。只不过是以哪种方式而已
♻️ 判断一个对象可以被回收
我们都说内存被占用,是Java的对象的占用的,那么JVM判断一个对象是否可以被回收,一般两种方式:
引用计数: 每一个对象都有引用计数的属性,新增一个引用计数+1,引用释放计数-1,计数为0可以回收可达性分析:从GC Roots开始搜索,搜索引用链路是否能到达GC Roots,如果没有任何引用链路相连时候,该对象就可不可用,JVM就判断为可回收对象, 这种可以解决循环引用问题
GC Roots对象有哪些:
- 虚拟机栈中引用的对象
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中
JNI引用的对象
因为,引用计数的方法简单,但是存在一个致命的缺陷,假设对象A引用对象B,对象B又引用对象A,双方的引用计数都为1,假如程序上确实没有使用这两个对象慢但是JVM却无法对他们进行回收。也就是对象的循环引用问题。
但是可达性分析的方式,从GC ROOTS开始搜索,找寻是否可达对象,不可达的进行回收,解决了循环引用的问题。
所以市面上大部分主流的虚拟机都使用可达性分析 来判定对象是否被GC回收
JAVA 体系 内存问题有几种
内存溢出OOM(out of memory), 申请分配内存时候,没有足够的可用空间出现OOM内存泄漏(memory leak), 已经申请分配的内存, 无法释放已经申请老的内存空间, 且一直在申请分配,但一直存在内存泄漏,内存泄漏堆积后,导致的无内存可以。
内存泄漏会导致OOM,但是OOM不完全因为内存泄漏。也可能是太多的大对象导致的。
如何分析内存泄漏问题
我们都知道内存泄漏是因为对象太多或者因为内存申请了但是无法释放导致的,所以针对内存泄漏的分析,一般也是围绕内存的对象的申请、释放等动作,对内存管理的信息进行统计、分析、可视化操作,根据这些信息进行判断释放有内存泄漏问题
工具主要有
- JvisualVM
- JProfile
- Arthas
- Xpocket
- …