类加载过程

参考j类加载过程详解
https://blog.csdn.net/ln152315/article/details/79223441
1、加载:这个很简单,程序运行之前jvm会把编译完成的.class二进制文件加载到内存,供程序使用,用到的就是类加载器classLoader ,这里也可以看出java程序的运行并不是直接依 靠底层的操作系统,而是基于jvm虚拟机。如果没有类加载器,java文件就只是磁盘中的一个普通文件。

2、连接:连接是很重要的一步,过程比较复杂,分为三步 验证 》准备 》解析

验证:确保类加载的正确性。一般情况由javac编译的class文件是不会有问题的,但是可能有人的class文件是自己通过其他方式编译出来的,这就很有可能不符合jvm的编 译规则,这一步就是要过滤掉这部分不合法文件

准备为类的静态变量分配内存,将其初始化为默认值 。我们都知道静态变量是可以不用我们手动赋值的,它自然会有一个初始值 比如int 类型的初始值就是0 ;boolean类型初始值为false,引用类型的初始值为null 。 这里注意,只是为静态变量分配内存,此时是没有对象实例的

解析把类中的符号引用转化为直接引用。解释一下符号引用和直接引用。比如在方法A中使用方法B,A(){B();},这里的B()就是符号引用,初学java时我们都是知道这是java的引用,以为B指向B方法的内存地址,但是这是不完整的,这里的B只是一个符号引用,它对于方法的调用没有太多的实际意义,可以这么认为,他就是给程序员看的一个标志,让程序员知道,这个方法可以这么调用,但是B方法实际调用时是通过一个指针指向B方法的内存地址,这个指针才是真正负责方法调用,他就是直接引用。
  
3、初始化:为类的静态变量赋予正确的初始值,上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

堆区:存放对象实例,几乎所有的对象实例都在这里分配内存。

Java程序对类的使用方式可分为两种

  • 主动使用
  • 被动使用

被动使用以后再讲,这里说说什么是主动使用,java对类的主动使用有六种情况

  1. 创建类的实例
  2. 访问某个类或接口的静态变量,或者对该静态变量赋值
  3. 调用类的静态方法
  4. 反射(如Class.forName(“com.shengsiyuan.Test”))
  5. 初始化一个类的子类(先初始化所有的父类,最后初始化本身,接口除外,类初始化的时候,它所实现的接口不会初始化,就算字接口初始化,父接口也不会初始化,只有当程序调用接口的静态变量的时候才会导致接口的初始化)
  6. Java虚拟机启动时被标明为启动类的类(简单说就是拥有main方法的类)
class Test2{
  public static final int n = 2;

  static{
    System.out.println("test");
  }
}

public class Test1 {
  public static void main(String[] args) {
    System.out.println(Test2.n);
  }

}

大家思考一下会出现什么?不管你的答案是什么,正确答案是2 。 Test2中的静态代码块是没有运行的,因为Test2并没有初始化

注意,这里的final关键字不可缺少,我们知道变量被关键字fianl修饰之后就不可修改,亦即此变量相当于编译期常量(是相当于并非就是常量),常量在java编译期已经确定,不需要初始化,但是把fianal去掉,或者把 final int n = 2 改为 final int n = new Random()。,运行的结果将变为 test ,2 ,因为n的值为变量或者n值在编译期不能确定,就必须经过初始化才能使用n的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值