简述JAVA类的生命周期
介绍
一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段:

加载
主要是:把类的信息加载到方法区中,并在堆中实例化一个Class对象。
加载方式
根据类的全路径加载class文件
从jar的包中读取class文件
根据一定的规则实时生成,比如设计模式中的动态代理模式,就是根据相应的类自动生成它的代理类。
加载的时期
不是jvm启动就加载,而是在真是使用的时候才会触发加载。
- new 一个类的时候
- 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
- 这个类是程序的入口类
- 对这个类进行反射的时候(执行了上面的行为)
连接
一般会跟加载阶段和初始化阶段交叉进行。
验证
验证一下这个类是否合法,
- 字节码格式是否合法
- 变量和方法是否有重复
- 继承和实现是否符合标准
。。。
准备
给类的静态变量分配并初始化存储空间;
也就是给静态变量赋默认的初始值(不包括非静态变量)
解析
把符合引用转换为直接引用。
比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,
jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。
这里show就是符号引用,而c17164就是直接引用。
在解析阶段jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。
初始化
执行静态变量的初始化和静态Java代码块,并初始化程序员设置的变量值!
时机
和加载的时机一样,更准确的说初始化之前必须先经过加载,所以他们基本一样
- new 一个类的时候
- 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
- 对这个类进行反射的时候(执行了上面的行为)
- 初始化一个类的子类,该子类所有的父类都会被初始化。
- 作为程序的入口类(如:main方法所在的类,java 命令跟着的类)
过程
按照顺序自上而下运行类中的【变量赋值语句】和【静态语句】,
如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。

使用
使用阶段包括主动引用和被动引用。
主动引用(会引起类的初始化)
- new 一个类的时候
- 调用类的静态方法,以及读取或者修改一个类的静态字段的时候(不是常量)
- 这个类是程序的入口类
- 对这个类进行反射的时候(执行了上面的行为)
注意:以上几种主动引用会引起类的初始化,这里的几种情况只有new或者使用class.newInstance()才会调用构造函数!
被动引用(不会引起类的初始化)
引用父类的静态字段
定义类数组
引用类的常量
例如
public class TestClassInit {
static {
System.out.println("初始化InitClass");
}
public static String staticA = null;
public final static String finalB = "b";
public static void staticMethod(){}
}
public class Test {
public static void main(String args []){
//主动引用
//new 一个类的时候
TestClassInit tct=new TestClassInit();
//读取静态变量
String staticA=TestClassInit.staticA;
//设置静态变量
TestClassInit.staticA="A";
//调用静态方法
TestClassInit.staticMethod();
//被动引用
//定义类数组,不会引起类的初始化
TestClassInit[] tcts=new TestClassInit[10];
//引用类的常量,不会引起类的初始化
String finalB=TestClassInit.finalB;
}
}
卸载
满足下面请看才会卸载类:
- java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收
- 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法
相关问题
Class.forName()和ClassLoader.loadClass的区别
Class.forName(className)方法,内部实际调用的方法是 Class.forName(className,true,classloader);
第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。
一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。
ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false);
第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,
不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行;
如:Student.class.getClassLoader().loadClass("com.we.web.erp.jvm.Student");
Class.forName("com.we.web.erp.jvm.Student");
静态代码块,构造代码块,构造函数,以及静态变量赋值, 实例变量赋值 的执行顺序;
- 没有继承关系的情况下:
静态变量赋值 > 静态代码 > 实例变量赋值 > 构造代码 > 构造函数
public class School {
public School(){
System.out.println("School的构造函数执行[静态属性]!");
}
}
public class Student {
public Student(){
System.out.println("Student类的构造函数执行[非静态属性]!");
}
}
public class SubClass {
private Student student=new Student();
private static School school=new School();
static
{
System.out.println("静态代码块!");
}
{
System.out.println("构造代码块!");
}
public SubClass()
{
System.out.println("构造函数!");
}
}
执行结果:
School的构造函数执行[静态属性]!
静态代码块!
Student类的构造函数执行[非静态属性]!
构造代码块!
构造函数!
执行这里的静态变量赋值和实例变量赋值可以按照下图理解;

- 有继承的情况下
public class SubClass extends SuperClass {
private Student student=new Student();
private static School school=new School();
static
{
System.out.println("子类静态代码块!");
}
{
System.out.println("子类的构造代码块!");
}
public SubClass()
{
System.out.println("子类构造函数!");
}
}
public class SuperClass {
static {
System.out.println("父类静态代码块!");
}
{
System.out.println("父类的构造代码块!");
}
SuperClass()
{
System.out.println("父类的构造函数!");
}
}
执行结果:
父类静态代码块!
School的构造函数执行[静态属性]!
子类静态代码块!
父类的构造代码块!
父类的构造函数!
Student类的构造函数执行[非静态属性]!
子类的构造代码块!
子类构造函数!
简述JAVA类的生命周期的更多相关文章
- Java类的生命周期详解
引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告 ...
- 【转】Java 类的生命周期详解
一. 引 言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大 ...
- 【转载】详解java类的生命周期
原文地址:http://blog.csdn.net/zhengzhb/article/details/7517213 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑, ...
- [Java]类的生命周期(上)类的加载和连接[转]
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java ...
- JVM类加载器及Java类的生命周期
预定义类加载器(三种): 启动(Bootstrap)类加载器: 是用本地代码实现的类装入器,它负责将<Java_Runtime_Home>/lib下面的类库加载到内存中(比如rt.jar) ...
- JVM-类加载过程(Java类的生命周期)
什么是类加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的 ...
- Java类的生命周期(转)
引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告 ...
- 详解Java类的生命周期
引言 最近有位细心的朋友在阅读笔者的文章时,对Java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内Java方面的教材大多只是告 ...
- Java类的生命周期浅析
类的生命周期?对象的生命周期?Spring bean 的生命周期?很多同学可能在学习java基础知识之初,很容易把这几个搞混.本文先来说说Java类的生命周期. 目录 知识前提 类的生命周期 加载(L ...
随机推荐
- POJ1845Sumdiv题解--约数之和
题目链接 https://cn.vjudge.net/problem/POJ-1845 分析 \(POJ\)里的数学题总是这么妙啊 首先有一个结论就是\(A=\prod{ \ {p_i}^{c_i} ...
- QT打开文件或文件夹或网络地址
打开文件或文件夹 如果是文件或文件夹 必须带file:/// 后面可以是文件(夹)的绝对路径 QDesktopServices::openUrl(QUrl("file:///C:/Docum ...
- 03 - Mongodb数据查询 | Mongodb
1.基本查询 ①方法find():查询 db.集合名称.find({条件文档}) ②方法findOne():查询,只返回第一个 db.集合名称.findOne({条件文档}) ③方法pretty(): ...
- 0基础学习web技术
说实话0基础学习前端挺难的,当然也没有是技术是容易学习的 我只是想分享一下我的学习经历: 分为以下几点: 1:学习html和css ,学习完成之后可以模仿各大网站的静态网页 2:学习原生js基础,jq ...
- 如何使用Chrome开发者工具找到Marketing Cloud某个contact的guid
我们使用nodejs对contact进行修改时,需要指定待修改contact实例的guid. 这个guid属于technical属性,在Marketing Cloud UI上默认情况下不可见.如何找到 ...
- RabbitMQ的持久化(六)
RabbitMQ的持久化主要体现在三个方面,即交换机持久化,队列持久化及消息持久化 注意,因公司使用php-amqplib来实现RabbitMQ,故之后举例说明的代码均使用的php-amqplib,而 ...
- 轻量化模型之SqueezeNet
自 2012 年 AlexNet 以来,卷积神经网络在图像分类.目标检测.语义分割等领域获得广泛应用.随着性能要求越来越高,AlexNet 已经无法满足大家的需求,于是乎各路大牛纷纷提出性能更优越的 ...
- kubernetes容易混淆的几个端口
k8s服务的配置文件中几个端口参数,nodePort.port.targetPort,刚开始的时候不理解什么意思很容易混淆写错,这里总结一下,概括来说就是nodePort和port都是k8s的serv ...
- macos下简单的socket服务器+客户端
TCP客户端服务器编程模型: 服务器: 调用socket函数创建套接字 调用bind绑定本地IP和端口 调用listen启动监听(准备好接收客户端链接的队列) 调用accept从已连接队列中提取第一个 ...
- Pycharm Community 配置 Django 开发环境
1. 安装数据库可视化工具 Database Navigator 2. 括号匹配高亮工具 HighlightBracketPair (...) Web 开发放弃 Pycharm Community 版 ...