java类的加载与加载器

Wesley13
• 阅读 774

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

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

java类的加载与加载器

 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();

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

java类的加载与加载器

结论:同一个字节码文件(*.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

java类的加载与加载器

 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 Files\Java\jdk1.8.0_192\jre\lib
         是用原生代码编写(c&c++),负责加载JVM运行依赖的jar包

java类的加载与加载器

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

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

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
限时发布!纯手打“RocketMQ笔记”
1JVM的内存区域布局java代码的执行步骤有三点java源码文件编译器字节码文件字节码文件JVM机器码机器码系统CPU执行JVM执行的字节码需要用类加载来载入;字节码文件可以来自本地文件,可以在网络上获取,也可以实时生成。就是说你可以跳过写java代码阶段,直接生成字节码交由JVM执行其中Jav
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这