JVM
Java:跨平台,一次编译到处运行(即在不同的体统中运行)
JVM:跨语言,可以运行多种语言的字节码文件,不单单只是Java语言
JVM结构图:
类加载器子系统:
类加载的过程:
三个阶段: 加载→链接→初始化
1、加载(Loading)
- 就是将编译好的字节码文件加载到虚拟机中,也就是JVM中,相当于一个搬运工,会以流的形式进行传输
- 并且会在内存中生成该字节码的对象
2、链接(Linking)
2.1 验证(Verify)- 也就是验证搬运过来的class字节码文件信息规则是否符合当前虚拟机的要求,以保证当前类加载的正确性
- 规则:文件格式验证,元数据验证,字节码验证,符号引用验证
2.2 准备(Prepare) - 为一个类中定义的变量分配内存并设置默认初始值,根据不同的数据类型设置不同的初始值,例如 int 类型就为0;
- 如果变量被final或者static修饰,在该阶段中就会直接初始化变量值,而不会设置默认值
- 这里不会为实例变量分配初始值。例如:在类中定义一个变量 :int num = 10; 那么在该阶段中,不会初始化num的值为10,而只是会分配num的内存并设置一个初始值为0;
2.3 解析(Resolve)
- 该过程在初始化完成后才执行
- 将常量池内的符号引用转换为直接引用的过程,也就是在反编译字节码文件中将常量池中对应的符号地址转为对应具体的值,如图:类似于地址值指向具体值
- 解析主要针对的是类或者接口、字段、类方法、接口方法、方法类型等。与常量池中的参数一一对应
3、初始化(Initialization)
- 也就是执行类构造器方法()的过程。
- 该方法不需要我们定义,是javac编译器自动收集类中的所有类变量赋值操作和静态代码块中的语句合并而来。也就是给变量属性进行赋值(初始化),包括静态代码块的中属性
- 构造器方法中指令按语句在源文件中出现的顺序执行,也就是代码的执行顺序,是按照一行一行的从上至下走
- ()不同于类的构造器(构造器是虚拟机视角下的()),如果一个类中没有被static修饰的属性或者没有静态代码块,编译后是没有()方法的;()相当于类的无参构造方法
- 如果该类具有父类,JVM会保证在子类()执行前,先执行父类的()。也就是先初始化父类的属性值
- 虚拟机必须保证一个类的()方法在多线程下被同步加锁。也就是多个线程同时访问一个类时,只能有一个线程初始化该类执行()方法,如果有一个线程在执行()方法(初始化类),其它线程都将进不去。