发布于2026-07-03 阅读(0)
扫一扫,手机访问
静态变量在 Ja va 里是个挺特别的存在——它的生命周期,其实跟堆里的那些实例对象没半毛钱关系。你可能会想,它什么时候生、什么时候死?说到底,得看它所属的那个 Class 对象在 JVM 里还能不能“活着”。
静态变量的生命周期与类相同,从类加载时初始化,存储于方法区(元空间),随类卸载而销毁;其存在依赖Class对象是否被JVM强引用,通常持续至JVM退出。

换句话说,静态变量不会因为某个对象被回收而消失,也不会因为你 new 了一个实例就凭空变出来。它的整个生命周期,完全取决于 JVM 对那个 Class 对象的引用情况。
当 JVM 第一次“真正用上”某个类时——比如调用它的静态方法、访问它的静态字段、或者 new 一个对象、通过反射获取 Class 对象——就会触发类加载流程:加载 → 链接(验证、准备、解析)→ 初始化。注意,在“准备”阶段,静态变量就已经被分配好内存,并且设好默认值了;到了“初始化”阶段,才会执行 static {} 代码块和静态字段的显式赋值。
这时候,静态变量实际上存放在方法区里(JDK 8 以后是元空间),跟堆内存没什么关系。它属于类本身,所有实例共享同一份数据。一个类只此一份,多少实例来了都一样。
静态变量不会被垃圾回收器单独处理——它没那么特殊。但它的“存在状态”直接由其所属的 Class 对象决定:只要这个 Class 对象还被强引用拿着,静态变量就一直有效。而 Class 对象能不能被卸载,得同时满足三个条件:
ClassLoader 实例本身也被 GC 回收了Class 对象不再有任何强引用——包括 MyClass.class、静态字段里持有该 Class 的引用、以及反射调用留下的痕迹等这三条缺一不可。只要有一条不满足,类就赖着不走,静态变量自然也就一直活在方法区里。
现实开发中,有些情况会让静态变量“意外长寿”,甚至变成内存泄漏的源头:
Class 对象和实例之间形成了一条双向强引用链,谁都别想逃ClassLoader 没被释放,而它加载的类里还有静态引用,整个加载器链都拽着不放ThreadLocal、监听器、回调接口等方式,间接引用了静态变量关联的对象这些场景的本质都一样:让 Class 对象始终可达,从而阻止类卸载。
在绝大多数标准 Ja va 应用里——尤其是用了 Spring 这种单例容器的项目——系统类加载器(Bootstrap、Extension、AppClassLoader)的生命周期和 JVM 是一体的,压根不会被回收。所以这些类加载器加载的类几乎永远不会被卸载,静态变量也就永远待在那里。
只有在那些动态类加载的场景下——比如 OSGi 容器、热部署环境、或者你自己用自定义 ClassLoader 配合弱引用管理——才有可能触发类卸载。一旦类被卸载,静态变量占用的方法区内存才会真正被释放。
简单总结一下:静态变量不归 GC 管,它归类加载器和 Class 对象管。它什么时候消失,取决于那个类什么时候真正“退场”。而大多数时候,退场时刻就是 JVM 关闭的那一刻。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8