讨论篇:静态变量生命周期到底何如?如何使用?

静态变量的生命周期

​ 最近有个朋友问我个问题,为何用静态变量做为一个标志位存储,可是时常数据丢失,有时候又是可行的,缘由究竟为什么。java

public static boolean flag = false
复制代码

​ 熟悉Java内存模型的朋友都知道,静态变量是存储在方法区之中的,而静态变量又属于整个类的实例,那么静态变量整个的生命周期是什么样子,何时会被回收呢?在此以前其实没有太多考虑这个问题,工做涉及到静态变量的地方通常也就是单例模式,但也没有出现过被回收的状况,加上工做以来,不少前辈同事也教导过不要使用太多的静态变量,因此,对这个问题本身也一直是只知其一;不知其二,没有认真思考这个问题,在此参考了一些资料,作一些记录。算法

1.类的生命周期

上述也说道,静态变量是属于类的实例对象,因此静态变量的生命周期实际也就是类的生命周期。bash

当咱们编写一个Java的源文件后,通过编译会生成一个后缀名为class的文件,这种文件叫作字节码文件,只有这种字节码文件才可以在Java虚拟机中运行,Java类的生命周期就是指一个class文件从加载到卸载的全过程。jvm

一个Java类的完整的生命周期会经历加载、链接、初始化、使用、和卸载五个阶段,这里就不都进行讨论了,咱们主要看加载和卸载两个阶段spa

1.1 加载

对于加载的时机,各个虚拟机的作法并不同,可是有一个原则,就是当jvm“预期”到一个类将要被使用时就会在使用它以前对这 个类进行加载。好比说,在一段代码中出现了一个类的名字,jvm在执行这段代码以前并不能肯定这个类是否会被使用到,因而,有些jvm会在执行前就加载这个类,而有些则在真正须要用的时候才会去加载它,这取决于具体的jvm实现。咱们经常使用的hotspot虚拟机是采用的后者,就是说当真正用到一个类的时候才对它进行加载。code

加载阶段是类的生命周期中的第一个阶段,加载阶段以后,是链接阶段。有一点须要注意,就是有时链接阶段并不会等加载阶段完 全完成以后才开始,而是交叉进行,可能一个类只加载了一部分以后,链接阶段就已经开始了。可是这两个阶段总的开始时间和完成时间老是固定的:加载阶段老是在链接阶段以前开始,链接阶段老是在加载阶段完成以后完成.对象

也就是相似懒加载的思想,在将要使用到的时候去加载这个类,这样也能避免浪费内存资源,固然,具体的实现就取决于具体的Jvm了生命周期

1.2 卸载

jvm卸载类的断定条件以下:参照hotspot虚拟机的一句话进程

1.该类全部的实例都已经被回收,也就是java堆中不存在该类的任何实例。
2.加载该类的ClassLoader已经被回收。
3.该类对应的java.lang.Class对象没有任何地方被引用,没法在任何地方经过反射访问该类的方法。
复制代码

从上面的条件能够看到,一个类被卸载的条件仍是挺苛刻的,首先全部类的对象实例要被回收,两者,加载该类的ClassLoader要被回收,这个条件就基本等同于进程挂掉,最后是Class对象无任何引用。内存

从上面结论基本能够判断,静态变量的生命周期基本是从这个类加载,到整个进程死掉的过程,注意退出APK不表明杀死进程,这时候,静态变量仍是有效的,进程重启后静态变量从新生成。依据根搜索算法,对象是否会被垃圾收集与未被使用时间长短无关,仅仅在于这个对象是否是“活”的。

同时咱们也应该注意到,静态变量生命周期的如此之长,致使静态变量基本很难被GC回收掉,是很是占用内存的,因此在开发过程当中,尽可能少使用一些静态属性的变量,减小内存占用。

以上也是仅表明我的意见,期待各位朋友的发言