zoukankan      html  css  js  c++  java
  • java类的加载与加载器

    java代码在计算机中经历的三个阶段:

    1.Source源代码阶段(代码还是在硬盘上,并没有进入内存)   Student.java 通过javac编译 Student.class字节码文件

    2.类加载器ClassLoader将字节码文件加载进入内存,成为Class类对象(成员变量Field[ ] fields、构造方法Constructor[ ] constructors、成员方法Method[ ] methods)

    3.运行时阶段new Student后

    Student s=new Student(); 是我们自己创建的一个类,java加载类时,用到哪个类会将该类加载。(边用边加载)

    JVM如何加载Student这个类?(加载-链接-初始化)

    1.JVM把Student这个类的Class对象加载进来了

    第一次加载该类时,JVM先从磁盘上找到该类的字节码文件(Student.class),JVM从系统环境变量的CLASSPATH里面找字节码文件的搜索路径。

    .;%JAVA_HOME%lib;%JAVA_HOME%lib ools.jar;%JAVA_HOME%libdt.jar(.代表CLASSPATH工程目录下(如要找Student类,要找对应的Module下找要加载的类),如果不是自己写的,会在后面的jdk库里面找字节码文件(如:System类.out等),将系统写好的打包放在架包里

    通过类加载器,从Student.class字节码文件中,把这个类的各种信息(类名、类的属性和方法)先加载到JVM中,这些信息的集合(相当于人的户口信息)称作Class对象(大写C)

     2.链接:验证类的Class对象的合法性,开辟内存空间。

    准备、验证的过程,验证当前类能够在JVM上运行(检车类的Class对象),给类的static静态成员开辟内存空间,如果当前类还有基类,继续加载其基类(执行1.2.3步)。

    3.初始化

    给static静态成员初始化,调用类的static静态初始化块

    到此,类的加载完成了!

    实例分析: 

    package com.load;
    /**
     * 验证类的加载
     * 任何东西.的时候,后面都会有class;
     * 2019/10/31
     */
    public class ClassLoadTest {
        public static void main(String[] args) throws Exception{
            //第一种加载类的方式,只是加载类的Class对象(只做了第一步)
            Class c1=Student.class;//获取类的Class对象
            //第二种加载类的方式 forName()方法(做了三步,加载-链接-初始化),
    //里面参数是包名.类名,会给静态变量分配空间并初始化、加载静态方法和静态块
    Class c2=Class.forName("com.load.Student");//包路径
    //new对象加载类
    Student s3=new Student();
    } } class Student{ private String name; private int age; private String sex; private static String school=method01(); static { System.out.println("类的静态初始化块!"); school="西安工业大学"; } private static String method01() { System.out.println("初始化类的静态成员变量!"); return "default"; } public Student(String name,int age,String sex){ this.name=name; this.age=age; this.sex=sex; } }

    三种加载类的方式:

    1. 第一种加载类的方式,只是加载类的Class对象(只做了第一步)
    Class c1=Student.class;  //获取类的Class对象

    多用于参数的传递
    2. 第二种加载类的方式 forName()方法(做了三步,加载-链接-初始化),
     里面参数是包名.类名,会给静态变量分配空间并初始化、加载静态方法和静态块
     Class c2=Class.forName("com.load.Student"); //包路径
    当加载Student类时,到第二步给成员变量分配内存空间时,要看这个类有没有基类,有基类时要先加载基类,执行一二三步,该基类若还有基类,则继续向上递归执行;

    多用于配置文件,将类名定义在配置文件中。读取文件,加载类!

    3.生成对象,首先会加载类,会打印实例化块和构造函数

    Student s=new Student; Class c=s.getClass();

    多用于对象的获取字节码的方式

     结论:同一个字节码文件(*.class)在依次程序运行过程中,只会被加载一次,不管通过哪种方式获取的Class对象都是同一个。

    JVM方法区(method area)Class对象信息,static 成员变量。类加载的时候就在方法区开辟空间,一般持续到程序结束。

    类加载器:

    访问类的第三种方式:Student s=new Student();   Class c3=s.getClass();( //通过访问类.class(第一步)) 

    System.out.println(s3.getClassLoad());          //(获取类的加载信息)   打印结果:sun.misc.Launcher$AppClassLoader@18b4aac2

     JVM的功能之一:提供类加载器加载类  

    打印系统定义的类的加载器时,结果为null                                                                          System.out.println(String.class.getClassLoader());

    打印AppClassLoader的父类加载器sun.misc.Launcher$ExtClassLoader@1b6d3586        System.out.println(c3.getClassLoader().getParent());

    再打印ExtClassLoader的父类为null                                                                                     System.out.println(c3.getClassLoader().getParent().getParent());

    因为java的jJVM是用C/C++写的,启动JVM时,本质上是一个C++程序。

    BootstrapClassLoader(原生类加载器)         C:Program FilesJavajdk1.8.0_192jrelib
             是用原生代码编写(c&c++),负责加载JVM运行依赖的jar包

     可知,三个加载器的继承关系:          JVM默认提供的类加载器

              * BootstrapClassLoader(原生类加载器) C:Program FilesJavajdk1.8.0_192jrelib
                 是用原生代码编写(c&c++),负责加载JVM运行依赖的jar包
                     |
              * ExtClassLoader(扩展类加载器)  加载java的扩展库        C:Program FilesJavajdk1.8.0_192jrelibext
                     |
              * AppClassLoader(应用类加载器)           CLASSPATH路径下去加载相应的字节码文件
                (SystemClassLoader)

    类加载器都是通过"双亲委托模型"来加载类的,什么意思?好处是什么?
    双亲委托模型:遇见一个需要加载的类,Student类理应由AppClassLoader来加载,实际上AppClassLoader先请求它的父类ExtClassLoader看能否加载Student类, ExtClassLoader在往上请求BootstrapClassLoader能否加载Student类;实际上BootstrapClassLoader无法加载Student类,ExtClassLoader也无法加载Student类,最后只能由AppClassLoader自己加载Student类,Student类就是这样加载起来的,把这种加载方式称为“双亲委托模型"


    好处:是防止类被重复的加载  String str = new String();

  • 相关阅读:
    SQL Server 2008数据库镜像+故障转移集群原理摘自网络
    AHCI和IDE区别,和在目前系统中设置 AHCI 摘自网络
    中国计算机技术职业资格网(软考 官方 官网)
    第十一节 导出Excel 简单
    第五章 IF语句与逻辑运算符 简单
    第十一节 10图片权限控制 简单
    第四章 C++数据类型 简单
    第二章 从一个最简短的C++程 简单
    php 解析xml文件 简单
    第十一节 6HttpHandler案例 简单
  • 原文地址:https://www.cnblogs.com/laurarararararara/p/11773625.html
Copyright © 2011-2022 走看看