类初始化,类加载,类加载器

类初始化,类加载,类加载器

  • 1. 类加载
    • 1.1. 类的加载
    • 1.2. 类的链接
      • 1.2.1. 验证
      • 1.2.2. 准备
      • 1.2.3. 解析
  • 2. 类加载器
    • 2.1. 类加载器分为四种:前三种为虚拟机自带的加载器。
    • 2.2. 类加载有三种方式:
    • 2.3. **JVM类加载机制**
    • 2.4. 双亲委派机制
  • 3. 类的初始化
    • 3.1. 类的主动引用会发生类的初始化
    • 3.2. 类的被动引用不会发生类的初始化
    • 3.3. 类缓存

在这里插入图片描述

1. 类加载

1.1. 类的加载

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

  • 类的加载的最终产品是位于堆区中的 Class对象, Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

  • 在加载阶段,虚拟机需要完成以下三件事情:

    • 通过一个类的全限定名来获取其定义的二进制字节流。
    • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    • 在Java堆中生成一个代表这个类的 java.lang.Class对象,作为对方法区中这些数据的访问入口。
  • 加载.class文件的方式

    • 从本地系统中直接加载
    • 通过网络下载.class文件
    • 从zip,jar等归档文件中加载.class文件
    • 从专有数据库中提取.class文件
    • 将Java源文件动态编译为.class文件

1.2. 类的链接

  • 将java类的二进制代码合并到JVM的运行状态中的过程

1.2.1. 验证

  • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
  • 验证阶段大致会完成4个阶段的检验动作:
    • 文件格式验证:验证字节流是否符合Class文件格式的规范;例如:是否以 0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。
    • 元数据验证:对字节码描述的信息进行语义分析(注意:对比javac编译阶段的语义分析),以保证其描述的信息符合Java语言规范的要求;例如:这个类是否有父类,除了 java.lang.Object之外。
    • 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
    • 符号引用验证:确保解析动作能正确执行。

1.2.2. 准备

  • 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配

该阶段有以下几点需要注意:

  • 1、这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。
  • 2、这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。
  • 3、如果类字段的字段属性表中存在 ConstantValue属性,即同时被final和static修饰,那么在准备阶段变量value就会被初始化为ConstValue属性所指定的值。

假设一个类变量的定义为: public static int value=3;那么变量value在准备阶段过后的初始值为0,而不是3,因为这时候尚未开始执行任何Java方法,而把value赋值为3的 public static指令是在程序编译后,存放于类构造器 <clinit>()方法之中的,所以把value赋值为3的动作将在初始化阶段才会执行

  • 对基本数据类型来说,对于类变量(static)和全局变量,如果不显式地对其赋值而直接使用,则系统会为其赋予默认的零值,而对于局部变量来说,在使用前必须显式地为其赋值,否则编译时不通过。
  • 对于同时被static和final修饰的常量,必须在声明的时候就为其显式地赋值,否则编译时不通过;而只被final修饰的常量则既可以在声明时显式地为其赋值,也可以在类初始化时显式地为其赋值,总之,在使用前必须为其显式地赋值,系统不会为其赋予默认零值。
  • 对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。
  • 如果在数组初始化时没有对数组中的各元素赋值,那么其中的元素将根据对应的数据类型而被赋予默认的零值。

1.2.3. 解析

  • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
  • 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。符号引用就是一组符号来描述目标,可以是任何字面量。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

2. 类加载器

2.1. 类加载器分为四种:前三种为虚拟机自带的加载器。

  • 启动类加载器(Bootstrap)C++
    • 负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
  • 扩展类加载器(Extension)Java
    • 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/ext/ *.jar或-Djava.ext.dirs指定目录下的jar包的一些jar包
  • 应用程序类加载器(AppClassLoader)Java
    • 也叫系统类加载器,负责加载classpath中指定的jar包及目录中class
  • 用户自定义加载器 Java.lang.ClassLoader的子类,用户可以定制类的加载方式

2.2. 类加载有三种方式:

  • 1、命令行启动应用时候由JVM初始化加载
  • 2、通过Class.forName()方法动态加载
  • 3、通过ClassLoader.loadClass()方法动态加载

2.3. JVM类加载机制

  • 全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
  • 父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
  • 缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效

2.4. 双亲委派机制

  • 双亲委派机制:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上。
    • 1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
    • 2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
    • 3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
    • 4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载
    • 5、如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException
  • 好处:
    • 防止内存中出现多份同样的字节码(安全性角度)

      • 比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object对象。
    • 保证Java程序安全稳定运行

3. 类的初始化

在Java中对类变量进行初始值设定有两种方式:①声明类变量时指定初始值;②使用静态代码块为类变量指定初始值。

  • 特点
    • 执行类构造器<clinit>()方法的过程。
      • 类构造器<clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)
    • 当初始化一个类时,如果其父类还没有进行初始化,则先触发其父类的初始化
    • 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步

3.1. 类的主动引用会发生类的初始化

  • 当虚拟机启动,会先初始化main方法所在的类
  • new一个类的对象
  • 调用类的静态成员(除了final常量)和静态方法
  • 使用Java.lang.reflect包的方法对类进行反射调用
  • 初始化一个类时,其父类如果没有初始化,则会先初始化它的父类

3.2. 类的被动引用不会发生类的初始化

  • 访问一个静态域时,只有真正声明这个域的类才会被初始化。如:通过子类引用父类的静态变量,不会导致子类初始化
  • 通过数组定义类引用,不会触发此类的初始化
  • 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)

3.3. 类缓存

标准的javaSE类加载器可以按要求查找类,一旦某个类 被加载到类加载器中,它将维持加载(缓存)一段时间。但是JVM垃圾回收机制可以回收这些Class对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/163207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GeoTrust通配符证书:保护您的网站安全

GeoTrust通配符 SSL证书是一种特殊的 SSL 证书类型&#xff0c;它可以同时为您的主域名及其所有子域提供安全保护。无论您有多少个不同的子域需要保障&#xff0c;都可以通过单一的 GeoTrust 通配符 SSL 证书轻松实现&#xff0c;极大地简化了管理流程并降低了成本。 此外&…

1688商品详情数据接口(1688.item_get)

1688商品详情数据接口是一种程序化的接口&#xff0c;通过这个接口&#xff0c;商家或开发者可以使用自己的编程技能&#xff0c;对1688平台上的商品信息进行查询、获取和更新。这个接口允许商家根据自身的需求&#xff0c;获取商品的详细信息&#xff0c;例如价格、库存、描述…

JUC(Java Util Concurrent)多线程并发库

JUC&#xff08;Java Util Concurrent&#xff09;是Java中用于编写多线程并发程序的库。开发过程中使用JUC主要有以下几个好处&#xff1a; 1. 提高程序性能&#xff1a;使用JUC可以实现多线程并发执行&#xff0c;充分利用多核CPU&#xff0c;提高程序的性能。 2. 简化代码…

群晖NAS搭建WebDav服务做文件共享,可随时随地远程访问

文章目录 1. 在群晖套件中心安装WebDav Server套件1.1 安装完成后&#xff0c;启动webdav服务&#xff0c;并勾选HTTP复选框 2. 局域网测试WebDav服务2.1 下载RaiDrive客户端2.2 打开RaiDrive&#xff0c;设置界面语言可以选择中文2.3 点击添加按钮&#xff0c;新建虚拟驱动区2…

从事软件测试8年,对业务测试人员的一些思考

自从事测试工作八年多以来&#xff0c;经历过三个部门多条业务线&#xff0c;也经历过测试转型再回到测试&#xff0c;在此过程中对测试工作和角色的认知也逐步有些思考&#xff0c;想把这些思考分享给大家&#xff0c;希望为业务测试同学提供一些有价值的思路。 同时&#xff…

YOLOV7主干改进,使用fasternet轻量化改进主干(完整教程)

1&#xff0c;Pconv&#xff08;来自Fasternet&#xff09;&#xff08;可作为模型中的基础卷积模块使用&#xff09; 论文链接&#xff1a;https://arxiv.org/abs/2303.03667 2&#xff0c;为了大家方便的使用&#xff0c;这里我对原本的PConv的代码做了部分的改动&#xff0…

立哥尖端技术-云安全整合方案

云安全管理中心 安全管理中心具有集中管控云环境整体安全态势的功能&#xff0c;具备以下功能&#xff1a; &#xff08;1&#xff09;部署方式&#xff1a;与云平台紧耦合&#xff0c;可实现云平台一键下单&#xff0c;自动交付。 &#xff08;2&#xff09;安全态势总览&a…

拿下挣值管理,软考集成你就成功了一半!

在备考软考集成的时候&#xff0c;挣值管理有多重要呢&#xff1f;挣值管理的计算题考的频率非常高&#xff0c;基本上每年都会考。 而且&#xff0c;计算题基本上都是20分左右&#xff0c;只要能在这道计算题上得满分&#xff0c;那么45分及格的考试就已经成功了一半。 今天…

豪华程度堪比飞机头等舱?奔驰在北美发布Tourrider系列巴士

今年三月&#xff0c;奔驰工厂附近出现了一台特殊的测试车。其突出的前保险杠以及竖置双风挡等特殊配置&#xff0c;都在暗示着它并非是为欧洲市场打造。 根据特征推测&#xff0c;这台车应该是为北美市场打造。 就在昨天&#xff0c;奔驰发布了旗下全新Tourrider系列豪华客车&…

python数据分析高效代码合集

文章目录 问题:我有5个dataframe,都包含time 列,如何将它们根据time列取交集,并保存到同一个excel的不同sheet页中。**df1,df2, df3, df4, df5,其也要用取交集后的time列**问题:我有5个dataframe,都包含time 列,如何将它们根据time列取交集,并保存到同一个excel的不同…

npm安装 node-sass

第一步&#xff1a;安装node-gyp 1.: npm install node-gyp -g2.: node-gyp install3.: npm install node-sass

QML24、常规组件StackView

1.简介与示例 StackView管理着view页面的生命周期,提供了页面的栈式导航。这些view页面可能有业务需要,根据业务需要,可以一级一级向深处跳转,根据当前view的状态与设定的情况,可能产生一个新view或者返回之前view 比如:注册账号分步骤,输入用户名,密码,点击下…

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好?

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好&#xff1f; 在某些平台上看到很多人鼓吹嵌入式Linux开发比单片机开发要好&#xff0c;让所有人都去做嵌入式Linux开发。说这种话的人大多数是嵌入式Linux的培训机构&#xff0c;或者是一开始就以嵌入式Linux入门的那一批人…

小型养猪场污水处理技术方案

诸城市鑫淼环保小编带大家了解一下小型养猪场污水处理技术方案 1.初步处理&#xff1a; 猪舍设立固液分离装置&#xff1a;这可以帮助将固体粪便与液体污水分开&#xff0c;减少进一步处理的难度和成本。 设置沉淀池&#xff1a;让分离后的污水在沉淀池内停留&#xff0c;使部分…

Windows更换主板后一直提示,你的pin码不可再用解决办法

最近惠普电脑主板坏了&#xff0c;到售后去维修电脑更换了个主板。 在经过了一系列的重新开机后&#xff0c;就直接卡在了“你的pin码不可再用”那里。 主要症状就是&#xff0c;一直点一直连不上windows的 microsoft账户&#xff0c;点完一会儿黑屏。然后就回到了一开头的“你…

飞书如何接入ChatGPT-打造个人智能问答助手实现无障碍交流

目录 前言 环境列表 1.飞书设置 2.克隆feishu-chatgpt项目 3.配置config.yaml文件 4.运行feishu-chatgpt项目 5.安装cpolar内网穿透 6.固定公网地址 7.机器人权限配置 8.创建版本 9.创建测试企业 10. 机器人测试 总结 前言 在飞书中创建chatGPT机器人并且对话&am…

python连接数据库的方式

python连接数据库的方式 pyzenith.connect&#xff08;&#xff09;函数就是连接数据库&#xff1b; exception.ScriptException&#xff08;&#xff09;这一句是自定义异常&#xff0c;可以不用我这个&#xff1b; finally里面还有一个try finally是有必要的&#xff0c;防止…

抖音汽车租赁小程序技术指南:开发高效便捷的租赁系统

为了更好地满足用户需求&#xff0c;抖音汽车租赁小程序成为一个备受关注的技术解决方案。本文将深入探讨开发高效便捷的汽车租赁系统所需的技术要点&#xff0c;为开发者提供一份实用的技术指南。 小程序架构选择 在搭建抖音汽车租赁小程序时&#xff0c;选择合适的小程序架构…

【Rust】从零开始的rust学习嗷

Rust Rust是什么&#xff1f;安装rust在Linux或者Mac OS&#xff1a;在Windows&#xff1a;更新与卸载 rust起步写我们的第一个程序&#xff0c;hello worldcargo使用cargo创建项目cargo基本命令 才来实习&#xff0c;由于部门使用的SDK是rust语言&#xff0c;所以先浅浅进行ru…

C/C++---------------LeetCode第1436. 旅行终点站

旅行的终点站 题目及要求哈希算法在main内使用 题目及要求 给你一份旅游线路图&#xff0c;该线路图中的旅行线路用数组 paths 表示&#xff0c;其中 paths[i] [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站&#xff0c;即没有任何可…