java类是如何加载的

硅谷探秘者 4066 0 1

首先要知道类的加载的过程包括了加载、验证、准备、解析、初始化五个阶段。

QQ截图20190105142639.png

java虚拟机加载class的过程

        虚拟机把Class文件加载到内存,然后进行校验,解析和初始化,最终形成java类型,这就是虚拟机的类加载机制。加载,验证,准备,初始化这5个阶段的顺序是确定的,类的加载过程,必须按照这种顺序开始。这些阶段通常是相互交叉和混合进行的。解析阶段在某些情况下,可以在初始化阶段之后再开始---为了支持java语言的运行时绑定。

Java虚拟机规范中,没有强制约束什么时候要开始加载,但是,却严格规定了几种情况必须进行初始化(加载,验证,准备则需要在初始化之前开始):

  • 1)遇到 new、getstatic、putstatic、或者invokestatic 这4条字节码指令,如果没有类没有进行过初始化,则触发初始化
  • 2)使用java.lang.reflect包的方法,对垒进行反射调用的时候,如果没有初始化,则先触发初始化
  • 3)初始化一个类时候,如果发现父类没有初始化,则先触发父类的初始化

 

        通过类的全限定名来获取定义此类的二进制字节流,将此二进制字节流所代表的静态存储结构转化成方法区的运行时数据结构,在内存中生成代表此类的java.lang.Class对象,作为该类访问入口.完成加载

验证

        连接阶段第一步.验证的目的是确保Class文件的字节流中信息符合虚拟机的要求,不会危害虚拟机安全,使得虚拟机免受恶意代码的攻击.大致完成以下四个校验动作:

文件格式验证,源数据验证,字节码验证,符号引用验证

准备

        在java虚拟机加载class文件并且验证完毕之后,就会正式给类变量分配内存并设置类变量的初始值。这些变量所使用的内存都将在方法区分配。注意这里说的是类变量,也就是static修饰符修饰的变量,在此时已经开始做内存分配,同时也设置了初始值。比如在 Public static int value = 123 这句话中,在执行准备阶段的时候,会给value分配内存并设置初始值0, 而不是我们想象中的123. 那么什么时候 才会将我们写的123 赋值给 value呢?就在下下面要讲的初始化阶段。

解析

        将常量池中的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法),这个可以在初始化之后再执行。可以认为是一些静态绑定的会被解析,动态绑定则只会在运行是进行解析;静态绑定包括一些final方法(不可以重写),static方法(只会属于当前类),构造器(不会被重写)

初始化

        类初始化阶段是类加载过程的最后阶段。在这个阶段,java虚拟机才真正开始执行类定义中的java程序代码。Java虚拟机是怎么完成初始化的呢?这要从编译开始讲起。在编译的时候,编译器会自动收集类中的所有静态变量(类变量)和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是根据语句在java代码中的顺序决定的。收集完成之后,会编译成java类的 static{} 方法,java虚拟机则会保证一个类的static{} 方法在多线程或者单线程环境中正确的执行,并且只执行一次。在执行的过程中,便完成了类变量的初始化。值得说明的是,如果我们的java类中,没有显式声明static{}块,如果类中有静态变量,编译器会默认给我们生成一个static{}方法。

为了加深理解,我写了个demo,仔细理解一下
class A {
	static {
		System.out.println(B.b+" **");
	}
	public static B b=B.b;
	
}

class B extends A{
	static {
		System.out.println("A");
	}
	public static B b=new B();
	
	public static void main(String[] args) {
		System.out.println(A.b);
	}
}
结果输出:
null **
A
null
class A {
	static {
		System.out.println(B.b+" **");
	}
	public static B b=B.b;
	
}
class B extends A{
	static {
		System.out.println("A");
	}
	public static B b=new B();
}
public class C{
	public static void main(String[] args) {
		System.out.println(A.b);
	}
}
结果输出:
A
club.test.controller.B@3d4eac69 **
club.test.controller.B@3d4eac69
package jvm;
class A {
	static {
		System.out.println(B.b+" **");
	}
	public static B b=B.b;
}
class B extends A{
	static {
		System.out.println("A");
	}
	public static B b=new B();
}
public class C{
	public static void main(String[] args) {
		B b=new B();
		System.out.println(A.b);
	}
}
结果输出:
null **
A
null

 


评论区
请写下您的评论...
暂无评论...
猜你喜欢
java虚拟机(jvm) 5120 Java器(英语:JavaClassloader)Java运行时环境(JavaRuntimeEnvironment)一部分,负责动态JavaJava虚拟机内存空间中。
java虚拟机(jvm) 5108 器虚拟机设计团队把阶段中“通过一个全限定名来获取描述此二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定去获取所需要。实现这个动作代码
spring/springmvc 2467 创建一个MarkControllerMarkController上有@RestController注解
算法基础 1241 Java中遍历集合方式以list集合为例,有三种遍历方式。ListStringlist=newArrayList(); list.add("2"); list.add("2"); list.add
spring/springmvc 3669 有时项目在初始化会有一些配置(bean)入ioc容器,在项目完成后该bean就没有用了,可以从ioc容器中销毁。具体
weblog 1557 java判断请求浏览器ie浏览器importjavax.servlet.http.HttpServletRequest;/*** 浏览器型判断*@author硅谷探秘者(jia
其他 9321 在一本书上看到过子可以重方法,关于这一点有点疑惑,个人重发生在同一个中。网上关于这个也存在争议。先暂时作为一个问题记录在此下面这张图片引用自《疯狂java讲义第三版》关于重写,遵循以
算法基础 2319 Java反射机制可以让我们获取某个所有信息,本文要聊获取某个,某个属性,某个方法修饰符。或判断某、属性、方法上否有某个修饰符。在Class、Field、Method这三
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。