类加载

    科技2024-10-17  25

    一、类的加载与ClassLoader的理解

    1.加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象(一个类只有一个Class对象) 2.链接: 将Java类的二进制代码合并到JVM的运行状态之中的过程。 (1)验证:确保加载的类信息符合JVM规范,没有安全方面的问题 (2)准备:正式为类变量(static) 分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。 (3)解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。(调用常量不需要初始化类) 3.初始化: (1)执行类构造器<clinit> ()方法的过程。类构造器<clinit> ()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。 (2)当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化(双亲委派:收到类加载指令,将请求交给父类完成,父类加载器完成不了,再交给子类加载,始终得到一个Object对象)。 (3)虚拟机会保证一个类的<clinit> ()方法在多线程环境中被正确加锁和同步。

    二、什么时候会发生类初始化?

    1.类的主动引用(一定会发生类的初始化) (1)当虚拟机启动,先初始化main方法所在的类 (2)new一个类的对象 (3)调用类的静态成员(除了final常量)和静态方法 (4)使用java.lang.reflect包的方 法对类进行反射调用 (5)当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类 2.类的被动引用(不会发生类的初始化) (1)当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化(父类拥有static int b =2,当子类调用b时,不会导致子类初始化) (2)通过数组定义类引用,不会触发此类的初始化(Son[] array = new Son[5] ) (3)引用常量(被final修饰)不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)

    三、类加载器

    类加载器的作用 1.类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象, 作为方法区中类数据的访问入口。 2.类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存) 一段时间。 不过JVM垃圾回收机制可以回收这些Class对象

    启动类加载器(BootstrapClassloader):用C++编写的, 是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库。该加载器无法直接获取

    扩展类加载器(ExtensionClassloader):负责jre/ib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入,工作库

    系统类加载器(SystemClassloader也叫应用类加载器):负责java - classpath或-Djava.class. path所指的目录下的类与jar包装入工作,是最常用的加载器

    四、反射操作泛型

    1.Java采用泛型擦除的机制来引入泛型, Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除(泛型擦除) 2.为了通过反射操作这些类型, Java新增了ParameterizedType , GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归到Class类中的类型但是又和原始类型齐名的类型., (1)ParameterizedType :表示一种参数化类型,比如Collection<String> (2)GenericArrayType :表示一种元素类型是参数化类型或者类型变量的数组类型 (3)TypeVariable :是各种类型变量的公共父接口 (4)WildcardType :代表一种通配符类型表达式  

     

    Processed: 0.036, SQL: 8