Java虚拟机(JVM):第二幕:自动内存管理 - Java内存区域与内存溢出异常
前言:Java与C++之间有一堵高墙,主要是有内存动态分配和垃圾收集技术组成的。墙外的人想要进来,墙内的人想要出去。
一、运行时数据区域
JVM在执行Java程序时,会将其管理的内存划分为若干个不同的数据区域。

1、是程序计数器,一个处理器一般只会执行一条线程的指令。为了线程切换后恢复到正确的执行位置,每一条线程都需要一个独立的程序计数器,每一个计数器互相不影响,独立存储,最重要的一点事,此类内存区域属于“线程私有”的内存。
2、接下来介绍,Java虚拟机栈也是线程私有的,虚拟机栈指的是Java方法执行的线程内存模型。经常有人将Java内存区域笼统的划分为“堆内存”和“栈内存”。这里的“栈内存”指的是Java虚拟机栈,但是确切的说是,虚拟机栈中的局部变量表部分。局部变量表存储了各种基本的数据类型,存储空间以局部变量槽表示,关于局部变量槽所占用的比特数量,有虚拟机决定。
3、其次是本地方法栈:为虚拟机用到的本地方法服务,有些虚拟机会将本地方法栈和虚拟方法栈合并(HotSpot:关于它的解释,见以前的博客)。
4、Java堆:Java堆是虚拟机所管理的内存中的最大的一部分,被所有线程所共享,同时也是垃圾收集器管理的内存区域,从分配内存的角度来看,Java堆可以分出多个线程私有的分配缓冲区,来提高对象分配时的效率。PS:根据规定,Java堆在物理上可以不连续,但是在逻辑上是连续的。
5、方法区:是一个线程共享的内存区域,用来存储已经被虚拟机加载的类型信息、常量、静态变量等数据。
6、运行时常量池:方法区的一部分,Class文件中除了常见的描述信息外,还有一项信息是常量池表,用来存放编译期生成的高中字面量和符号引用,常量池表的内容在类引用之后存放到方法区中的运行时常量池中。另外一个特征是动态性,可以在运行期间将新的常量加入池中。
7、直接内存:使用native函数库直接分配堆外内存,通过存放在Java堆中的对象作为这一部分内存的引用进行操作。
二、HotSpot虚拟机对象探秘
在第一部分,学习了内存存放什么,但是对于如何创建以及如何访问等,存在着盲区,这里采用最常见的虚拟机Hotspot和最常用的内存区域Java堆。来深入探讨一些虚拟机内部的神秘世界。
2.1、对象的创建
1、当遇到new命令时,检查指令的参数是否能在常量池中正确定位符号的引用,检查符号代表的类是否被加载、解析和初始化过。如果没有执行操作2。
2、类加载检查通过后,为新生对象分配内存(大小确定),Java堆中的内存必定存在已经分配和未被分配的,所以分配方式引入“指针碰撞”的方式进行分配内存[Java堆内存是规整的],如果不规整的话,需要采用“空闲列表”的方式,来分配内存。
3、除了划分可用空间之外,对象在虚拟机创建的行为是频繁的,经常发生“线程安全”问题,解决方法:1、保证分配空间的原子性。2、预先分配内存,此方式为“本地线程分配缓冲”:哪家线程要分配内存,就在哪家的本地缓冲区中分配,只有这一次的本地缓冲区用完之后,采用分配新的,同时进行同步锁定。
4、分配到的内存空间初始化为零值,这样的操作,对应到Java代码中为:不用赋予初始值就可以使用。
5、所有的信息都要存储到对象头中。
6、虽然上述操作介绍完了,但是仅此还是不够的。对象构建需要的其他资源也没有弄好。
2.2、对象的内存布局
HotSpot虚拟机中,对象在堆内存中的存储布局主要分为三个部分:对象头、实例数据、对齐填充。
首先介绍一下对象头,对象头主要分为两部分,第一部分是用于存储对象自身的运行时数据,包括各类的标识元数据信息,为了更好的存储数据,所以将此设计为动态定义的数据结构。第二部分是类型指针,也就是对象指向它的类型元数据的指针,查找对象的元数据信息并不一定经过对象本身。
实例数据:用来存储对象的真正有效的信息,也就是我们在程序代码中定义的各种类型的字段内容。
对齐填充:仅仅是占位符的作用,因为自动内存管理系统要求对象的起始地址必须是8字节的整数倍,所以,对于对象实例数据没有对齐的部分,就需要通过填充来对齐。
2.3、对象的访问定位
因为在Java程序中没有被定义,所以具体的访问方式需要在虚拟机中去实现,主流的访问方式有使用句柄和直接指针两种。
1、使用句柄:这个像是引入了“中间商”,Java堆中划出一块内存来当做句柄池。
2、使用直接访问:reference存储的直接就是对象地址。
两者只能说是各有优劣,句柄最大的好处是,当对象被移动是,只会修改句柄中的实例数据指针,而reference本身不需要修改。直接指针最大的优点就是访问速度更快。本文以HotSpot为主,它采用的是直接指针访问的方式,但是如果从整个软件开发的范围来看,使用句柄来访问显得更加的优秀。
三、实战:OutOfMemoryError 异常
1、Java堆溢出:这种异常方式是最为常见的内存溢出情况,解决方法在于:通过内存映像分析工具 对Dump出来的堆转储快照进行分析。存在内存泄漏和内存溢出两种。
2、虚拟机栈和本地方法栈溢出:
3、方法区和运行时常量池溢出:运行时常量池是方法区的一部分.
4、本地直接内存溢出‘:直接内存的大小可以通过参数来制定。
Java虚拟机(JVM):第二幕:自动内存管理 - Java内存区域与内存溢出异常的更多相关文章
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
- Java虚拟机------JVM内存区域
JVM内存区域运行时数据区域分为两种: JVM内存区域 运行时数据区域分为两种: 线程隔离的数据区: 程序计数器 Java虚拟机栈 本地方法栈 所有线程程共享的数据区: Java堆 方法区 JVM 内 ...
- java虚拟机 jvm 出入java栈 栈空间内存分配
java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...
- 如何设置Java虚拟机JVM启动内存参数
Tomcat默认的Java虚拟机JVM启动内存参数大约只有64MB或者128MB,非常小,远远没有利用现在服务器的强大内存,所以要设置Java虚拟机JVM启动内存参数.具体设置方法为: Tomcat修 ...
- 深入理解java虚拟机_第二章_读书笔记
1.本章内容目录: 概述 运行时数据区域 程序计数器 java虚拟机栈 本地方法栈 java堆 方法区 运行时常量池 直接内存 HotSpot虚拟机对象探秘 对象的创建 对象的内存布局 对象的访问定位 ...
- Java虚拟机(JVM)知多少
本文大量参考:https://www.cnblogs.com/lfs2640666960/p/9297176.html 概述 JVM是JRE的一部分.它是一个虚构出来的计算机,是通过在实际的计算机上仿 ...
- 深入理解java虚拟机JVM(下)
深入理解java虚拟机JVM(下) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...
- Java虚拟机JVM相关知识整理
Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系 ...
- 深入理解java虚拟机JVM(上)
深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...
随机推荐
- 1. CS和BS的优缺点
1. CS CS : 客户端服务器架构模式 优点 : 充分利用客户端机械的资源 , 减轻服务器的符合 缺点 : 需要安装 : 升级维护成本较高 2. BS 优点 : 客户端不需要安装 : 维护 ...
- Java判断一个数是不是质数
判断一个数是不是质数 做这个题之前我们需要先进行了解什么是质数 质数:只能被1和它本身整除的数 举一个简单的例子:数字5是不是质数呢? 我们可以进行分析: 解题思路:5可以分为1 2 3 4 5,我们 ...
- Java使用数组存储成绩,输出成绩列表,总分,平均分
代码如下: public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out. ...
- ELK8.8部署安装并配置xpark认证
ELK8.8部署安装并配置xpark认证 介绍 主要记录下filebeat+logstash+elasticsearch+kibana抽取过滤存储展示应用日志文件的方式:版本基于8.8,并开启xp ...
- Kubernetes(k8s) Web-UI界面(一):部署和访问仪表板(Dashboard)
目录 一.系统环境 二.前言 三.仪表板(Dashboard)简介 四.部署Kubernetes仪表板(Dashboard) 五.访问Kubernetes仪表板(Dashboard) 5.1 使用to ...
- 面试官:讲讲MySql索引失效的几种情况
索引失效 准备数据: CREATE TABLE `dept` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `deptName` VARCHAR(30) DEFAUL ...
- 2023-07-03:讲一讲Redis缓存的数据一致性问题和处理方案。
2023-07-03:讲一讲Redis缓存的数据一致性问题和处理方案. 答案2023-07-03: 数据一致性 当使用缓存时,无论是在本地内存中缓存还是使用 Redis 等外部缓存系统,会引入数据同步 ...
- 脱发秘籍:前端Chrome调试技巧汇总
Chrome浏览器调试工具的核心功能: 注:本文测试.截图均为Edge浏览器(内核是Chromium),浏览器内核可了解<有哪些浏览器/内核?> 00.基础操作汇总 操作类型 快捷键/说明 ...
- C++ 惯用法之 Copy-Swap 拷贝交换
C++ 惯用法之 Copy-Swap 拷贝交换 这是"C++ 惯用法"合集的第 3 篇,前面 2 篇分别介绍了 RAII 和 PIMPL 两种惯用法: RAII: Resouce ...
- Redis Stack:基于Redis的搜索、文档、图形和时间序列功能
基于Redis的搜索.文档.图和时间序列功能整合到一个扩展Redis Stack中,以使开发人员能够轻松构建实时应用程序. Redis Stack 于 3 月 23 日发布,由三个组件组成: Redi ...