Java基础之类加载机制及反射

本文详细介绍了Java中类的加载过程,包括加载、连接和初始化三个阶段,以及类加载器的工作原理。阐述了类初始化的时机及类加载器的层次结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类的加载、连接和初始化:

   1.JVM和类:

     当调用Java命令运行某个Java程序时,该命令将会启动一个Java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少个线程,它们都处于该Java虚拟机进程中。

      以下几种情况JVM进程将会被终止:   

         1).程序运行到最后正常结束;

         2).程序运行到使用System.exit()或Runntime.getRuntime().exit()代码处结束程序;

         3).程序执行过程中遇到未捕获的异常或错误而结束;

         程序所在平台强制结束了JVM。

   在两个JVM之间并不会共享数据。

   2.类的加载:

      当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来对该类进行初始化。

      类加载指的是将类的class文件读入内存,并为之创建 一个java.lang.Class对象,当程序使用任何类时,系统都会为之建立一个java.lang.Class对象。

     类加载由类加载器完成,类加载器通常由JVM提供,JVM提供的是系统加载器,除此之外可通过继承ClassLoader基类来创建自己的类加载器。

     通过不同的的类加载器可以从不同来源加载类的二进制数据:

        1). 从本地文件系统加载class文件;

        2).从JAR包加载class文件,如JDBC加载数据库驱动类;

        3).通过网络加载class文件;

         把一个Java源文件动态编译,并执行加载。

   3.类的连接:

      当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中,类连接分为三个阶段:

        1).验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致;

        2).准备:类准备阶段则负责为类的类变量分配内存,并设置默认初始化值;

        3). 解析:将类的二进制数据中的符号引用替换成直接引用。

   4.类的初始化:

      在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对类变量进行初始化。在Java类变量指定初始化值有两种方式:声明类变量指定初始化;使用静态初始化块为类变量指定初始化值。

      JVM初始化一个类包含以下几个步骤: 

        1).假如这个类还没有被加载和连接,则程序先加载并连接该类;

        2). 假如该类的直接父类还没有被初始化,则先初始化其直接父类;

        3).假如类中有初始化语句,则系统依次执行这些初始化语句。

  5.类的初始化的时机:

     当Java程序首次通过下面6种方式来使用某个类或接口时,系统就会初始化该类或接口:

        1).创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例;

        2).调用某个类的类方法(静态方法);

        3).访问某个类或接口的类变量,或为该类变量赋值;

        4).使用反射方式来强制创建某个类或接口对应的java.lang.Class对象;

        5).初始化某个类的子类,当初始化某个类的子类该子类的所有父类都会被初始化;

        6).直接使用java.exe命令来运行某个主类。当运行某个主类时,程序会先初始化该主类。

二、类加载器:

  类加载器负责所有的类,系统为所有被载入内存中的类生成一个java.lang.Class实例。一旦一个类被载入JVM中,同一个类就不会被再次载入。

   当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:

      1).Bootstrap ClassLoader:根类加载器,负责加载Java的核心类;

      2).Rxtension ClassLoader:扩展类加载器,负责加载JRE的扩展目录(%JAVA_HOME%/jre/lib/ext或由java.ext.dir系统属性指定的目录)中JAR包的类;

      3).Sytem ClassLoader:系统加载器,负责在JVM启动时加载来自java命令的-classpath选项、java.class.path系统属性,或CLASSPATH环境变量所指定的JAR包和类。路径,程序可通过ClassLoader的静态方法getSystemClassLoader()来获取系统类加载器。如没特殊指定,则用户自定义的类加载器都类加载器作为父加载器。

    1.类加载机制:

        主要由三种:

           1).全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显式使用另外一个类加载器来载入;

           2).父类委托:先让父类加载器试图加载该Class,只有在父类加载器无法加载时才尝试从自己的类路径中加载该类;

           3).缓存机制:将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区中。

   类加载器加载Class大致为八个步骤:

      1).检测此Class是否载入过,如有则进入8否则执行2;

      2).如果父类加载器不存在,则跳4,如父加载器存在则执行3;

      3).请求使用父类加载器去载入目标类,如成功载入则跳8,否则执行5;

      4).请求使用根类加载器尝试寻找Class,如找到执行6,如找不到跳7;

      5).当前类加载器尝试寻找Class文件,如找到执行6,如找不到跳7;

      6).从文件中载入Class,成功载入跳8;

      7).抛出ClassNotFoundException异常;

      8).返回对应的java.lang.Class对象。

    2.反射:

       获取Class对象:

         1).使用Class类的forName(String className)静态方法,该方法传入的字符串参数是某个类的全限定类名;

         2).调用某个类的class属性来获取该类对应的Class对象;

         3).调用某个对象的getClass()方法。

    3.使用反射生成并操作对象:

         1).创建对象:使用Class对象的newInstance()方法来创建该Class对应类的实例;

使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建Class对象的实例;

         2).调用方法:通过Class对象的getMethods()方法获取指定的方法,再用invoke方法去调用方法;

         3).访问成员变量:使用getFields()方法去获取该类所包含的全部成员变量。

    4.使用反射生成JDK动态代理:

       proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果在程序中为一个或多个接口动态地生成实现类,就可以使用proxy来创建动态代理类;如需要为一个多个接口动态地创建实例,也可以使用proxy来创建爱你动态代理实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值