当前位置: 首页 > news >正文

JVM复习

冯诺依曼模型与计算机处理数据过程相关联:

  • 冯诺依曼模型:        
    • 输入/输出设备
    • 存储器
    • 输出设备
    • 运算器
    • 控制器
  • 处理过程:
    • 提取阶段:输入设备传入原始数据,存储到存储器
    • 解码阶段:由CPU的指令集架构ISA将数值解码成指令
    • 执行阶段:控制器把需要计算或处理的数据调入运算器
    • 最终阶段:由输出设备把运算结果返回

所以JVM是什么呢?

  • 首先,将java文件编译成.class文件之后,JVM会对字节码文件进行解释,翻译成对应平台的机器指令开始执行。屏蔽了底层操作系统,实现跨平台运行。

.java文件是如何变成.class文件的?

类文件解读:

  • 16进制

  • magic、版本号、常量池(62个字面量和符号引用)、字段表集合、方法表集合

  • 符号引用就是类信息、修饰符,名称等等,不直接指向

类加载机制:

所谓的类加载机制就是将class文件加载进内存,并对数据进行校验,转换解析和初始化,形成JVM可以直接使用。

  • 当字节码文件加载到内存的时候,是不是需要一个访问入口呀?
  • 那如何将字节码文件加载进内存呢?
    • 常见的从本地系统加载
    • 动态代理技术,运算时计算而成
    • 从jar包中加载
  • 类加载过程:
    • 装载:
      • 通过类全限定名获取类的二进制字符流!
      • 将字符流代表的静态存储结构转换为方法区的运行时数据结构
      • 在堆中生成java.lang.class对象,作为对方法区中这些数据的访问入口
    • 链接
      • 验证:格式验证、字节码验证、符号引用验证。-Xverify:none 取消验证。
      • 准备:为静态变量赋值,初始化成默认值。
        • 这里不包含final修饰的static,final修饰的static都在编译的时候就分配了
        • 不会为实例变量分配初始化,类变量在方法区中,实例变量随着对象在堆中(即在实例构造器方法中进行的)
      • 解析
        • 将符号引用转换成直接引用,直接指向目标的指针,或者间接定位到目标的句柄
        • 对解析结果进行缓存
    • 初始化
      • 执行类构造器方法的过程,对比于准备阶段,这里是通过指定主观计划去初始化变量和其他资源。
      • 对类变量设置初始值的两种方式:
        • 直接声明
        • static代码块
      • 步骤
        • 先装载和链接本类
        • 然后初始化父类
        • 初始化自己
      • 什么时候初始化:(主动引用)
        • 创建实例;
        • 对静态变量赋值;
        • 调用静态方法;
        • 调用子类父类也会初始化;
        • 标明启动类的类
      • (被动引用)
        • 定义类数组不会初始化
        • 使用父类的静态变量,不会初始化
        • static final不会初始化
    • 卸载:
      • 用完之后就卸载回收
        • 包括类加载器,class对象,实例
  • 类加载器:
    • 就是读取字节码,转换成java.lang.class类的一个实例的代码模块
    • 一个类在同一个类加载器中具有唯一性,不同类加载器是允许同名类存在的,类加载器不同,就不会是同一个类。
    • 分类:
      • bootstrap classloader:负责java_home的所有class
      • extension classloader:负责一些扩展的包
      • app classloader:classpath中指定的包
      • custom classloader:根据程序自定义类加载器
    • 为什么要分层?
      • 如果自己编写了一个java.lang.String类,如果只有一个的话无法判定究竟要加载哪个。所以分层对信任级别进行划分
    • 三个特性:
      • 全盘负责:
        • 当一个类加载器加载某个class的时候,该class所依赖的和引用其他的class都由该类加载器负责载入。除非显式使用另一个类加载器
      • 父类委托(双亲委派):
        • 首先传入类的全限定名
        • 从app层依次往上找是否加载过,然后又从上往下看谁能加载,最后还没有就抛异常。
        • 可以重写loadclass打破双亲委派
        • 打破:
          • SPI,JDK提供了一套接口,定义实现类,在META-INF/services中注册实现类的相关信息,比如JDBC的DriverManager
          • OSGI:热部署、热替换
          • 如果怕打破可以重写findclass方法
      • 缓存机制:
        • 加载过的class文件在内存中(方法区)缓存
        • 每一个类加载器都有自己的缓存

运行时数据区:

  • 常量池:
    • 静态常量池:class文件的一部分,由字面量(文本、字符串以及final修饰的)和符号引用(描述信息)组成
    • 运行时常量池:静态常量池被加载到内存后就变成了运行时常量池了,class文件内容落地到内存了
    • 字符串常量池:现在在堆中
      • 面试常问的:
        • String a ="aaaa";

          解析:最多创建一个字符串对象。先查找有没有这个,没有就创建一个,返回引用。

        • `String  a  =new  String("aaaa");`

          解析:最多会创建两个对象。常量池没有的话,就在堆中创建一个字符串对象(放字符串常量池里),再在堆中创建一个对象(独立出去),返回后面的引用。有没有都要多创建一个。

        • intern()

          • String s1 = new String("yzt");
            String s2 = s1.intern();
            System.out.println(s1 == s2); //false
            返回的是字符串常量池里的
        • 方法区:
          • 线程共享
          • 堆的一个逻辑部分,但是也要和堆区分出来
          • 存放虚拟机加载的类信息,常量、静态变量、JIT代码等等
          • 当方法区无法满足内存分配的需求时,将抛出OOM异常
          • 1.8后在系统内存(元空间)中,为了避免内存泄露和OOM
        • 堆:
          • 虚拟机管理内存中最大的一块,在虚拟机启动的时候被创建,线程共享
          • 实例和数组都在堆上分配,注意java.class.class这个对象就是方法区中数据的访问入口
        • 虚拟机栈:
          • 假设现在已经初始化完成了要使用了,一个线程的运行状态就由虚拟机栈来保存,线程私有,随着线程的创建而创建。
          • 线程执行的每一个方法,就是栈中的一个栈桢,可以看作是一个方法的运行空间。
        • 程序计数器:
          • 线程切换的时候,记录正在执行的字节码指令的地址
        • 本地方法栈:
          • 如果执行Native就在本地方法栈执行
          • 如果在java方法执行的时候调用native方法,就是动态链接。

内存布局:

  • 对象内存布局:
  • 指针压缩:
    • 在64位的操作系统中,一个指针一般是八个字节,在很多情况下,并不需要使用这么多的地址空间。压缩的主要是classpointer
    • 减少内存消耗,压缩成4字节。对于大型应用,节省空间。
    • 更好的缓存应用:能存放更多的对象
    • 提高访问速度:较小的数据结构代表着读写能够更快的完成
    • 减少垃圾回收开销:扫描和标记耗时变小
    • 无效情况:
      • 32位超过32G
      • 怎么去理解?
        • 第一种理解:对象长度一定是8的整数倍,所以只用存第一个,4G*8=32G
        • 第二种理解:当存入64位寄存器的时候,左移三位,末尾三个0是不需要的,索引寻址空间提高了8倍;
  • java采用的大端存储,便于符号判断,小端便于类型转换
  • classpointer设计:
    • 句柄池访问:对象移动的时候只需要修改一个指针,但是多一次定位的时间开销
    • 直接指针:节省了一次定位开下,在对象移动后,还需要修改引用
  • 对齐填充:
    • 8字节,举个例子,如果针对开区域存储,那么就需要读两次内存,现在读一次就可以了。也可以选择策略
      • 0:基本类型>填充类型>引用类型
      • 1:引用类型>基本类型>填充类型
      • 2:父类的引用类型和子类的引用类型放在一起,父类采用0,子类采用1,从而降低空间的开销。

运行时数据区:

  • 根据GC的悲观策略,98%的对象不能达到分代年龄
  • 内存担保机制:假设在young gc后,新生代仍然有大量的对象存活,就需要老年代进行分配担保。

什么时候Full GC?

  • 每次晋升的对象平均大小>剩余空间,基于历史水平计算 

  • 上面内存担保机制

  • 元空间内存不足

  • System.GC

  • 如何理解Minor/Major/Full GC

Minor GC:新生代
Major GC:老年代
Full GC:新生代+老年代
  • 为什么需要Survivor区?只有Eden不行吗?

如果没有survivor区域,那么就会导致,每进行一次minor gc,存活的对象就要进入老年代,这样老年代就会很快填满,容易发生full gc,老年代空间又比较大。

如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。
这样一来,老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)。
老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。
执行时间长有什么坏处?频发的Full GC消耗的时间很长,会影响大型程序的执行和响应速度。
​
可能你会说,那就对老年代的空间进行增加或者较少咯。
假如增加老年代空间,更多存活对象才能填满老年代。虽然降低Full GC频率,但是随着老年代空间加大,一旦发生Full GC,执行所需要的时间更长。
假如减少老年代空间,虽然Full GC所需时间减少,但是老年代很快被存活对象填满,Full GC频率增加。
​
所以Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。
  • 为什么需要两个Survivor区?

最大的好处就是解决了碎片化。也就是说为什么一个Survivor区不行?第一部分中,我们知道了必须设置Survivor区。假设现在只有一个Survivor区,我们来模拟一下流程:
刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
永远有一个Survivor space是空的,另一个非空的Survivor space无碎片。
  • 新生代中Eden:S1:S2为什么是8:1:1?

新生代中的可用内存:复制算法用来担保的内存为9:1
可用内存中Eden:S1区为8:1
即新生代中Eden:S1:S2 = 8:1:1
现代的商业虚拟机都采用这种收集算法来回收新生代,IBM公司的专门研究表明,新生代中的对象大概98%是“朝生夕死”的
  • 堆内存中都是线程共享的区域吗?

JVM默认为每个线程在Eden上开辟一个buffer区域,用来加速对象的分配,称之为TLAB,全称:Thread Local Allocation Buffer。
对象优先会在TLAB上分配,但是TLAB空间通常会比较小,如果对象比较大,那么还是在共享区域分配。

相关文章:

JVM复习

冯诺依曼模型与计算机处理数据过程相关联: 冯诺依曼模型: 输入/输出设备存储器输出设备运算器控制器处理过程: 提取阶段:输入设备传入原始数据,存储到存储器解码阶段:由CPU的指令集架构ISA将数值解…...

63、ARM/STM32中IIC相关学习20240417

完成温湿度传感器数据采集实验。 【思路:1.通过IIC通信原理,理解其通信过程,通过调用封装的IIC函数达成主机和从机之间:起始信号、终止信号、读、写数据的操作; 2.了解温湿度传感器控制芯片SI7006的工作原理&#…...

离岸人民币与人民币国际化

参考 什么是离岸人民币?它有什么用? - 知乎 “人民币就是人民币,为什么要在它前面加上离岸二字?” “既然有离岸人民币,是否有在岸人民币?” 今天我们就简单了解一下什么是离岸人民币。 离岸/在岸人民币…...

Linux平台上部署和运行Ollama的全面指南

Ollama的安装与配置 Ollama提供了一种简单的安装方法,只需一行命令即可完成安装,但是对于想要更深入了解和自定义安装的用户,我们也提供了手动安装的步骤。 快速安装 Ollama的安装极为简单,只需在终端中执行以下命令&#xff1…...

Web---robots协议详解

在Web中,robots协议(也称为robots.txt)是一种文本文件,用于向搜索引擎机器人(通常称为爬虫)提供指导,以指示它们哪些页面可以抓取,哪些页面应该忽略。robots.txt文件位于网站的根目录…...

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第四套

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第四套 (共9套,有答案和解析,答案非官方,仅供参考)(共九套,每套四十个选择题) 部分题目分享,完整版获取(WX:didadida…...

clipper一些数据结构(入门初识(一))

clipper一些数据结构(一) Clipper库是一个用于执行多边形裁剪(clipping)和偏移(offsetting)操作的开源C库。在Clipper库中,点和多边形(polygon)是基本的数据结构。Clipp…...

读《SQL基础教程 第二版 上》的一些总结

1. 数据库语言 DDL: Data Definition Language,数据定义语言(库、表的操作) DML: Data Manipulation Language, 数据操控语言(对表中数据的增删改) DQL: Data Query Language,数据库查询语言…...

EDI是什么:EDI系统功能介绍

EDI全称Electronic Data Interchange,中文名称是电子数据交换,也被称为“无纸化贸易”。EDI实现企业间(B2B)自动化通信,帮助贸易伙伴和组织完成更多的工作、加快物流时间并消除人为错误。 目前国内企业实现EDI通信大多…...

64B/66B GT Transceiver 配置

一、前言 前一篇文章已经讲述了64B/66B的编码原理,此篇文章来配置一下7系列GT的64B/66B编码。并讲述所对应的例子工程的架构,以及部分代码的含义。 二、IP核配置 1、打开7 Series FPGAs Transceiver Wizards,选择将共享逻辑放置在example …...

ES6: promise对象与回调地狱

ES6: promise对象与回调地狱 一、回调地狱二、Promise概述三、Promise的组成四、用函数封装Promise读取文件操作 一、回调地狱 在js中大量使用回调函数进行异步操作,而异步操作什么时候返回结果是不可控的,所以希望一段程序按我们制定的顺序执…...

Qt事件处理机制2-事件函数的传播

所有继承自QObject的类都有event函数,该函数用来处理自身的事件,函数定义如下: virtual bool QObject::event(QEvent *e);Qt帮助文档: This virtual function receives events to an object and should return true i…...

【PDF.js】PDF文件预览

【PDF.js】PDF文件预览 一、PDF.js二、PDF.js 下载1、下载PDF.js2、在项目中引入3、屏蔽跨域错误 三、项目中使用四、说明五、实现效果 使用PDFJS实现pdf文件的预览,支持预览指定页、关键词搜索、缩略图、页面尺寸调整等等。 一、PDF.js 官方地址 文档地址 二、PD…...

从建表语句带你学习doris_表索引

1、doris建表概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE [olap|mysql|broker|hive]] [key_desc] [COMMENT "tabl…...

Linux CentOS 安装 MySQL 服务教程

Linux CentOS 安装 MySQL 服务教程 1. 查看系统和GNU C库(glibc)版本信息 1.1 查询机器 glibc 版本信息 glibc,全名GNU C Library,是大多数Linux发行版中使用的C库,为系统和应用程序提供核心的API接口。在Linux系统中,特别是在…...

MSSQL 命令行操作说明 sql server 2022 命令行下进行配置管理

说明:本文的内容是因为我在导入Access2019的 *.accdb 格式的数据时,总是出错的背景下,不得已搜索和整理了一下,如何用命令行进行sql server 数据库和用户管理的方法,作为从Access2019 直接导出数据到sql server 数据库…...

【系统分析师】系统安全分析与设计

文章目录 1、安全基础技术1.1 密码相关1.1.1对称加密1.1.2非对称加密1.1.3信息摘要1.1.4数字签名1.1.5数字信封 1.2 PKI公钥体系 2、信息系统安全2.1 保障层次2.2 网络安全2.2.1WIFI2.2.2 网络威胁与攻击2.2.3 安全保护等级 2.3计算机病毒与木马2.4安全防范体系 1、安全基础技术…...

ActiveMQ 07 集群配置

Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…...

Redis(哨兵模式)

什么是哨兵机制 问题: redis 主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工进行主从切换, 同时大量客户端需要被通知切换到新的主节点上, 对于有一定规模的应用来说, 对于人力的资源消耗会很大.解决: 通过哨兵对主从结构进行监控, 一旦出现主节点挂了的情况, 自动…...

一种基于镜像指示位办法的RingBuffer实现,解决Mirror和2的幂个数限制

简介 在嵌入式开发中,经常有需要用到RingBuffer的概念,在RingBuffer中经常遇到一个Buffer满和Buffer空的判断的问题,一般的做法是留一个单位的buffer不用,这样做最省事,但是当RingBuffer单位是一个结构体时&#xff0…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

离线语音识别方案分析

随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...

c# 局部函数 定义、功能与示例

C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...

shell脚本质数判断

shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数)shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数) 思路: 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...

Java中栈的多种实现类详解

Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...