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,操作更 ...
随机推荐
- 前端vue uni-app多图片上传组件,支持单个文件,多个文件上传 步骤条step使用
快速实现多图片上传组件,支持单个文件,多个文件上传 步骤条step使用; 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=1274 ...
- java调用WebService(未完成)记录篇
背景: 因工作需要和一个Sap相关系统以WebService的方式进行接口联调,之前仅听过这种技术,但并没有实操过,所以将本次开发相关的踩坑进行记录 通过一个实例来认识webservice 服务端 首 ...
- FFmpeg合并视频和音频文件
使用IDM下载Bilibili的视频会出现音视频分离的问题,通常文件大的是视频(没有声音),文件小的是单独的音频. 将两个文件都下载下来后,可以使用FFmpeg将其合并成一个视频文件.首先去FFmpe ...
- 安装VMware Workstation 16 Pro
下载 官网:https://www.vmware.com/cn/products/workstation-pro/workstation-pro-evaluation.html 注:我是在新毒霸软件管 ...
- 【环境搭建】vscode调试php
待解决问题 使用vscode和phpstudy实现PHP的本地调试 解决办法 1.打开xdebug 找到网站使用的PHP版本,在设置中将Xdebug调试组件打开,并确认端口是9000 找到php扩展目 ...
- webshell工具流量特征
常见的webshell管理工具及流量特征 菜刀 作为老牌 Webshell 管理神器,中国菜刀的攻击流量特征明显,容易被各类安全设备检测,实际场景中越来越少使用,加密 Webshell 正变得日趋流行 ...
- linux基础命令及常用命令总结
1.ls命令 ls命令是最基础的命令之一,作用是列出当前目录下所有的文件和目录.ls命令有很多选项可以使用,比较常用的是-l选项,可以以详细信息的形式列出所有文件和目录的信息. 示例:列出当前目录下的 ...
- Spring—bean的作用域
beans的作用域 单例模式(Spring默认模式) <?xml version="1.0" encoding="UTF-8"?> <bean ...
- Elementary OS old version download 旧版本下载
Elementary OS 号称是最漂亮的Linux发行版,没有之一.确实,他的整体风格看起来就是特别舒服,说不出哪里特别好,但也挑不出什么毛病.相比之下,其他Linux的界面总感觉不太和谐.比如特别 ...
- Linux 脚本:冒泡排序
#!/bin/bash arr=(3 2 5 4 1) len=${#arr[@]} for i in $(seq 1 $len) ; do index=$(($len - $i - 1)) for ...