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

【JVM】详解Java内存区域和分配

这里写目录标题

  • 一、前言
  • 二、运行时数据分区
    • 2.1程序计数器(PC)
    • 2.2 Java虚拟机栈
    • 2.3 本地方法栈
    • 2.4 Java堆
    • 2.5 方法区
      • 2.5.1 运行时常量池
    • 2.6 直接内存
  • 三、HotSpot虚拟机对象探秘
    • 3.1 对象的创建
    • 3.2 对象的内存布局
    • 3.3 对象的访问定位

一、前言

C/C++需要自行回收和释放已经没用的对象,但是对于Java程序员来说,在虚拟机自动内存管理机制的帮助下, 不再需要为每一个new操作去写对应的free代码,就如同吃完饭之后不需要自己收拾盘子一样。看起来一切都师范的美好,但是一旦出现内存泄漏和溢出,如果不了解虚拟机是如何使用内存的,那么排查错误、纠正问题就会是一个艰难的问题。

二、运行时数据分区

Java虚拟机再执行的时候,会将它管理的内存划分为若干个不同的数据区,这些区域各有用途,本节就是了解这些内容。根据Java虚拟机规范,JVM所管理的内存将会包括以下几个运行时区域
在这里插入图片描述

2.1程序计数器(PC)

程序计数器是一块较小的内存空间,是当前所执行的指令的行号指示器,在JVM中,字节码解释器工作是就是通过改变这个计数器来选取下一条需要执行的字节码指令,一系列分支、循环、跳转和异常处理、线程恢复都需要使用到PC。需要注意到的是,这个程序计数器是线程私有的,用于标识当前线程运行到的指令位置,它和计算机自身的PC不一样,计算机的PC只有一个,用于表示整个计算机运行到的指令的位置,而JVM中的PC是指各个Java进程运行到的位置,每一个Java进程都有一个。

2.2 Java虚拟机栈

和程序计数器一样,Java虚拟机栈也是线程私有的,他的生命周期和线程相同。虚拟机栈是Java方法执行的线程内存模型:每个方法被执行的时候,JVM会在对应线程的虚拟机栈中创建一个栈帧。这个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法被调用直到执行完毕的过程,就对应着一个栈帧在虚拟机栈中入栈出栈的过程。方法的调用和结束调用类似于栈的入栈和出栈,因此虚拟机栈中栈帧的出入栈和方法的调用是保持一致的。

局部变量表存放着许多编译器就可知的JVM基本数据类型(boolean, byte, char, short, int, float, long, double)以及对象引用、return Address类型。这些数据类型在局部变量表中以局部变量槽Slot表示,其中long和double作为64B的变量会占用两个Slot,其余的会占用一个

在虚拟机栈中,如果线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError异常;如果JVM栈可以动态扩展,但是扩展时服务申请到足够多的内存,则会抛出OutOfMemoryError异常。

2.3 本地方法栈

本地方法栈和虚拟机栈发挥的作用十分相似,区别是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到本地方法服务。

2.4 Java堆

Java堆事JVM的内存管理中最大的一块,是一个线程共享的区域,JVM启动时就会创建这片区域,所有的对象实例以及数组都应该在堆上分配,但是随着Java语言的发展,现在已经看到了一些迹象表明日后可能支持将值存放在堆上,并且由于即时编译技术的进步,栈上分配、标量替换优化手段使得将其他内容存放在堆上成为可能,因此还需要密切关注技术变化。

堆也是垃圾收集器管理的内存区域,对于垃圾回收期GC的详细介绍,会在后面详细介绍,也可以先看看这个
https://blog.csdn.net/qq_25430563/article/details/109201945

2.5 方法区

方法区和堆一样,是各个线程共享的内存区域,用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

在以前HotSpot设计团队选择把垃圾收集器的分区设计扩展至方法区,使用管理永久代的策略管理方法区,使得垃圾收集器能够像管理堆一样管理这部分内存,省去专门为方法区编写内存管理代码的工作。这使得JDK 8之前的程序员喜欢用永久代来称呼方法区,但实际上两者是不一样的,在《JMV规范》中并没有统一要求方法区需要使用何种垃圾收集策略,而常用的HotSpot虚拟机则在JDK8之前都是将方法区作为永久代进行管理,但是将方法区视作为永久代并不是一个好主意,这会导致Java更容易遇到内存溢出的问题,HotSpot从JDK6逐渐开始放弃永久代,改为使用本地内存实现方法区,在JDK8完全放弃了永久代的概念,改用在本地内存中实现元空间来替代。

2.5.1 运行时常量池

运行时常量池是方法区了一部分,class文件除了有类的版本,字段方法,接口等描述信息外,还有一项信息就是常量池表,用于存放编译期生成的各种字面量和符号引用,常量池表会在类加载后放入运行时常量池。

运行时常量池相对于Class文件中的常量池具有动态性,运行期间可以将新的常量放入到池中,这种特性用的较多的是String的intern()方法

2.6 直接内存

直接内存并不是JVM数据区的一部分,他就是平时我们讲的一般的内存空间

直接内存与堆内存的区别:
直接内存申请空间耗费很高的性能,堆内存申请空间耗费比较低
直接内存的IO读写的性能要优于堆内存,在多次读写操作的情况相差非常明显

三、HotSpot虚拟机对象探秘

本节主要探讨HotSpot虚拟机在Java堆中对象分配,布局和访问的全过程

3.1 对象的创建

当虚拟机碰到一条字节码new指令的时候,首先去检查这个指令是否能在常量池中定义到一个类的符号引用(也就是检查有没有这个类),并且检查这个类是否被加载、解析和初始化过。如果没有则先执行类加载过程。在类加载检查通过后,接下来虚拟机将为新生的对象分配内存,对象所需内存大小在类加载完成后可以完全确定,为对象分配空间实际上是等同于将一块确定大小的内存块从堆内划分出来。

如果堆中内存块是绝对规整的,那么就会将所有已经使用的内存放在边,没有使用的内存放在另一边,管理内存只需要一个指针,分配内存只是将指针向空闲空间方向挪动相同大小的距离,这种方式称为指针碰撞,Serial,ParNew等带压缩整理过程的收集器会使用此法,简单高效。另外如果堆中内存块大小不一,那么已使用和空闲的内存相互交错,JVM就需要维护一个列表,记录哪个内存块是可用的,称为空闲列表法,CMS等基于清除算法的收集器会使用该法

另外还有一个问题就是:对象创建在虚拟机中时十分频繁的过程,因此需要考虑并发问题。这有两种方式解决问题:一个是对分配内存空间的动作进行同步处理,也就是保证分配内存空间的操作的原子性。另外一个就是为各个线程预先分配一小块内存,称为本地线程分配缓冲(TLAB),某个线程需要给对象实例分配内存,则先分配到TLAB中,只有本地缓冲区用完了,才会同步锁定。

接下来JVM还需要对对象进行必要的设置,比如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象哈希码和对象的GC分代年龄信息等。完成这些共走后,从虚拟机的视角来看,一个新的对象已经产生了,但是从Java程序视角来看,对象创建才刚刚开始,构造函数(也就是Class文件中的<init>()方法)还没开始执行,所有字段都默认为零值。

3.2 对象的内存布局

在HotSpot虚拟机中,对象在堆内存中的存储布局可以划分为三个部分:对象头(header),实例数据(instance data)和对齐填充(padding)。

HotSpot虚拟机对象的对象头部分包括两类信息。第一类是用于存储对象自身的运行时数据,如哈 希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。对象头的另外一部分是类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例。这是Java实现反射的重要组成部分

接下来实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字 段内容,无论是从父类继承下来的

第三部分是对齐填充,HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,因此对齐填充用于填充空余的字节,使得一个对象的大小是8字节的整数倍。

3.3 对象的访问定位

创建对象自然是为了后续使用该对象,Java程序会通过栈上的reference数据来操作堆上的具体对象。对象访问方式也是由虚拟机实现而定的,主流的访问方式主要有使用句柄和直接指针两种:

如果使用句柄访问,Java堆中将划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息。
在这里插入图片描述

如果使用直接指针访问,Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址,如果只是访问对象本身的话,就不需要多一次间接访问的开销
在这里插入图片描述

使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,在对象被移动(垃圾收集时移动对象非常普遍)时只会改变句柄中的实例数据指针,但是需要额外一次的寻址开销;使用直接指针最大的好就是速度更快,它节省了一次指针定位的时间开销

相关文章:

【JVM】详解Java内存区域和分配

这里写目录标题一、前言二、运行时数据分区2.1程序计数器(PC)2.2 Java虚拟机栈2.3 本地方法栈2.4 Java堆2.5 方法区2.5.1 运行时常量池2.6 直接内存三、HotSpot虚拟机对象探秘3.1 对象的创建3.2 对象的内存布局3.3 对象的访问定位一、前言 C/C需要自行回收和释放已经没用的对象…...

JAVA开发(史上最完整追本溯源JAVA历史、发展和学习)

(第二次世界大战1931-1945) 世界上最先进的技术往往是由于战争催生&#xff0c;在第二次世界大战中除了飞机&#xff0c;坦克和大炮的武器较量外&#xff0c;在隐秘战线的情报工作其实更为重要&#xff0c;在军队将领来往的电报中&#xff0c;为了防止军事情报的泄漏&#xff…...

Qt 防止程序退出

文章目录摘要QWidgetQML方法 1方法 2关键字&#xff1a; Qt、 eventFilter、 Close、 键盘、 任务管理器摘要 今天要聊得内容还是怎么防止别人关闭我的程序&#xff0c;之前都是在win下面&#xff0c;一般都是用过钩子连捕获键盘事件&#xff0c;完了吧对应的事件忽略&#x…...

【校验码 - 循环冗余校验码CRC】

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 循环冗余校验码 1.多项式 2.CRC编码的组成 3.校验码的生成 4.例题&#xff1a; 循环冗余校验码 广泛地在网络通信及磁盘存储时采用。 1.多项式 在循环冗余校验(CRC)码中&#xff0c;无一例…...

【Rust】一文讲透Rust中的PartialEq和Eq

前言 本文将围绕对象&#xff1a;PartialEq和Eq&#xff0c;以及PartialOrd和Ord&#xff0c;即四个Rust中重点的Compare Trait进行讨论并解释其中的细节&#xff0c;内容涵盖理论以及代码实现。 在正式介绍PartialEq和Eq、以及PartialOrd和Ord之前&#xff0c;本文会首先介绍…...

Vulnhub靶场----9、DC-9

文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-9下载地址&#xff1a;https://download.vulnhub.com/dc/DC-9.zip kali&#xff1a;192.168.144.148 DC-9&#xff1a;192.168.144.158 二、渗透流程 1、信息收集nmap -T5 -A -p- -sV -sT 192.168.144.158思路&am…...

使用Containerd搭建K8s集群【v1.25】

[toc] 一、安装要求 在开始之前,部署Kubernetes集群机器需要满足以下几个条件: 一台或多台机器,操作系统 CentOS7.x-86_x64硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多集群中所有机器之间网络互通可以访问外网,需要拉取镜像禁止swap分区二、准备环境 角色IP…...

NMT - 构建双语概率词典(Probabilistic dictionaries)

文章目录一、安装依赖包mosesdecoder安装 mgiza二、数据预处理三、训练本文参考&#xff1a;How to train your Bicleaner https://github.com/bitextor/bicleaner/wiki/How-to-train-your-Bicleaner 一、安装依赖包 这个过程主要依赖于 mosesdecodermgiza mosesdecoder git…...

《ChatGPT是怎样炼成的》

ChatGPT 在全世界范围内风靡一时&#xff0c;我现在每天都会使用 ChatGPT 帮我回答几个问题&#xff0c;甚至有的时候在一天内我和它对话的时间比和正常人类对话还要多&#xff0c;因为它确实“法力无边&#xff0c;功能强大”。 ChatGPT 可以帮助我解读程序&#xff0c;做翻译…...

Streaming System是第一章翻译

GIthub链接&#xff0c;欢迎志同道合的小伙伴一起翻译 Chapter 1.Streaming101 如今&#xff0c;流数据处理在大数据中是非常重要的&#xff0c;其主要原因是&#xff1a; 企业渴望对他们的数据有更及时的了解&#xff0c;而转换到流处理是实现更低延迟的一个好方法&#xf…...

abap MODIFY常用语法解析

MODIFY 是既可以操作数据又可以操作内表的一个语法, 实现的逻辑都一样. 如果你内表或数据库中存在该行数据会对该行数据进行更新. 如果不存在,就会插入数据. , 1.如果it_tab是带有标题行的内表,是可以忽略FROM wa_tab工作区的 MODIFY it_tab .2.把工作区wa_tab中的数据更新…...

[媒体分流直播]媒体直播和传统直播的区别,以及媒体直播的特点

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 直播毋庸置疑已经融入到了我们生活的方方面面&#xff0c;小到才艺&#xff0c;游戏&#xff0c;大到政策的发布&#xff0c;许多企业和机构也越来越重视直播&#xff0c;那么一场活动怎…...

打地鼠游戏-第14届蓝桥杯STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第102讲。 蓝桥杯选拔赛现已更名为STEMA&#xff0c;即STEM 能力测试&#xff0c;是蓝桥杯大赛组委会与美国普林斯顿多…...

链表经典刷题--快慢指针与双指针

本篇总结链表解题思路----快慢指针&#xff0c;其实也就是双指针&#xff0c;这个快慢并不单纯指“快慢”&#xff0c;它更多的可以表示&#xff0c;速度快慢&#xff0c;距离长度&#xff0c;时间大小等等&#xff0c;用法很有趣也很独特&#xff0c;理解它的思想&#xff0c;…...

【Java集合框架】篇四:Set接口

1. Set及主要实现类特点 Set&#xff1a;无序、不可重复&#xff08;去重&#xff09;、存储value HashSet&#xff1a;底层使用HashMap&#xff0c;即使用 数组单项链表红黑树 结构进行存储。&#xff08;jkd8中&#xff09; LinkedHashSet&#xff1a;是HashSet的子类&…...

Python 数据库连接 + 创建库表+ 插入【内含代码实例】

人生苦短 我用python Python其他实用资料:点击此处跳转文末名片获取 数据库连接 连接数据库前&#xff0c;请先确认以下事项&#xff1a; 您已经创建了数据库 TESTDB.在TESTDB数据库中您已经创建了表 EMPLOYEEEMPLOYEE表字段为 FIRST_NAME, LAST_NAME, AGE, SEX 和 INCOME。连…...

DSS 部署环境需求清单

文章目录 DSS系统需求项目地址计算资源计算基准:计算引擎程序硬件需求表 :DSS计算及存储资源需求计算资源计算基准:计算程序硬件需求表:DSS系统需求 项目地址 https://github.com/WeBankFinTech/DataSphereStudio 计算资源计算基准: 1.日活用户10万。 2.单用户单日总…...

Python的面向对象,详细讲解Python之用处等基本常识

目录 Python 面向对象 面向对象技术简介 创建类 实例 实例 self代表类的实例&#xff0c;而非类 实例 创建实例对象 访问属性 实例 Python内置类属性 实例 python对象销毁(垃圾回收) 实例 实例 类的继承 实例 方法重写 实例 基础重载方法 运算符重载 实例…...

如何使用固态继电器为恒温器供电

恒温器有两种电源&#xff1a;电池和 24VAC。恒温器需要电池才能不间断地运行。电池消耗的能量尽可能低非常重要&#xff0c;但即使您最大限度地减少消耗&#xff0c;这仍然不是一个用户友好的选择&#xff0c;因为电池会不时需要更换。要降低更换频率&#xff0c;可以使用 24V…...

【LeetCode】剑指 Offer(14)

目录 题目&#xff1a;剑指 Offer 32 - I. 从上到下打印二叉树 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 32…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...