您的位置:1010cc时时彩经典版 > 1010cc时时彩经典版 > 【1010cc时时彩经典版】类加载机制,java类加运载

【1010cc时时彩经典版】类加载机制,java类加运载

发布时间:2019-08-10 21:41编辑:1010cc时时彩经典版浏览(189)

    java类加载机制,java加载机制

    java中通过JVM加载类文件,类加载方式分为隐式加载和显式加载。其中,隐式加载时通过new创建对象时,隐式的通过类加载器将相应的类文件加载到JVM中。显式加载通过class.forName()显式方式把所需的类文件加载到JVM中。

    在java语言中,类的加载时动态的,并不是一次将所有的类文件都加载到JVM中,而是先将基础类加载到JVM中,其他用户类等需要时在加载到JVM中。

    在java语言中,类可以分3类:系统类、扩展类和自定义类,针对这3类文件提供了不同的类加载器

        Bootstrap Loader  -- 负责加载系统类

         ExtClass Loader -- 负责加载扩展类

                  AppClassLoader   -- 负责加载应用类

     

    类加载过程主要有如下几步:(详细部分可以参考《深入理解java虚拟机》)

       1. 装载 : 根据查找路径找到相应的class文件,然后导入。

       2. 链接: 链接可以分为3步

           (1) 检查: 检查待加载的class文件的正确性

           (2)准备: 将类中的静态变量分配内存空间

           (3)解析:将符号引用解析为直接引用

       3. 初始化: 对静态变量和静态代码块执行初始化工作。

     

    java中通过JVM加载类文件,类加载方式分为隐式加载和显式加载。其中,隐式加载时通过new创建对象时,隐式的...

           (3)解析:将符号引用解析为直接引用

    在java语言中,类可以分3类:系统类、扩展类和自定义类,针对这3类文件提供了不同的类加载器

    从上例可以看出,TestLoader类是由AppClassLoader来加载的。另外需要说明的一点是,由于Bootstrap Loader是用C 语言来实现的,因此,在Java语言中是看不到它的,所以此时程序会输出null。

    二、类加载机制(装载、验证、准备、解析、初始化、使用、卸载)

       2. 链接: 链接可以分为3步

           (3)解析:将符号引用解析为直接引用

    package com.js;
    /**
     * 说明类加载器的工作原理
     * @author jiangshuai
     *
     */
    public class TestLoader {
        public static void main(String[] args){
            //调用Class加载器
            ClassLoader clApp = TestLoader.class.getClassLoader();
            System.out.println(clApp);
            //调用上一层Class加载器
            ClassLoader clExt = clApp.getParent();
            System.out.println(clExt);
            //调用根部Class加载器
            ClassLoader clBoot = clExt.getParent();
            System.out.println(clBoot);
        }
    }
    

    大纲:

           (1) 检查: 检查待加载的class文件的正确性

       3. 初始化: 对静态变量和静态代码块执行初始化工作。

    任何一个工程项目都是由许多个类组成的,当程序启动时,只把需要加载的类加载到JVM中,其他类只有被使用到的时候才会被加载,采用这种方法,一方面可以加快加载速度,另外一方面可以节约程序运行过程中对内存的开销。此外,在Java语言中,每个类或接口都对应一个.class文件,这些文件可以被看成一个个可以被动态加载的单元,因此当只有部分类被修改时,只需要重新编译变化的类即可,而不需要重新编译所有文件,因此加快了编译速度。

    三、类执行机制


    源码编译机制:

    (由.java源文件转为.class二进制字节码文件的过程)

    使用命令 javac test.java 就可以编译test.java文件。生成test.class文件。

    编译的过程:

    词法分析、语法分析、语义分析、生成字节码

    详细的过程:

    源代码文件*.java -> 词法分析器 -> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> JVM字节码文件*.class

    ———————————————————————————————————————————

    类加载机制:

    在Class文件中描述的各种信息,最终都需要加载到虚拟机中才能运行和使用。那么虚拟机是如何加载这些Class文件的呢?

    JVM把描述类数据的字节码.Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制。

    类从被加载到虚拟机内存中开始,到卸载出内存为止,它的生命周期包括了:加载/装载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称链接。

    一、加载

    a.(类的加载指的是将类的.class文件中的二进制数据读入到内存中,生成对应的class对象)我们可以利用类加载器,实现类的动态加载。

    b.在Java中,采用双亲委派机制来实现类的加载。委托模式。每个 ClassLoader 都有一个父加载器。类加载器在加载类之前会先递归的去尝试使用父加载器加载。父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类的时候才试图从自己的类路径加载,从而保证只有一个类进行加载,虚拟机有一个内建的启动类加载器(bootstrap ClassLoader),该加载器没有父加载器,但是可以作为其他加载器的父加载器。

    c.委派机制则保证了基类都由相同的类加载器加载,这样就避免了同一个字节码文件被多次加载生成不同的 Class 对象的问题。

    d.类加载器其实也是Java类。有四大类:

    根加载器Bootstrap Class Loader:其负责加载Java的核心类,比如String、System这些类

    扩展加载器Extension Class Loader:其负责加载JRE的拓展类库

    系统应用加载器APP Class Loader:其负责加载CLASSPATH环境变量所指定的JAR包和类路径

    用户自定义加载器Customer Class Loader

    e.加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所ClassLoader加载一次。然后开始加载类,加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

    f.java程序运行的场所是内存,当在命令行下执行:java HelloWorld命令的时候,JVM会将HelloWorld.class加载到内存中,并形成一个Class的对象HelloWorld.class。

    g.类加载的方式:

    命令行启动应用时候由JVM初始化加载

    通过Class.forName()方法动态加载

    通过ClassLoader.loadClass()方法动态加载

    h.双亲委派模型的工作过程为:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。

    二、链接

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

    三个阶段

    验证:检验被加载的类是否有正确的内部结构,并和其他类协调一致

    准备:负责为类的类(静态)变量分配内存。并设置默认初始值

    准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:

    1、这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。

    2、这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。

    假设一个类变量的定义为:public static int value = 3;

    那么变量value在准备阶段过后的初始值为0,而不是3,因为这时候尚未开始执行任何Java方法,而把value赋值为3的putstatic指令是在程序编译后,存放于类构造器()方法之中的,所以把value赋值为3的动作将在初始化阶段才会执行。

    解析:将类的二进制数据中的符号引用转换成直接引用

    三、初始化

    初始化,为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。

    在Java中对类变量进行初始值设定有两种方式:

    1010cc时时彩经典版,①声明类变量是指定初始值

    ②使用静态代码块为类变量指定初始值

    JVM初始化步骤

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

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

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

    类初始化时机

    创建类实例。也就是new的方式

    调用某个类的类方法

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

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

    初始化某个类的子类,则其父类也会被初始化

    直接使用java.exe命令来运行某个主类

    类实例创建过程

    按照父子继承关系进行初始化,首先执行父类的初始化块部分,然后是父类的构造方法;再执行本类继承的子类的初始化块,最后是子类的构造方法

    注意⚠️:

    JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的, 静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。(链接的准备阶段)

    初始化阶段:

    先初始化父类的静态代码--->初始化子类的静态代码-->

    初始化父类的非静态代码--->初始化父类构造函数--->

    初始化子类非静态代码—>初始化子类构造函数

    分析:静态代码块在类加载的时候执行,而非静态代码快在生成对象时才被执行

    类执行机制:

    JVM是基于栈结构的体系结构来执行class字节码的,不同于windows和Linux基于寄存器结构。类的执行机制,主要是在Java栈上面完成。当一个线程被创建后,Java栈和PC寄存器就会被创建。Java栈由栈帧组成,调用一个方法,就会生成一个栈帧(可以理解为表示调用一个方法)。栈帧又由局部变量表、操作数栈和常量池引用组成。


    其他:

    常量:

    一、用final修饰的成员变量表示常量,值一旦给定就无法改变!一般都用大写字符为常量赋值。在常量中,往往通过下划线来分隔不同的字符。对于同时被static和final修饰的常量,必须在声明的时候就为其显式地赋值,否则编译时不通过;而只被final修饰的常量则既可以在声明时显式地为其赋值,也可以在类初始化时显式地为其赋值,总之,在使用前必须为其显式地赋值,系统不会为其赋予默认零值。

    二、final关键字与static关键字同时使用

    由于Java是面向对象的语言,所以在Java常量定义的时候还有与其它编程语言不同的地方。如一段程序代码从编辑到最后执行,即使需要经过两个过程,分别为代码的装载与对象的建立。不同的过程对于常量的影响是不同的。

    1).不使用static修饰情况:

    例如:final long CURRENT_TIME=System.currentTimeMillis();

    默认情况下,定义的常量是在对象建立的时候被初始化。如果在建立常量时,直接赋一个固定的值,而不是通过其他对象或者函数来赋值,那么这个常量的值就是恒定不变的,即在多个对象中值也使相同的。但是如果在给常量赋值的时候,采用的是一些函数或者对象(如生成随机数的Random对象),那么每次建立对象时其给常量的初始化值就有可能不同。可见,使用final的Java常量定义并不是恒定不变的。

    2).使用static修饰情况:

    例如:static final long CURRENT_TIME=System.currentTimeMillis();

    这个是一个静态的概念。即当利用这个关键字来修饰一个变量的时候,在创建对象之前就会为这个变量在内存中创建一个存储空间。以后创建对对象如果需要用到这个静态变量,那么就会共享这一个变量的存储空间。也就是说,在创建对象的时候,如果用到这个变量,那么系统不会为其再分配一个存储空间,而只是将这个内存存储空间的地址赋值给他。如此做的好处就是可以让多个对象采用相同的初始变量。当需要改变多个对象中变量值的时候,只需要改变一次即可。从这个特性上来说,其跟常量的作用比较类似。不过其并不能够取代常量的作用。


    变量

    类变量:static int allClicks=0;

    局部变量:类的方法中的变量

    public void method(){

    int i =0; //局部变量

    }

    实例变量: String str="hello world";


         ExtClass Loader -- 负责加载扩展类

       1. 装载 : 根据查找路径找到相应的class文件,然后导入。

    其实,它们是通过委托的方式实现的。具体而言,就是当有类需要被加载时,类加载器会请求父类来完成这个载入工作,父类会使用其自己的搜索路径来搜索需要被载入的类,如果搜索不到,才会由子类按照其搜索路径来搜索待加载的类。下例可以充分说明类加载器的工作原理:

    一、编译机制

    本文由1010cc时时彩经典版发布于1010cc时时彩经典版,转载请注明出处:【1010cc时时彩经典版】类加载机制,java类加运载

    关键词: