在java代码中,类型的加载,链接,和初始化都是在程序运行期间完成的
1,加载:加载类的class文件中的二进制数据到内存中,把它放在运行时数据区的方法区中,并且在内存中创建一个java.lang.class对象,用来封装类在方法区中的数据结构
加载class文件的方式:
1)从本地系统中直接加载
2)通过网络下载class文件
3)从zip,jar等归档文件中加载class文件
加载的顺序:
1)调用findLoadedClass方法查看是否已经被加载过,如果是,那么直接返回,反之进入第二步
2)一步步调用父类的loadClass方法,如果父类为null,那么调用根类加载器,因为只有根类加载器是没有父类加载器的,如 果加载成功,就返回一个class对象,如果失败,进入第三步
3)调用自定义的findClass,当然这是存在于是自定义的类加载器中,如果有这个方法,就调用,否则就抛出异常
类加载器的命名空间:每个类加载器都有自己的命名空间,命名空间由该类加载器及所有父加载器所加载的类组成
1)在同一个命名空间中,不会出现类的完整名(包括包名)相同的两个类
2)在不同的命名空间中,有可能出现类的完整名字(包括包名)相同的两个类,比如:自定义的类加载器,实例化两个对象,分别去加载指定路径并且不在项目中的class文件,A加载了class文件,然后B去加载的时候,自己是没有加载过的,所以这是不同的命名空间
2,链接:就是将已经读到内存中的二进制数据合并到虚拟机的运行环境中去
1)验证:确保加载的类的正确性,检查内容为:类文件的结构,语义检查,字节码验证,二进制兼容性验证
2)准备:为类的静态变量分配内存空间,并且初始化为默认值
3)解析:将符号引用转成直接引用
3,初始化:为类的静态变量赋予正确的初始值,类或者接口在首次主动使用的时候被初始化
主动使用的的方式:
1)创建类的实例
2)访问类的静态变量,或者为静态变量赋值
3)访问类的静态方法
4)反射(forName方法)
5)初始化一个类的子类
6)标明为启动类的类
java虚拟机生命周期结束的4种情况:
1)执行了system.exit()方法
2)遇到异常,没捕捉到,异常结束
3)程序执行完毕
4)系统发生错误(这一点是无法控制的)
类加载器的两种类型:
1,java虚拟机自带的加载器
1)根类加载器/BootStrap ClassLoader
2)扩展类加载器/Extension
3)系统(应用)类加载器/app
2,用户自定义的类加载器
1)是java.lang.classLoader的子类
2)用户可定制类的加载方式
类的初始化步骤:
1,假如这个类没被加载和链接,那就先进行加载和链接,
2,假如类存在父类,并且父类还没有初始化,那就先初始化直接父类
3,假如类中存在初始化语句,那就依次执行语句
类在初始化的时候会要求其所有父类都初始化,但不要求其实现的接口初始化,接口初始化的时候,父接口并不会要求初始化,