jvm中对象的生命周期
创建阶段
(1)为对象分配存储空间
(2)开始构造对象
(3)从超类到子类对static成员进行初始化
(4)超类成员变量按顺序初始化,递归调用超类的构造方法
(5)子类成员变量按顺序初始化,子类构造方法调用,并且一旦对象被创建,并被分派给某些变量赋
值,这个对象的状 态就切换到了应用阶段
应用阶段
(1)系统至少维护着对象的一个强引用(Strong Reference)
(2)所有对该对象的引用全部是强引用(除非我们显式地使用了:软引用(Soft Reference)、
弱引用(Weak Reference)或虚引用(Phantom Reference))
引用的定义:
1.我们的数据类型必须是引用类型
2.我们这个类型的数据所存储的数据必须是另外一块内存的起始地址
不可见阶段
不可见阶段的对象在虚拟机的对象根引用集合中再也找不到直接或者间接的强引用,最常见的就是线程或者函数中的临时变量。程序不再持有对象的强引用。(但是某些类的静态变量或者JNI是有可能持有的 )
不可达阶段
指对象不再被任何强引用持有,GC发现该对象已经不可达
与不可见阶段的区别就是:不可达是经过算法之后的
那么有哪些算法?
引用计数:
对象有一个引用就+1,去掉一个引用就-1,当引用数为0就认为是没有引用,可以回收
问题:解决不了循环依赖问题
可达性分析:通过GC Root的对象,开始向下寻找,看某个对象是否可达
什么能看作GC ROOT:加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、
本地方法栈的变量等本质上就是一组活跃的引用
收集阶段
看对象需不需要执行finalize方法:
如果不需要:虚拟机已经调用过finalize方法或者对象没有重写finalize方法,那么对象可以回收
需要:虚拟机将对象放入F-queue,创建一个低优先级的线程执行队列中对象的finalize方法
finalize方法中是否重新为该对象建立引用连接
是:虚拟机将对象移出F-queue队列,对象重新回到应用阶段
否:对象可以回收
finalize方法会影响JVM的对象以及分配回收速度
finalize方法可能会让对象复活
终结阶段
对象的finalize()函数执行完成后,对象仍处于不可达状态,该对象进程终结阶段。
对象内存空间重新分配阶段
GC对该对象占用的内存空间进行回收或者再分配,该对象彻底消失
内存溢出
1、堆内存溢出:java.lang.OutOfMemoryError: GC overhead limit exceeded
-Xmx20M :程序运行时最大能扩容到的大小
-Xms20M:初始化堆大小
2、方法区内存溢出:java.lang.OutOfMemoryError: Metaspace
-XX:MetaspaceSize:初始化方法区大小
-XX:MaxMetaspaceSize:程序运行时最大能扩容到的大小
3、占内存溢出:java.lang.StackOverflowError
-Xss:栈的大小(默认1M)