【JavaEE 初阶(十)】JVM

❣博主主页: 33的博客❣
▶️文章专栏分类:JavaEE◀️
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你了解更多进阶知识

在这里插入图片描述

目录

  • 1.前言
  • 2.JVM内存区域划分
  • 3.类加载
    • 3.1双亲委派模型
  • 4.垃圾回收(GC)
    • 4.1垃圾识别
      • 4.1.1引用计数
    • 4.1.2可达性分析
    • 4.2垃圾释放
    • 4.2.1标记释放
    • 4.2.2复制算法
    • 4.2.3标记整理
    • 4.2.4分代回收
  • 5.总结

1.前言

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统,JVM本省是一个比较复杂的东西,我主要从三个方面进行讲述:内存区域划分,类加载机制垃圾回收算法。

2.JVM内存区域划分

JVM其实就是一个进程,进程在运行过程中,要从操作系统申请资源空间,JVM申请的空间会划分为几个不同的区域,每个区域作用各不相同。这些资源支持了后续Java程序的执行。
在这里插入图片描述
堆区:整个进程只有一份,代码中new出来的对象,对象中的非静态成员变量,放在堆区
栈区:虚拟机栈记录了JAVA代码中的调用关系,java局部变量。
程序计数器:专门用来存储下一条Java指令的地址
元数据:整个进程只有一份,一些辅助性质的,描述性质的属性,我们所写的JAVA代码,各种逻辑运算,会通过javac完成代码转换成字节码,此时这些字节码在程序运行时就会被JVM加载到元数据中,此时当前程序如何执行,做哪些事就按照上述元数据区记录的字节执行。
下列元素n,m,t各在什么区?

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

t为局部变量在栈区
new Test在堆区
n是成员变量也在堆中
m是static修饰,类属性在元数据区

3.类加载

类加载就是指JAVA程序运行是,把.class文件从硬盘中读到内存,再进行一系列解析。
类加载大致可以分为5步:
1)加载
把硬盘上的.class文件找到,打开文件读取文件内容
2)验证
确保读到的文件内容是合法的
3)准备
给类申请内存空间,默认值为全0
4)解析
主要针对类中的字符串常量进行处理
例如有一串代码为String s=”hello";s变量存入的是hello的地址,但是再.calss文件中不纯在地址的概率,那么为了就可以给s填一个偏移量。
在这里插入图片描述

5)初始化
把类对象的各个部分的属性进行赋值填充

3.1双亲委派模型

在类加载的时候有一个重要模型就是双亲委派模型,描述了如何找到.class文件。在进行加载操作的时候有一个专门的模块叫做类加载器,默认含有三个
BootstrapClassLoader:负责查找标准库的目录
ExtensionClassLoader:负责查找扩展库的目录
ApplicationClassLoader:负责查找当前项目的代码目录,第三方库目录
上述三个类加载器存在父子关系,类似于二叉树,有一个指针指向父类加载器
在这里插入图片描述
双亲委派工作流程:
1)从ApplicationClassLoader作为入口,开始工作
2)ApplicationClassLoader不会立即搜索自己负责的目录,会把搜索的任务交给自己的父亲
3)进入ExtensionClassLoader,也不会立即搜索自己负责的目录,也会把搜索的任务交给自己的父亲
4)进入BootstrapClassLoader,不会立即搜索自己负责的目录,也会把搜索的任务交给自己的父亲
5)BootstrapClassLoader发现自己没有父亲节点,此时会真正的搜索负责的目录,如果找到了就执行后续操作,没有找到就返回给孩子
6)ExtensionClassLoader收到父亲的任务以后,会搜索自己负责的目录,如果找到了就执行后续操作,没有找到就返回给孩子
7)ApplicationClassLoader收到父亲的任务以后,会搜索自己负责的目录,如果找到了就执行后续操作,没有找到就返回给孩子,但如果没有孩子就说明类加载失败,抛出ClassNotFoundException

4.垃圾回收(GC)

垃圾回收是回收的内存,其中主要回收的是堆中的内存,栈中的内存在代码块结束以后会自动销毁。那么垃圾回收具体是怎么展开的呢?主要分为垃圾识别和垃圾释放

4.1垃圾识别

判定new出来的对象在后续是否要使用,如果不再使用旧标记为垃圾。
例:

void func(){
Test t=new Test();
t.find();
}

当程序执行到}时,t就被释放,此后就不再使用new Test()对象了,就可以标记为垃圾,但如果有些大妈比较复杂,例如

Test t=new Test();
Test m=t;
Test n=m;
Test z=n;

此时就有很多引用指向new Test()对象,就学要确保没有任何一个引用指向这个对象才能标记为垃圾,那么我们怎么知道什么时候没有引用指向它呢?

4.1.1引用计数

当我们创建一个对象时,给每个对象分配一个额外的空间记录当前对象有几个引用。
在这里插入图片描述
每增加一个引用,计数位置+1,每减少一个引用,技术位置-1,如果为0就标记为垃圾
问题一
这样会消耗额外的空间,当我们的对象非常多,但对象的体积非常小,那么久可能导致计数所占的空间就占了所有空间的大部分。
问题二
可能会引起循环引用,那么就永远释放不了资源

class Test{
Test t;
}
Test a=new Test();
Test b=new Test();
a.t=b;
b.t=a;
a=null;
b=null;

在这里插入图片描述
这俩对象不能再使用也释放不了

4.1.2可达性分析

在写代码的时候会定义很多变量,就可以从这些变量作为起点开始遍历,所谓的遍历就是会沿着这些变量的引用类型成员再京一部访问,所有能被访问到的自然不是垃圾
在这里插入图片描述

4.2垃圾释放

4.2.1标记释放

最直接的方法就是把标记为垃圾的直接释放掉:但是这样会生成很多内存碎片,后续如果有类对象再申请空间可能就不够用
在这里插入图片描述

4.2.2复制算法

把一个空间分成两半,假设数据存放于左半边那么把不是垃圾的数据全部赋值到右半再讲左半数据全部释放掉。
灰色为垃圾标记,数字为数据
在这里插入图片描述
在这里插入图片描述
这样总的内存空间减少,且复制的开销也很大。

4.2.3标记整理

在这里插入图片描述
在这里插入图片描述
该方案是把所有的数据依次向前搬运,覆盖掉垃圾区,再把剩下的垃圾进行释放。
虽然这样能解决内存碎片的问题,但搬运的内存开销很大

4.2.4分代回收

JVM中有专门的线程负责周期性扫描,一个对象如果被扫描了一次,年龄就+1,JVM会根据对象年龄的差异,把整个堆分成2部分,新生代,老年代。
在这里插入图片描述
1)当代码中new出一个新的对象,这个对象就是被创建在伊甸区,伊甸区的对象大部分都活不够第一轮,生命周期非常短
2)第一轮GC扫描完成以后,少数伊甸区幸存的对象会通过复制算法拷贝到生存区,在后续GC扫描的时候不仅会扫描伊甸区还会扫描生存区的对象,生存区的大多数对象也会在扫描中被标记为垃圾,少数存活,就会继续通过复制算法拷贝到另一个生存区,每次经历一轮GC年龄就+1.
3)如果这个对象在生存区中经历了若干轮依然在,那么就会把这个对象拷贝到老年区。
4)老年代的对象也会被GC扫描只是频次大大减小
5)对象在老年代结束以后就会释放内存。

5.总结

本篇文章主要JVM内存区域划分,类加载,双亲委派模型,垃圾识别,引用计数,可达性分析,垃圾释放,分代回收等等。

下期预告:MySQL

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

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

相关文章

1098: 堆的判断

解法&#xff1a; 堆是完全二叉树 用数组来存储 然后用定义判定 #include<iostream> #include<vector> using namespace std; int main() {int n;cin >> n;vector<int> vec(n);for (int i 0; i < n; i) cin >> vec[i];for (int i 0; i &…

LabVIEW超高温高压流变仪测试系统

LabVIEW超高温高压流变仪测试系统 超高温高压流变仪广泛应用于石油、天然气、化工等行业&#xff0c;用于测量材料在极端条件下的流变特性。随着计算机技术、测试技术和电子仪器技术的快速发展&#xff0c;传统的流变仪测试方式已无法满足现代工业的需求。因此&#xff0c;开发…

【全开源】沃德商协会管理系统源码(FastAdmin+ThinkPHP+Uniapp)

一款基于FastAdminThinkPHPUniapp开发的商协会系统&#xff0c;新一代数字化商协会运营管理系统&#xff0c;以“智慧化会员体系、智敏化内容运营、智能化活动构建”三大板块为基点&#xff0c;实施功能全场景覆盖&#xff0c;一站式解决商协会需求壁垒&#xff0c;有效快速建立…

就业班 第三阶段(CICD) 2401--5.15 day2 自动化构建打包、部署(Jenkins + maven+ gitlab+tomcat)

一、平滑发布与灰度发布 **什么叫平滑&#xff1a;**在发布的过程中不影响用户的使用&#xff0c;系统不会因发布而暂停对外服务&#xff0c;不会造成用户短暂性无法访问&#xff1b; **什么叫灰度&#xff1a;**发布后让部分用户使用新版本&#xff0c;其它用户使用旧版本&am…

vector的底层实现与模拟

嗨喽大家好&#xff0c;时隔许久阿鑫又给大家带来了新的博客&#xff0c;关于vector的模拟实现&#xff0c;下面让我们开始今天的学习吧&#xff01; vector的底层实现与模拟 1.关于vector中的插入和删除 2. vector中的拷贝构造和赋值 3.vector的构造函数 4.关于vector中浅…

微信小程序报错:notifyBLECharacteristicValueChange:fail:nodescriptor的解决办法

文章目录 一、发现问题二、分析问题二、解决问题 一、发现问题 微信小程序报错&#xff1a;notifyBLECharacteristicValueChange:fail:nodescriptor 二、分析问题 这个提示有点问题&#xff0c;应该是该Characteristic的Descriptor有问题&#xff0c;而不能说nodescriptor。 …

windows docker desktop 更换镜像存储目录

windows docker desktop 更换镜像存储目录 方法&#xff1a;如图&#xff0c;Browse浏览一个新的目录并选中&#xff0c;确定后&#xff0c;程序会开始stop&#xff0c;在stop完成前&#xff0c;会持续迁移原有镜像到新的位置&#xff0c;你会发现目标位置的磁盘占用空间越来越…

DNS服务的部署与配置(1)

一、DNS的定义 1、域名系统&#xff08;英文&#xff1a;Domain Name System&#xff0c;缩写&#xff1a;DNS&#xff09;是互联网的一项服务。 它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网。 DNS使用UDP端口53。 当前&#xff0…

使用pygame绘制图形

参考链接&#xff1a;https://www.geeksforgeeks.org/pygame-tutorial/?reflbp 在窗口中绘制单个图形 import pygame from pygame.locals import * import sys pygame.init()window pygame.display.set_mode((600,600)) window.fill((255,255,255))# pygame.draw.rect(wind…

WSL调用docker

WSL&#xff08;windows subsystem linux&#xff09;是window系统的原生linux子系统&#xff0c;用于代码开发很方便。 希望在wsl里面运行docker&#xff0c;首先要安装docker在WSL中使用&#xff0c;大部分人的第一想法肯定是用以下命令行安装&#xff08;个人不推荐&#x…

【C语言】指针运算

前言 前面在“走进指针世界”中我已经讲解过指针相关的很多前置知识&#xff0c;其实还有一个很重要的部分就是指针的运算。这篇博客&#xff0c;就让我们一起了解一下指针的运算吧&#xff01; 指针作为变量&#xff0c;是可以进行算术运算的&#xff0c;只不过情况会和整型…

Behind the Code:Polkadot 如何重塑 Web3 未来

2024 年 5 月 17 日 Polkadot 生态 Behind the Code 第二季第一集 《创造 Web3 的未来》正式上线。第一集深入探讨了 Polkadot 和 Web3 技术在解决数字身份、数据所有权和去中心化治理方面的巨大潜力。 &#x1f50d; 查看完整视频&#xff1a; https://youtu.be/_gP-M5nUidc?…

aws glue配置读取本地kafka数据源

创建连接时填写本地私有ip地址&#xff0c;选择网络配置 配置任务选择kafka作为数据源 但是执行任务时日志显示连接失败 文档提到只能用加密通信 如果您希望与 Kafka 数据源建立安全连接&#xff0c;请选择 Require SSL connection (需要 SSL 连接)&#xff0c;并在 Kafka priv…

滑动谜题 leetcode的BFS题目 启发如何写一个拼图编程呢

题目链接 题目要求&#xff0c;要将上面的拼板拼成123450 首先&#xff0c;转换为字符串&#xff0c;为什么要转换为字符串呢&#xff0c;因为处理会变得很简单比如示例一&#xff0c;转化为字符串是12345&#xff0c;目标字符串为123450&#xff0c;只需要证明通过某种交换&a…

JDBC(Java DataBase Connectivity)Java数据库连接

JDBC(Java DataBase Connectivity) Java 语言连接数据库 再本模块中,java提供里一组用于连接数据库的类和接口Java 语言开发者,本身没有提供如何具体连接数据库的功能只是定义了一组java程序连接数据库的访问接口 连接到数据库向数据库发送增,修改,删除这一类的sql发送查询sq…

【vue echart】完成一个简单echart图表+自适应

实现效果&#xff1a; html&#xff1a; <divref"echartOne"id"echartOne"style"width: 100%; height: 100%" ></div> js: getEchartOne() {let chart this.$echarts.init(this.$refs.echartOne);chart.setOption({title: {text:…

vue 纵向滚动菜单, 点击滚动到选中菜单

1 背景 需要设计一个纵向滚动菜单&#xff0c;要求丝滑点&#xff0c;默认显示选中菜单 2 思路 给定一个容器&#xff0c;样式包含overflow:hidden&#xff0c;默认高宽足够显示一个菜单&#xff08;以下用图标代替菜单&#xff09;&#xff0c;鼠标悬浮时增大容器高度&#…

揭秘Python的魔法:装饰器的超能力大揭秘 ‍♂️✨

文章目录 Python进阶之装饰器详解1. 引言装饰器的概念与意义装饰器在Python编程中的作用 2. 背景介绍2.1 函数作为对象2.2 高阶函数 3. 装饰器基础3.1 理解装饰器3.2 装饰器的工作原理 4. 带参数的装饰器4.1 为什么需要带参数4.2 实现带参数的装饰器使用函数包裹装饰器使用类实…

通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称、用icon区分文件和文件夹等需求

目录 一、通过el-tree自定义渲染网页版工作目录 1.1、需求介绍 1.2、使用el-tree生成文档目录 1.2.1、官方基础用法 ①效果 ②代码&#xff1a; 1.2.2、自定义文档目录&#xff08;实现鼠标悬浮显示完整名称、用icon区分文件和文件夹&#xff09; ①效果&#xff08;直接效…