Java——JVM

前言

JVM.即Java虚拟机.用来解释执行Java字节码.

一、JVM中的内存区域划分

JVM其实也是一个进程,进程运行过程中,要从操作系统这里申请一些资源(内存就是其中的典型资源)

这些内存空间,就支撑了后续Java程序的执行.

JVM从系统中申请了一大块内存,这一大块内存给Java程序使用的时候,又会根据实际的使用用途来划分出不同的空间(区域划分)

1. 堆(只有一份)

代码中new出来的对象,就是在堆里的,对象中持有的非静态成员变量,也就是在堆里.

2. 栈(可能有N份)

本地方法栈/虚拟机栈->记录了Java代码的调用关系,Java代码的局部变量

包含了方法调用关系和局部变量

3. 程序计数器(可能有N份)

这个区域比较小的空间,专门用来存储吓一跳要执行的Java指令的地址.

4. 元数据区(只有一份)(以前也叫方法区)

" 元数据 " 是计算机的一个常见术语(meta data)

往往指的是一些辅助性质的,描述性质的属性.

类的信息,方法的信息:

一个程序,有哪些类,每个类里有哪些方法,每个方法里面都包含了那些指令,都会记录在元数据区里.

硬盘上不仅仅要存文件的数据本体,还需要存储一些辅助信息:

文件的大小,文件的位置,文件的拥有者,文件的修改时间,文件的权限信息.....这些统称为" 元数据 "

比如这样一个代码:

class Test{
    private int n;
    private static int m;
}
main(){
Test t = new Test();
}

这个代码中:
n是Test的成员变量,是在 堆 的.

t是一个局部变量(引用类型),在 栈.

static修饰的变量,称为 " 类属性 "

static修饰的方法,称为 " 类方法 "

非static修饰的变量,称为 " 实例属性 "

非static修饰的方法,称为 ' 实例方法 "

上述带有static 修饰的变量,就是在类对象(.class)中,也就是在元数据区中.

JVM把.class文件加载到内存之后,就会把这里的信息使用对象来表示,此时这样的对象就是类对象.

类对象里就包含了一系列的信息:

包括但不限于:类的名称,类继承自哪个类,实现了哪些接口.

都有哪些属性,都叫什么名字,都是什么类型,都有什么权限.

都有哪些方法,都叫什么名字,都是什么参数,都有什么权限.

java文件中涉及的信息都会在.class中有所体现.

区分一个变量在哪个内存区域中,最主要就是看变量的 " 形态 "(局部变量,成员变量,静态成员变量)

二、JVM的类加载机制

类加载,指的是java进程运行的时候,需要把.class 文件从硬盘,读取到内存,并进行一系列的校验解析的过程.

.class -> 类对象        硬盘 -> 内存

类的加载大体的过程可以分为5个步骤:

1. 加载

把硬盘上的.class文件,找到,打开文件,读取到文件的内容,

2. 验证

当前需要确保读到的文件的内容,是合法的. class文件(字节码文件)格式

3. 准备

给类对象,申请内存空间.

此时申请到的内存空间,里面的默认值,都是全0的.

4. 解析

主要是针对类中的字符串常量进行处理

硬盘中没有地址,引用类型的数据无法通过地址存储,就可以使用偏移量,等. class文件加载到内存中后,就有hello的地址了.

5. 初始化

针对类对象完成后续的初始化.

还要执行静态代码块的逻辑,还可能会触发父类的加载.

双亲委派模型(加载环节)

描述了如何查找. class文件的策略

JVM中进行类加载的操作,是有一个专门的模块,称为 " 类加载器 "

JVM中的类加载器默认是有三个的

BootstrapClassLoader   负责查找标准库目录

ExtensionClassLoader   负责查找扩展库目录

ApplicationClassLoader   负责查找当前项目的代码目录以及第三方库的目录

上述这三个类加载器,存在 "父子关系",类似于二叉树,有一个指针parent指向自己的父类加载器.

双亲委派模型的工作流程:

1.从ApplicationClassLoader 作为入口,开始工作.

2..ApplicationClassLoader 不会立即搜索自己负责的目录,会把搜索的任务交给自己的父亲.

3.代码就进入到ExtensionClassLoader 范畴了.

ExtensionClassLoader 也不会立即搜索自己负责的目录,也要把搜索的任务交给自己的父亲.

4.代码就进入到BootstrapClassLoader  范畴了.

BootstrapClassLoader  也不会立即搜索自己负责的目录,也要把搜索的任务交给自己的父亲.

5. BootstrapClassLoader 发现自己没有父亲,才会真正的开始搜索自己的目录,通过全限定类名,尝试在标准库目录中找到符合要求的.class文件

如果找到了,接下来直接进入打开文件/读文件等流程中.

如果没找到,回到孩子这一辈的类加载器中,继续尝试加载.

6. ExtensionClassLoader 收到父亲交回给他的任务后,搜索自己负责的目录

如果找到了,接下来直接进入打开文件/读文件等流程中.

如果没找到,回到孩子这一辈的类加载器中,继续尝试加载.

7. ApplicationClassLoader 收到父亲交回给他的任务后,搜索自己负责的目录.

如果找到了,接下来直接进入打开文件/读文件等流程中.

如果没找到,回到孩子这一辈的类加载器中,继续尝试加载.

由于ApplicationClassLoader没有孩子了,此时说明类加载过程失败了,就会抛出ClassNotFountException异常.

上述这一些列规则,只是JVM自带的类加载器,遵守的默认规则,如果自己写类加载器,也可以打破这种规则.

三、垃圾回收机制(GC)

引入了垃圾回收机制后,就不需要手动释放内存了.程序会判定内存是否还需要使用,不需要使用的就会被释放.

STW(stop the world)问题:触发垃圾回收机制的时候,很可能会使当前程序的其他的业务逻辑被暂停.

垃圾回收,是回收内存,JVM的内存有好几块,其中堆是GC的主要战场.

垃圾回收机制的具体展开:

1. 识别出垃圾.

判定一个对象之后是否还需要继续使用,如果一个对象没有任何引用,就会被视为垃圾.

如果有多个引用指向同一个对象,那些引用的生命周期又各不相同,此时情况就会比较复杂.

    1.1 引用计数

        给每个对象安排一个空间,记录有多少个引用指向当前对象,当垃圾回收机制发现这个计数为0,就可以回收这个空间了.

        但是引用计数会有一个问题,如果A对象的一个引用指向了B对象,B对象的一个引用又指向了A对象,然后指向AB的引用各自置为null,就会导致这两块空间都无法被回收 

2. 可达性分析(JVM所使用的)

本质上就是时间换取空间,再写代码的时候,会定义很多的变量,就可以从这些变量出发,尝试进行遍历.

所谓的遍历就是沿着这些变量中持有的引用类型的成员,在进行下一步的访问,无法被访问到的就会被视为垃圾.

2. 把标记为垃圾的对象内存空间进行释放
 

主要的释放方法有三种:

        a. 标记-清除

        把标记为垃圾的对象,直接释放掉.

        但是会导致内存碎片问题,所以一般不使用这个方案

        所谓内存碎片,就是一块完整的内存,其中有一些地方被标记为垃圾,被释放掉,但是时候申请内存的时候,如果总内存足够,但是因为有内存碎片,就会导致没有一块连续的内存的空间达到要申请的空间的大小,此时,去申请空间就会失败.

        例如,要申请1M的空间,总的空闲空间比1M 大,但是空闲空间是1000个碎片,每个碎片是10K,此时空闲空间是10M,但是每个碎片都是小于1M的,就会申请失败.

b. 复制算法

        复制算法,核心就是不直接释放内存,而是把不是垃圾的对象,复制到另一块内存.,然后把之间的空间全部释放.

        这样确实可以解决碎片问题,但是会导致:

        1. 总的可用空间变少了.

        2. 如果每次要复制的对象比较多,此时复制的开销就会很大.

        所以这种方法一般适用于少数对象存活.

c. 标记-整理

        类似于顺序表,释放一个空间后,会把后面的元素向前搬运.

        但是这种方法的搬运内存开销非常大.

分代回收

由于上述垃圾回收机制,都存在问题,所以JVM自己弄出了一个方案.

引入概念:对象的年龄

JVM中有专门的线程负责周期性扫描/释放

一个对象,如果被线程扫描了一次,可达了,年龄就+1(初始为0)

1. 当代码中new出一个新对象的时候,这个对象就是被创建在伊甸区的

2. 第一轮GC扫描完后,少数伊甸区中幸存的对象,就会通过复制算法,拷贝到生存区.

后续再进行扫面,如果这个对象再生存区中还存活者,就会继续被拷贝到另一半生存区中.

3. 如果这个对象在生存区中经过GC多轮扫描依旧存在,就会被拷贝到老年区代.

4. 老年代的对象,被GC扫描的频率就会大幅度降低了.

5. 对象在老年代寿终正寝,此时JVM就会按照标记整理的方式,释放内存.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TOGAF数字化转型的关键(文尾附在线TOGAF免费测试)

业务架构驱动数据架构和应用架构的设计,而应用架构又依赖于数据架构和技术架构的支持。技术架构则为整个架构提供了稳定的基础设施。 在数字化转型中,协调和整合这四种架构是至关重要的。通过确保它们之间的一致性和协同工作,可以实现企业业务…

高效文件传输攻略:利用局域网共享实现极速数据同步

最近,我换了一台新电脑,面对两个电脑之间文件备份和传输的问题,感到十分头疼。经过多方了解,我发现可以在原电脑上设置共享文件,然后接收方从共享文件中接受即可,这样可以将局域网的带宽拉满,比…

力扣78. 子集

给你一个整数数组nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。你可以按任意顺序返回解集。 示例 1: 输入:nums [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3…

GIS数据快捷共享发布工具及操作视频

有网友反映还是不会操作GIS数据快捷共享发布工具(建立自己的地图网站),要我录个视频。 好,那就录一个: GIS数据快捷共享发布工具及操作视频 虽然默认例子是二维的,但这个服务器可以为二维、三维系统发布时间服务。都是…

AI炒股:用kimi获取美股实时行情数据并保存到Excel

在kimi中输入提示词: 你是一个Python编程专家,要完成一个编写Python脚本的任务,具体步骤如下: 获取美股实时美股行情数据,然后保存在F盘的Excel文件中,Excel文件名为:usstock20240605.xlsx 实…

物联网实战--平台篇之(十三)物模型设备端

本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.html 物联网实战--平台篇https://blog.csdn.net/ypp240124016/category_12653350.htm…

存在d盘里的数据突然没有了?别担心,恢复方案在此

在数字化时代,数据存储的重要性不言而喻。然而,有时候我们会遭遇一些意想不到的困扰,比如存储在D盘的数据突然消失。这不仅可能导致重要文件的丢失,还可能影响我们的工作和生活。本文将探讨D盘数据消失的可能原因,提供…

【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化

目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析:使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…

OpenAI新研究破解GPT-4大脑,分解1600万个特征打开“黑匣子”,Ilya 、Jan Leike也参与了!

6月7日凌晨,OpenAI在官网发布了一个新的研究成果,首次破解GPT-4的神经网络活动。通过改进大规模训练稀疏自动编码器将GPT-4的内部表示分解为 1600 万个特征。而且,前段时间离职的Ilya Sutskever、Jan Leike也是作者之一! 这不是破…

【CS.SE】浅谈: 程序员的职业素养与成长之路

文章目录 1 引言2 持续学习与自我提升2.1 永无止境的学习之路2.2 真实案例:自学Python 3 团队合作与沟通能力3.1 高效沟通是团队成功的基石 4 责任心与职业道德4.1 责任心:代码背后的承诺4.2 真实案例:修复紧急Bug 5 适应变化与快速反应5.1 适…

pytorch 自定义学习率更新 Poly

Poly 学习率调整策略需要继承_LRScheduler类,该类包含三个重要属性和两个重要方法 学习率与batch-size的关系 一般来说,batch-size的大小一般与学习率的大小成正比。batch-size越大一般意味着算法收敛方向的置信度越大,也可以选择较大的学…

2024年【起重机械指挥】考试及起重机械指挥新版试题

题库来源:安全生产模拟考试一点通公众号小程序 起重机械指挥考试考前必练!安全生产模拟考试一点通每个月更新起重机械指挥新版试题题目及答案!多做几遍,其实通过起重机械指挥试题及解析很简单。 1、【多选题】《中华人民共和国特…

校验参数个数工具类

项目中有个需求:前后端参数一致性校验,在某业务场景下后端代码需要校验参数个数,因此设计了1个工具类方便大伙使用,特此简单记录下。 校验参数个数工具类 一、校验工具类CheckNumInsideParamters二、单元测试ParameterSizeTest三…

Nginx 配置:gzip动态压缩、静态压缩

动态压缩 动态压缩开启的现象 Nginx配置 http {# 启用 gzip 压缩gzip on;# 设置 gzip 压缩级别,范围是1-9,数字越大压缩率越高但CPU消耗也越大gzip_comp_level 5;# 设置最低压缩的文件大小(大于1KB的文件才进行压缩)gzip_min_le…

Stable Diffusion WebUI 各操作系统安装教程

最近几天在 2 台 Mac、2 台 PC、一台云无 GPU 的 Linux 安装了 Stable Diffusion WebUI,这里记录下如何安装,以及一些注意点和坑。 以下内容针对 Windows(N 卡)、MacOS(m 系列芯片)、Linux(Ubu…

指针在C/C++中的魔力:一级指针与二级指针

什么是指针? 指针是一个变量,它的值是另一个变量的地址。在C/C中,指针是一个强大的工具,可以让我们直接操作内存地址。指针的主要用途包括动态内存分配、数组和字符串处理、函数参数传递等。 一级指针 一级指针(也称为…

数据库-列的完整性约束-概述

引言 我们都知道人以群分 ,但分为 若按照 人类的皮肤分类 黄种人(其实是西方人定义)我们虽然不承认也不否定 ,黑皮肤 ,棕色人种(在南太平洋和西太)白种人 排名你懂的 这好像是枚举类型 emm 尴尬…

Sql-labs的第一关

前言 我们在使用Sql-libs靶场进行Sql注入实验的时候,前提要求我们对mysql数据库结构要有一个大概的了解,因为mysql5.0以上的版本都会自带一个名为information_schema的数据库,这个数据库下面会有columns和tables两个表。 tables这个表的table…

异步复位和同步释放

文章目录 前言一、为什么需要复位呢?二、同步复位1. 同步复位定义2. 同步复位的实现3. 同步复位的优点和缺点同步复位优点同步复位缺点 三、异步复位1. 异步复位定义2. 异步复位的实现3. 异步复位的优点和缺点异步复位优点异步复位缺点 四、异步复位同步释放1. reco…

Type-C转音频(C/3.5mm接口USB2.0数据传输)带PD充电低成本解决方案

LDR6500:领先市场的USB-C DRP接口USB PD通信芯片 产品介绍 LDR6500,由乐得瑞科技精心研发,是一款针对USB Type-C标准中Bridge设备而优化的USB-C DRP(Dual Role Port,双角色端口)接口USB PD(Po…