第三章 JVM内存概述
附录:精选面试题
Q:为什么虚拟机必须保证一个类的Clinit( )方法在多线程的情况下被同步加锁 ?
A: 因为虚拟机在加载完一个类之后直接把这个类放到本地内存的方法区(也叫原空间)中了,当其他程序再来调这个类的时候直接从内存中拿的,因此Clinit( )方法只会执行一次来保证类只会被加载一次,当同时有两个线程进来操作同一个类的Clinit( )方法,可能会出现数据的不一致性,当两个线程中的某个线程抢到了类锁,而且一直在Clinit()方法中执行,另一个线程会一直保持阻塞状态
Q: 类加载子系统中的加载阶段分别有哪些类加载器 ?
A: 一般会有BootStarpClassLoader引导类加载器,ExtClassLoader扩展类加载器,ApplicationClassLoder应用类加载器。
Q: 类加载器又分为几种 ?
A: 从官方给的规范来讲,分为两种类加载器,分别是引导类加载器,和自定义类加载器。引导类加载器BootStarpClassLoader是由C语言和C++进行编写的,主要加载Java的核心类库。而直接或间接继承ClassLoader的加载器都可以认为是自定义类加载器,JVM默认提供给用户使用的是继承图最底层的ApplicationClassLoader系统类加载器,ApplicationClassLoader调用getParent( )方法一直往上面调,是获取不到BootStarpClassLoader引导类加载器的。
一、内存结构
当class文件以二进制流的方式加载到JVM内存的类加载子系统时,在类加载子系统(Class Loader SubSystem)中又分三步对数据进行解析,分别是加载阶段(Lading),链接阶段(Linking),初始化阶段(Initiatlizetion)。

加载阶段有:引导类加载器(BootStrapClassLoader),扩展类加载器(ExtensionClassLoder),系统类加载器(ApplicationClassLoder),和自定义加载器。
链接阶段:验证(Verify),准备(Prepare),解析(Resolve)。
最后把数据一起放入初始化阶段。



二、类加载器和类加载过程
ClassLoader 只负责class文件的加载,至于是否可以运行,则有ExecutionEngin(执行引擎) 决定。




Loading加载阶段


链接阶段(Linking)

初始化阶段(Initiatlizetion)

程序加载到初始化阶段<clinit>( )方法会收集静态变量赋值的动作,在连接阶段(Linking)先为静态变量(类变量)赋0值,当程序走到初始化阶段从上到下收集赋值动作,赋值给静态变量。
当类中没有声明过静态变量或者静态代码块时,类加载子系统在进行到初始化阶段时就不会创建<clinit>( )方法。


变量声明在静态代码块的后面,可以在静态代码块进行赋值,但不能进行调用,报错信息为 “非法的前向引用”


任何一个类都会有 init( )方法(用来初始化类对象),但不都有Clinit( )方法(用于收集静态变量,供该类全局使用)

Q:为什么虚拟机必须保证一个类的Clinit( )方法在多线程的情况下被同步加锁。
A: 因为虚拟机在加载完一个类之后直接把这个类放到本地内存的方法区(也叫原空间)中了,当其他程序再来调这个类的时候直接从内存中拿的,因此Clinit( )方法只会执行一次来保证类只会被加载一次,当同时有两个线程进来操作同一个类的Clinit( )方法,可能会出现数据的不一致性,当两个线程中的某个线程抢到了类锁,而且一直在Clinit()方法中执行,另一个线程会一直保持阻塞状态。
三、类加载器的分类

下面这一张图的几种类加载器是等级关系,例如文件目录上下级。但绝不能理解为是 继承关系。BootClassLoader是用C和C++编写的,而下面的几个类加载器是Java语言编写的,都间接继承了ClassLoader。





是一种像文件夹一样的包含关系。A文件夹包含B文件夹,B文件夹又包含着C文件夹,ClassLoader.getSystemClassLoader( ) 方法获取到ApplicationClassLoader。

也可以认为BootStarpClassLoader只负责加载Java程序的核心类库,自定义的加载器太low了,不配“高端”加载器出手帮忙,另外一方面,BootStarpClassLoader是使用C和C++进行编写的,自热而然的就获取不到它的对象了。

public class ClassLoaderTest {public static void main(String[] args) {//获取系统类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2//获取其上层:扩展类加载器ClassLoader extClassLoader = systemClassLoader.getParent();System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@1540e19d//获取其上层:获取不到引导类加载器ClassLoader bootstrapClassLoader = extClassLoader.getParent();System.out.println(bootstrapClassLoader);//null//对于用户自定义类来说:默认使用系统类加载器进行加载ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2//String类使用引导类加载器进行加载的。---> Java的核心类库都是使用引导类加载器进行加载的。ClassLoader classLoader1 = String.class.getClassLoader();System.out.println(classLoader1);//null}
}
引导类、扩展类、系统类加载器的使用及演示
引导类加载器
在上面我们看到,从最底层的systemClassLoader系统类加载器,调用 getParent( )方法会调用到它上层的一个扩展类加载器和应用类加载器对象,这些两个类加载器对象也都需要加载。都是通过BootStarpClassLoader引导类加载器进行加载的,所以也就把BootStarpClassLoader、ExtClassLoader、ApplicationClassLoader都认为是系统核心类库。



扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器扩展类加载器



应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器应用程序类加载器

自定义类加载器自定义类加载器自定义类加载器自定义类加载器自定义类加载器


自定义加载器
package com.atguigu.java1;import java.io.FileNotFoundException;/*** 自定义用户类加载器* @author shkstart* @create 2019 下午 12:21*/
public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] result = getClassFromCustomPath(name);if(result == null){throw new FileNotFoundException();}else{return defineClass(name,result,0,result.length);}} catch (FileNotFoundException e) {e.printStackTrace();}throw new ClassNotFoundException(name);}private byte[] getClassFromCustomPath(String name){//从自定义路径中加载指定类:细节略//如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。return null;}public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader();try {Class<?> clazz = Class.forName("One",true,customClassLoader);Object obj = clazz.newInstance();System.out.println(obj.getClass().getClassLoader());} catch (Exception e) {e.printStackTrace();}}
}

package com.atguigu.java1;/*** @author shkstart* @create 2020 上午 10:59*/
public class ClassLoaderTest2 {public static void main(String[] args) {try {//1.获取引导类加载器 获取不到 nullClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();System.out.println(classLoader);//2.获取系统类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();System.out.println(classLoader1);//3.获取扩展类加载器 sun.misc.Launcher$ExtClassLoader@1b6d3586ClassLoader classLoader2 = ClassLoader.getSystemClassLoader().getParent();System.out.println(classLoader2);} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
相关文章:

第三章 JVM内存概述
附录:精选面试题 Q:为什么虚拟机必须保证一个类的Clinit( )方法在多线程的情况下被同步加锁 ? A: 因为虚拟机在加载完一个类之后直接把这个类放到本地内存的方法区(也叫原空间)中了,当其他程序再来调这个类…...

基于SpringBoot的企业客户信息反馈平台的设计与实现
背景 企业客户信息反馈平台能够通过互联网得到广泛的、全面的宣传,让尽可能多的用户了解和熟知企业客户信息反馈平台的便捷高效,不仅为客户提供了服务,而且也推广了自己,让更多的客户了解自己。对于企业客户信息反馈而言…...
【SA8295P 源码分析】01 - SA8295P 芯片介绍
【SA8295P 源码分析】01 - SA8295P 芯片介绍 一、Processors 处理器介绍二、Memory 内存介绍三、Multimedia 多媒体介绍3.1 DPU 显示处理器:Adreno DPU 11993.2 摄像头ISP:Spectra 395 ISP3.3 视频处理器:Adreno video processing unit (VPU)3.4 图像处理器:Adreno graphic…...
扩展1:Ray Core详细介绍
扩展1:Ray Core详细介绍 导航 1. 简介和背景2. Ray的基本概念和核心组件3. 分布式任务调度和依赖管理4. 对象存储和数据共享5. Actor模型和并发编程6. Ray的高级功能和扩展性7. 使用Ray构建分布式应用程序的案例研究8. Ray社区和资源9. 核心框架介绍...

day08 Spring MVC
spring MVC相当于Servlet mvc解释:模型,视图,控制器 **使用该思想的作用:**减少耦合性,提高可维护性 Spring MVC前端控制器 方式1 1.在web.xml中配置前端控制器方式2 要是用前端控制器,必须在web.xml中配置DidpatcherServlet类 <!--前端控制器--> <servlet&g…...
c++中的extern “C“
在一些c语言的library库中,我们经常可以还看下面这样的结构 #ifndef __TEST_H #define __TEST_H#ifdef _cplusplus extern "C" { #endif/*...*/#ifdef _cplusplus } #endif #endif#ifndef __TEST_H这样的宏定义应该是非常常见了,其作用是为了…...
python异常处理名称整理
Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误。你可以使用该功能来调试python程序。BaseException所有异常的基类UnboundLocalError访问未初始化的本地变量SystemExit...

SpringMVC拦截器
SpringMVC拦截器 介绍 拦截器(interceptor)的作用 SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器 进行预处理和后处理 将拦截器按一定的顺序连接成一条链,这条链称为拦截器链(Interception Ch…...
Python第八章作业(初级)
目录 第1关:统计字母数量 第2关:统计文章字符数 第3关:查询高校信息 第4关:查询高校名 第5关:通讯录读取 第6关:JSON转列表 第7关:利用数据文件统计成绩 第8关:研究生录取数据…...

chatgpt赋能python:Python中如何取消列表
Python中如何取消列表 在Python中使用列表是一种非常常见的数据结构,它允许我们在其中存储任意数量的元素,并且可以非常容易地进行遍历和操作。但是,有时候我们需要从列表中删除元素。这个过程并不难,但是有些细节需要注意。本文…...

Java中List排序的3种方法
在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进行排序,这个时候,…...
flutter-读写二进制文件到设备
看了下很多文章,本地文件存储都只有存储txt文件,我们探索下存储二进制文件吧。 保存二进制文件到设备硬盘上。 我们保存一个图片到手机本地上,并读取展示图片到app上。 以百度logo图为例子 写入图片 逻辑如下: 获取本地路径 -&g…...
C语言基础知识:内存分配
目录 内存分配原理 内存分配方法 静态内存分配 动态内存分配 MALLOC() CALLOC() 内存释放 注意事项 在C语言中,内存分配是非常重要的一个概念,因为C语言中没有内置的垃圾回收机制,需要我们手动管理内存的分配和释放。下面我们来详细讲…...

【Simulink】示波器图形数据导入Matlab重新绘图(论文)
版本:Matlab2019b 效果 示波器波形图片: 黑色背景,而且坐标轴字体较小,不方便修改,不能直接用在论文上面 对比 Matlab 绘图: 接下来介绍如何设置~ Simulink 设置 选择需要导入的示波器数据 点击 Vi…...

汇编调试及学习
汇编调试 打印寄存器的值 打印内存地址 打印8字节,就是64位 打印格式 是从低位取过来的 b 字节 h 双字节 w四字节 g八字节 前变基 后变基 。 后变基这个变基会发生变化的。前变基变基不会发生变化需要用!号。 前变基 , 加了࿰…...

Linux - 第19节 - 网络基础(传输层二)
1.TCP相关实验 1.1.理解listen的第二个参数 在编写TCP套接字的服务器代码时,在进行了套接字的创建和绑定之后,需要调用listen函数将创建的套接字设置为监听状态,此后服务器就可以调用accept函数获取建立好的连接了。其中listen函数的第一个参…...

web实现日历、阳历农历之间相互转换、npm、push、unshift、includes、innerHTML
文章目录 1、原生web实现效果图htmlJavaScriptstyle vue2实现htmlJavaScript 1、原生web实现 效果图 html <div class"box"><div class"week"><div>星期日</div><div>星期一</div><div>星期二</div><…...

GcExcel v6.1 支持新的 ‘.sjs‘ 模板文件 ‘.xltx‘ 格式 Crack
GrapeCity Documents for Excel (GcExcel) v6.1 版本现已上线!该版本支持新的 SpreadJS .sjs 文件格式和 Excel 模板文件 .xltx 格式。此外,GcExcel 支持更多的SpreadJS兼容性功能和对 GcDataViewer 的多项增强。看看下面的主要亮点。 导入/导出 Spread…...

面试官:MySQL自增主键一定是连续的吗?
测试环境: MySQL版本:8.0 数据库表:T (主键id,唯一索引c,普通字段d) 如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的…...

2023ACP世界大赛教育者论坛:让职业教育直面AI机遇与挑战
“AI技术的普及对创意行业和教育带来的影响和变革-2023 Adobe Certified Professional教育者论坛”在苏州西交利物浦大学成功举办。 本次论坛,由Adobe Certified Professional 世界大赛中国赛区组委会主办,联动了来自院校、海内外杰出的创意公司及国际知…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...