学习笔记4——JVM运行时数据区梳理

学习笔记系列开头惯例发布一些寻亲消息

链接:https://baobeihuijia.com/bbhj/contents/3/192489.html
在这里插入图片描述


类装载器classLoader:

  • 将本地的字节码文件.class 加载到内存方法区中成为元数据模板(两个class对象是否为同一个类要求:完整类名包括包名一致+加载类的classloader要一致)

    • 启动类加载器,用于提供JVM自身需要的类(除了启动类加载器,其他都继承自classloader)

    • 扩展类加载器:从用户指定目录中加载类

    • 应用程序类加载器:加载环境变量/系统属性指定路径下的类库,是程序中默认的类加载器

    • 用户自定义类加载器

双亲委派机制:

  • 按需加载,需要用到该类的时候才会加载到内存中生成class对象
  • 向上委托,父类加载失败则由子加载器处理
  • 优点:
    • 避免类重复加载
    • 防止核心api被随意更改【沙箱安全】:自定义string类,在加载的自定义string类的时候会率先使用引导类加载器加载jdk自带的string.class文件,可以保证对java核心源代码的保护

在这里插入图片描述

在这里插入图片描述

运行时数据区:

  • JAVA内存布局规定了java运行过程中内存申请,分配和管理的策略:

    • 每个线程独立拥有程序计数器、栈、本地方法栈

    • 线程共享,随虚拟机存亡的:方法区、堆

程序计数器

  • (由于cpu一直在线程中切换,利用程序计数器可以记住切回来后继续执行的位置【cpu时间片:cpu分给各个线程的时间段】)

    • pc寄存器用来存储指向下一条指令的地址/如果该线程执行的是native方法,则是未指定值

    • 通过pc来控制程序的分支、循环、跳转等

    • 字节码解释器就是通过pc来找到下一条即将要执行的字节码指令

    • 是jvm中唯一一个没有规定任何outofmemoryerror情况的

虚拟机栈(栈帧就类似于寄存器之间的倒换)

  • java的指令都是基于栈来设计的,因为不同的平台cpu架构不同,所以不能设计基于寄存器的
  • 随着方法的执行,java栈的操作就是对栈帧的入栈还有出栈,不存在垃圾回收问题(之前的基于寄存器的方法执行是通过寄存器来转移操作数据)
  • 栈可能出现的异常
    • 线程请求分配的栈容量超过java的栈最大容量,就抛出stackoverflowerror异常
    • 如果是没有内存来创建或者满足栈要求,就抛出outofmemoryerror异常
  • 每个线程都有自己的栈,栈中数据是以栈帧格式存在的,执行引擎运行所有的字节码指令只针对当前栈帧进行,也就是说一个时间点只会有一个活动的栈帧,如果该方法调用了别的方法,那么别的方法的栈帧就会被创建并放到栈顶端,成为当前栈帧
  • 栈帧中包括:
    • 局部变量表
      • 局部变量表所需的大小在编译的时候就写在了字节码文件中,所以大小是固定的
      • 以slot为基本存储单位
      • 当一个方法被执行引擎调用的时候,该方法的方法参数和内部定义的局部变量都会按照执行顺序被复制到局部变量表中的slot上
      • 局部变量表必须进行人为的初始化,没有系统自带的准备阶段初始为0,没有赋值就不能使用
    • 操作数栈
      • 保存计算过程的中间结果,同时是计算过程中变量的临时存储空间
      • 并非使用索引来进行数据访问,而是通过数据的出栈和入栈来完成一次访问
      • 栈顶缓存技术:将频繁的栈顶读写缓存到物理cpu中,降低对内存的读写
    • 动态链接(指向运行时常量池的方法引用,将符号转化为调用方法的直接引用)
      • 静态链接(早期绑定):在编译期可知,且运行期不变,用静态链接直接替换
      • 动态链接(晚期绑定):编译期无法确定,要根据程序运行时的实际类型才能确定【比如我们是通过一个变量值>3来判断执行哪个方法,像这样就无法直接替换,就需要在运行时进行动态的链接/支持多态】
        • 虚方法表:每次动态分派的过程都要在类的方法元数据中找到合适的目标,因此在类的方法区建立虚方法表使用索引来代替查找
    • 方法返回地址
      • 存放调用该方法的pc寄存器的值,即调用该方法的下一条指令的地址
      • 若是异常退出,则返回地址是要通过异常表来确定

在这里插入图片描述

Java方法内的局部变量是否线程安全问题_在方法中会产生线程安全问题吗对吗-CSDN博客

本地方法栈

  • 调用本地的一些基于C编写的程序时,采用本地方法栈来管理本地方法的调用

  • 当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。它和虚拟机拥有同样的权限。

  • 是JVM中分配内存最大的一块区域,如果内存大小超过-Xmx指定的最大内存就会抛出outofmemeryerror

    • 为什么xms和xmx要设置成相同的值?【精选】jvm调优技巧 - 内存抖动 、Xms和Xmx参数为什么要设置相同的值_xmx和xms为什么要一样-CSDN博客

      xms是发现空余堆内存大于阈值,jvm减小直到xms最小

      xmx是发现空余堆内存小于阈值,jvm增大直到xmx最大

      1、首先,如果-Xms起初值设置的比较小,那么就频繁触发GC操作。当GC操作无法释放更多内存时,会进行内存的扩充。

      2、内存扩充的时候,会出现内存抖动的情况

      【就比如我上街看到一个很喜欢的商品,想要买下这个商品,但是我身上的钱不够了, 于是我向你借钱,你同意了,然后你掏出钱包, 把钱拿出来,然后再交给我,你拿钱给我的这整个过程也是需要时间的。所以我为了省下这个拿钱的时间,我在一开始出门的时候就直接带上足够的钱,这样就可以省下借钱的时间了】

  • 为对象分配内存TLAB

    • 为避免多个线程操作同一堆区的对象地址,使用TLAB机制,如果失败那就使用加锁机制确保数据操作的原子性
  • 对象不一定全部分配在堆上,采用逃逸分析时,即对象只在方法体内使用时,也可以分配到栈中
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

方法区

  • 实际物理内存空间和堆一样可以不连续的,如果方法区定义了太多的类,那么方法区也会outpfmemoryerror
  • 在这个类加载阶段包括两部分,一是对静态变量的加载(分为static和final static),二是对类的加载
  • 内部结构
    • 类型信息:全名(包名.类名),直接父类的完整有效名,修饰符,直接接口
    • 域信息
    • 方法信息:方法名,方法返回类型,参数,修饰符,字节码,操作数栈,局部变量表以及大小,异常表
  • 方法区是运行时常量池、字节码文件内部包含常量池
    在这里插入图片描述

常量池(字节码)和运行时常量池(方法区)

  • 一个java源文件中的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。

  • 这部分内容在类加载后存放到方法区的运行时常量池中,其中每个已加载的类都会维护一个常量池,通过索引访问

    • 编译期就明确数值字面量
    • 运行期才能获得方法或者字段引用,此时就不再是常量池中的符号地址了,而是真实地址

大概梳理流程:

【创建轮子,车架】我将我的java文件打包生成字节码文件,当我点击运行的时候,启动类会被主动加载,jvm的类加载器就会

  • 加载类中的静态变量到方法区,直接分配内存(可能分配到永久代/堆)
  • 加载字节码中的类信息到方法区(按需加载,需要用到该类的时候才会加载到内存),包括类名,域名,方法名,并且将类的常量池放到方法区的运行时常量池中(根据这个信息才能将类完整的刻画出来),将符号引用变为直接的内存地址

【实例化四个轮子,车架】jvm开启线程,主动对启动类进行类的初始化:先进行类初始化,即将方法区/堆区的静态变量进行初始化,执行静态代码块,然后是对象初始化,new的对象放到jvm的堆中,执行赋值语句,普通代码块,最后是构造函数代码。

【组装】jvm在栈中开启一个栈帧记录线程,在运行时加载该方法的局部变量表,利用操作栈对数据进行循环,遍历运算,如果在执行过程中遇到了对象引用,那就去方法区的运行时常量池将符号转化为直接引用,执行完毕后,堆中的对象被清除。

在这里插入图片描述

面试题

在这里插入图片描述

在这里插入图片描述

当在多次minor GC后仍然存活的满足一定存活代数的对象,或者是由于太大无法在新生代中分配的对象

在这里插入图片描述

java8之前,两种模式

  • 所有的类信息(运行时常量池)和静态变量,字符串常量都放在永久代上
  • 只剩类信息(运行时常量池)在永久代 / 静态变量,字符串常量放在堆中

java8之后

  • jvm没有永久代的概念,类信息(运行时常量池)放在本地内存上,叫元空间

为什么有这个变动呢?

  • 因为随着类加载变多,我们无法定义一个合适的永久代空间,因此放到本地的话,元空间的大小只受限于本地的内存大小
  • 原始字符串常量放在永久代中,只有full GC(老年代或者永久代不足)的时候才会被清理,回收效率不高,所以新的改进是放到堆中,跟随对象及时回收内存

行时常量池)放在本地内存上,叫元空间

为什么有这个变动呢?

  • 因为随着类加载变多,我们无法定义一个合适的永久代空间,因此放到本地的话,元空间的大小只受限于本地的内存大小
  • 原始字符串常量放在永久代中,只有full GC(老年代或者永久代不足)的时候才会被清理,回收效率不高,所以新的改进是放到堆中,跟随对象及时回收内存

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

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

相关文章

单通道低压 H 桥电机驱动芯片AT9110H 兼容L9110 马达驱动芯片

H桥直流电机驱动电路是一种用于控制直流电机运转的电路,其主要特点是可以实现正反转控制,控制电机转速和方向,同时也具有过流保护功能。 H桥电路由四个功率晶体管和一些辅助电路组成,其中两个晶体管用于控制电机正转,…

【MySQL】一文学会所有MySQL基础知识以及基本面试题

文章目录 前言 目录 文章目录 前言 一、主流数据库以及如何登陆数据库 二、常用命令使用 三、SQL分类 3.1 存储引擎 四、创建数据库如何设置编码等问题 4.1操纵数据库 4.2操纵表 五、数据类型 六、表的约束 七、基本查询 八、函数 九、复合查询 十、表的内连和外连 十一、索引…

基于ssm的校园办公室报修管理系统

基于ssm的校园办公室报修管理系统 摘要 基于SSM的校园办公室报修管理系统是一个现代化的、高效的报修平台,它能够帮助校园内的教职工和学生更方便、更快捷地提交和处理报修请求。该系统基于Spring、SpringMVC和MyBatis(简称SSM)开发&#xff…

iOS 16.4 之后真机与模拟器无法使用Safari调试H5页面问题

背景 iOS 16.4之后用真机调试H5时候发现,Safari中开发模块下面无法调试页面 解决方案 在WKWebView中设置以下代码解决 if (available(iOS 16.4, *)) {[_webView setInspectable:YES];}然后再次调试就可以了

【C++类和对象中:解锁面向对象编程的奇妙世界】

【本节目标】 1. 类的6个默认成员函数 2. 构造函数 3. 析构函数 4. 拷贝构造函数 5. 赋值运算符重载 6. const成员函数 7. 取地址及const取地址操作符重载 1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗&#xf…

迅为龙芯3A5000主板,支持PCIE 3.0、USB 3.0和 SATA 3.0显示接口2 路、HDMI 和1路 VGA,可直连显示器

性能强 采用全国产龙芯3A5000处理器,基于龙芯自主指令系统 (LoongArch)的LA464微结构,并进一步提升频率,降低功耗,优化性能。 桥片 桥片采用龙芯 7A2000,支持PCIE 3.0、USB 3.0和 SATA 3.0显示接口2 路、HDMI 和1路 …

Leetcode---370周赛

题目列表 2923. 找到冠军 I 2924. 找到冠军 II 2925. 在树上执行操作以后得到的最大分数 2926. 平衡子序列的最大和 一、找到冠军I 第一题模拟题,简单来说是看每一行(列)是否全是1,当然不包括自己比自己强的情况,需要特判 代码如下 …

xdcms漏洞合集-漏洞复现

目录 xdcms v3.0.1漏洞 环境搭建 代码审计 目录总览 配置文件总览 登陆处sql注入 漏洞分析 漏洞复现 注册处sql注入漏洞 漏洞分析 漏洞复现 getshell 任意文件删除 xdcms订餐网站管理系统v1.0漏洞 简介 环境搭建 全局变量的覆盖 漏洞分析 漏洞复现 后台任意…

Android平台上执行C/C++可执行程序,linux系统编程开发,NDK开发前奏。

Android平台上执行C/C可执行程序,linux系统编程开发,NDK开发前奏准备。 1.下载NDK,搭建NDK开发环境 下载地址 https://developer.android.com/ndk/downloads 下载过程中点击下面箭头的地方,点击鼠标右键,复制好下载…

分享vmware和Oracle VM VirtualBox虚拟机的区别,简述哪一个更适合我?

VMware和Oracle VM VirtualBox虚拟机的区别主要体现在以下几个方面: 首先两种软件的安装使用教程如下: 1:VMware ESXI 安装使用教程 2:Oracle VM VirtualBox安装使用教程 商业模式:VMware是一家商业公司,而…

ubuntu 安装redis详细教程

下载redis安装包 链接如下: http://redis.io/download 本例版本为:redis-7.2.3.tar.gz 下载安装包到目录/opt下,路径可修改,本例为/opt wget https://github.com/redis/redis/archive/7.2.3.tar.gz 解压安装包,并…

整理笔记——稳压直流电路知识

一、稳压直流电路的基本构成 稳压直流电路就是把生活中常用的220V交流电转换成稳压直流电。如生活中常见的手机充电器就是一个稳压直流电路。其主要功能是提供持续稳定且满足要求的电压。 直流稳压电路由一下几个模块组成: 下面具体分析下各个模块的功能。…

个人前端编程技巧总结

目录 1. 让界面位于当前屏幕的中心(屏幕中心)css代码示例 2. 界面透明但是内部元素不透明(毛玻璃)css代码示例 3. 将当前界面的参数传递到跳转的目标页面(携参跳转)js代码 1. 让界面位于当前屏幕的中心&…

API接口自动化测试

本节介绍,使用python实现接口自动化实现。 思路:讲接口数据存放在excel文档中,读取excel数据,将每一行数据存放在一个个列表当中。然后获取URL,header,请求体等数据,进行请求发送。 结构如下 excel文档内容如下&#x…

Python的版本如何查询?

要查询Python的版本,可以使用以下方法之一: 1.在命令行中使用python --version命令。这会显示安装在计算机上的Python解释器的版本号。 # Author : 小红牛 # 微信公众号:wdPython2.在Python脚本中使用import sys语句,然后打印sy…

Django(二、静态文件的配置、链接数据库MySQL)

文章目录 一、静态文件及相关配置1.以登录功能为例2.静态文件3.资源访问4.静态文件资源访问如何解决? 二、静态文件相关配置1. 如何配置静态文件配置?2.接口前缀3. 接口前缀动态匹配4. form表单请求方法补充form表单要注意的点 三、request对象方法reque…

【服务发现与配置】Consul特性及搭建

文章目录 一、前言二、概念2.1、什么是Consul?2.2、Consul具有哪些特点?2.3、Consul 架构图2.4、Consul的使用场景 三、安装3.1. 下载3.2. 解压3.3. 拷贝到usr目录下3.4. 查看 安装是否成功3.5. 启动 四、Consul 开机自启动4.1. 路径/usr/lib/systemd/system/&…

前端工程化(vue2)

一、环境准备 1.依赖环境:NodeJS 官网:Node.js 2.脚手架:Vue-cli 参考网址:安装 | Vue CLI 介绍:Vue-cli用于快速的生成一个Vue的项目模板。主要功能有:统一的目录结构,本地调试&#xff0…

电脑msvcp110.dll丢失怎么办,msvcp110.dll缺失的详细修复步骤

在现代科技发展的时代,电脑已经成为我们生活和工作中不可或缺的工具。然而,由于各种原因,电脑可能会出现一些问题,其中之一就是msvcp110.dll文件丢失。这个问题可能会导致一些应用程序无法正常运行,给我们的生活和工作…

muduo源码剖析之TcpClient客户端类

简介 muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Conneccor发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClient class只管理一个TcpConnecction,连接建立成功后设置相应的回调函数…