Java的类是怎么执行的
当我们在调用Java命令运行一个Java程序时,该命令会启动一条Java虚拟机的进程。
当程序主动使用某个类时:
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。如果该类还未被加载到内存中,jvm会通过加载,连接,初始化来对类进行初始化,通常把这3个步骤统称为类的加载或者类的初始化,
类的加载:
类的加载是指将编译好的类的class文件加载到内存中,随后,系统会创建一个Java.lang.Class对象,也就是说,任何一个类的class文件被加载到内存后,系统都会为之创建一个Java.lang.Class对象。
上述的加载过程是由类加载器来完成的。类加载器通常是由jvm来提供的,jvm提供的这些类加载器称为系统类加载器,除此之外,可以通过继承ClassLoader类来创建自己的类加载器。
类加载器加载的文件有:
项目本地的Java程序编译后的class类文件
项目引用的jar包中的class类文件
项目中通过网络加载的class文件
类的连接:
当类被加载后,会生成一个对应的class对象,接着会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中。
1.验证:验证被加载的类中是否有正确的内部结构,并和其他类协调一致
验证阶段:验证类是否遵从Java类文件的固定格式;会进行语义检查;会确保相互应用的类之间协调一致,比如Work类中有个gotowork的方法,方法中调用了car.run()的方法,Java虚拟机在验证Work类的同时,会检查方法区内是否存在Car类的run方法,如果不存在,会抛异常。
2.准备:为静态属性分布内存,并设置默认初始值
为静态属性分布内存空间;
设置默认初始值:
Java虚拟机会给int类型的静态变量a分配4个字节的内存空间,并设置初始值0,给Long类型的静态变量b分配8个字节的空间,设置初始值为0,当类初始化时,才会将a的值改为1,b改为2
3.解析:将类中的二进制数据中的符号引用替换为直接引用
Java虚拟机会将Work类中gotowork()方法中调用的car.run方法的描述改为指针
类的初始化:
当一个类加载,连接完成后,就会对类进行初始化。类的初始化大体步骤为: 先将类的所有的成员变量进行初始化,待类的成员变量初始化完成后,会调用类的构造方法来构造对象。
类的初始化步骤:
1,当类还没有被加载,连接时,先进行类的加载和连接。
2,如果类的直接父类还没有被初始化,先初始化直接父类。
3,按照类中的初始化语句依次执行初始化语句。
执行初始化语句的顺序:先父后子,静态全完成,再分父与子。父类完成后,再来构造子。
1. 父类(静态成员变量)
2. 父类(静态代码块)
3. 子类(静态成员变量)
4. 子类(静态代码块)
5. 父类(普通成员变量)
6. 父类(普通代码块)
7. 父类(构造函数)
8. 子类(普通成员变量)
9. 子类(普通代码块)
10. 子类(构造函数)
类的加载或初始化时机:
1.创建类的实例(就是去new一个对象时)
2.调用某个类的静态方法时(直接用类名.静态方法)
3.访问某个类或者接口的静态属性时(如果这个静态属性被final修饰,并且编译时值确定,则调用该静态属性时,此类不会被初始化)
4.使用反射机制来强制创建某个类或者接口对应的Java.lang.Class对象(Class.forName("Car"))
5.初始化某个类的子类(初始化一个类时,他的所有父类都会被实例化)
6.直接使用Java.exe命令来运行某个主类
