【Java】「深入理解Java虚拟机」学习笔记(2)- JVM内存区域
一、运行时数据区
JVM在执行Java程序的时候,将其运行时数据区划分为若干不同区域。它们的用途和创建及销毁的时间不同。

1、程序计数器(Program Counter Register)
是一块很小的内存空间。当线程执行的是Java方法,它记录的是当前正在执行的字节码指令的地址;当线程执行的是Native方法,则它的值为空。
2、虚拟机栈(Java Virtual Machine Stacks)
它描述的是Java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧,用来存储变量表、操作数栈、动态链接和方法出口等信息。每个方法
从调用到执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
3、本地方法栈(Native Method Stack)
顾名思义,它和虚拟机栈的区别是:它为本地方法的执行提供服务,虚拟机栈为Java方法的执行提供服务。
Hotspot不区分虚拟机栈和本地方法栈。
4、堆(Heap)
它是JVM所管理的内存中最大的一块,随虚拟机启动而创建。它唯一的作用就是存放对象实例,几乎所有的对象实例和数组都是在堆上分配,所以是GC的主要管理区域。
我是不是可以把它当做对象区?
5、方法区(Method Area)
又称作非堆(None-Heap),这个称谓在JConsole等工具中很常见。它用于存储已经被JVM加载的类信息、常量、静态变量以及即时编译器编译后的代码等。
我是不是可以把它当做类区?
|
♣运行时常量池 方法区中除了存放跟类相关的信息之外,还有一部分是运行时常量池。它用来存放编译器产生的字面量和符号引用。 int i = 1; //将1赋值给变量i,那么1就是字面量 String s = "abc"; //字符串abc也是字面量 字面量包括整数、浮点数、字符串有些语言的字面量还包括布尔型。 在编译时, Java类并不知道所引用的类的实际地址, 因此只能使用符号引用来代替。比如org.simple.People类引用了org.simple.Language类,在编译时People类并不知道 Language类的实际内存地址(只有运行时,类被加载之后才知道), 因此只能使用符号org.simple.Language来表示Language类的地址,org.simple.Language就是所谓的符号引用。 运行时常量池的作用是节省空间和时间。例如字符串常量池,在编译阶段就把所有的字符串放到一个常量池中,可以避免频繁的创建和销毁对象而影响系统性能,同时实现了对象的共享。 |
|
♣直接内存 这部分内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。 JDK1.4的NIO引入了一种基于通道(Chanel)和缓冲区(Buffer)的一种I/O,利用native函数库直接分配外部内存。然后通过分配在堆中的DirectByteBuffer对象作为这块内存的引用 来对其进行操作。 这块内存不容忽视,因为它属于主机总内存的一部分,溢出也会报错java.lang.OutOfMemoryError。其容量通过参数XX进行设置,默认值同Java堆最大值(Xmx)一致。 |
二、对象的创建
对象的创建一般是在new、对象克隆和反序列化的时候。

三、对象的内存布局

四、对象的访问定位
一般地,对象的访问定位方式有两种:通过句柄访问和通过直接指针访问。
JVM在调用一个方法的时候,会在虚拟机栈上创建栈帧,其本地变量表中会包含对象的reference。
1、通过句柄访问:
在堆上划出一部分作为对象句柄池,句柄中包含两个指针—对象实例数据指针和对象类型数据指针。reference用句柄作为跳板,来访问对象的实例数据(堆上)
和对象类型数据(方法区里)。
2、通过直接指针访问:
堆上不单独划句柄池,在给对象分配的内存中包含对象实例数据和类型数据指针。通过reference直接访问对象实例数据,通过类型数据指针作为跳板来访问
方法区中的对象类型数据。Hotspot使用这种方法。
五、内存溢出
1、堆溢出
堆溢出会报错java.lang.OutOfMemoryError。
首先要区分是泄露还是溢出,泄露一般是由于某些原因导致对象脱离了GC的管理。如果是溢出,可以考虑优化虚拟机的堆参数(Xms和Xmx)。
可以通过内存映射分析工具Eclipse Memory Analyzer进行分析,找到解决方案。
2、虚拟机和本地方法栈溢出
原因有两个:①线程请求栈深度超过虚拟机允许的最大值,会报错java.lang.StackOverFlow;
②栈空间的额度给的太小,会报错java.lang.OutOfMemoryError。
3、方法区和运行时常量池
原因是运行时加载了大量的类信息填满了方法区导致溢出,会报错java.lang.OutOfMemoryError。
4、Hotspot虚拟机架构

【参考文章】
https://blog.csdn.net/BraveLoser/article/details/82500474
https://blog.csdn.net/BraveLoser/article/details/82500474
https://javapapers.com/java/java-garbage-collection-introduction/
【Java】「深入理解Java虚拟机」学习笔记(2)- JVM内存区域的更多相关文章
- 【Java】「深入理解Java虚拟机」学习笔记(1) - Java语言发展趋势
0.前言 从这篇随笔开始记录Java虚拟机的内容,以前只是对Java的应用,聚焦的是业务,了解的只是语言层面,现在想深入学习一下. 对JVM的学习肯定不是看一遍书就能掌握的,在今后的学习和实践中如果有 ...
- 《深入理解Java虚拟机》学习笔记1-内存数据区域
1.程序计数器 作用-较小的内存空间,用于存储当前线程所执行的字节码的行号 特性-每条线程有需要一个独立的程序计数器,各线程间互不影响,独立存储,称为"线程私有"的内存 ...
- 【Java】「深入理解Java虚拟机」学习笔记(5)- 类加载
C/C++在编译时需要进行连接,而Java的类加载.连接和初始化是在运行时完成的. 图 类的生命周期 图中解析的过程不一定在准备和初始化之间,也可以在初始化之后再开始,以支持Java的运行时动态绑定 ...
- 【Java】「深入理解Java虚拟机」学习笔记(4)- 类文件结构
我为什么喜欢Java,另一个重要原因就是跨平台,WORA. 程序员是爽了,但肯定有人要为你遮风挡雨,解决WORA的基石就是字节码+虚拟机. ♣Tip 其实这里存在两种无关性,一是平台无关性.另一个是语 ...
- 「中国剩余定理CRT」学习笔记
设正整数$m_1, m_2, ... , m_r$两两互素,对于同余方程组 $x ≡ a_1 \ (mod \ m_1)$ $x ≡ a_2 \ (mod \ m_2)$ $...$ $x ≡ a_r ...
- Java四种引用--《深入理解Java虚拟机》学习笔记及个人理解(四)
Java四种引用--<深入理解Java虚拟机>学习笔记及个人理解(四) 书上P65. StrongReference(强引用) 类似Object obj = new Object() 这类 ...
- Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)
Java虚拟机内存溢出异常--<深入理解Java虚拟机>学习笔记及个人理解(三) 书上P39 1. 堆内存溢出 不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达 ...
- 《深入理解Java虚拟机》学习笔记
<深入理解Java虚拟机>学习笔记 一.走近Java JDK(Java Development Kit):包含Java程序设计语言,Java虚拟机,JavaAPI,是用于支持 Java 程 ...
- 《深入理解 Java 虚拟机》学习笔记 -- 内存区域
<深入理解 Java 虚拟机>学习笔记 -- 内存区域 运行时数据区域 主要分为 6 部分: 程序计数器 虚拟机栈 本地方法栈 Java 堆 方法区 如图所示: 1. 程序计数器(线程私有 ...
随机推荐
- Microsoft Windows .Reg File Dialog Box Message Spoofing 0day
Microsoft Windows .Reg文件对话框消息欺骗 0day 概述 扩展名为.reg的文件是Windows注册表中使用的注册文件.这些文件可以包含hives.密钥和值..reg文件可以在文 ...
- Java SE之反射技术[Class,Field](一)
一.什么是反射? 反射库(Reflection Library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵Java代码的程序.这项功能被大量地应用在JavaBeans中,它是Java组 ...
- js伪数组转数组
方法1: 遍历伪数组,在把值push进一个空数组中 方法2: 使用数组的slice方法,它返回的是数组,使用call或apply指向伪数组 var arr = [].slice.call(argume ...
- 在github上创建自己的项目
使用过很多次github 但一直是把别人的项目clone下来,并没有自己创建过项目.所以记录一下~ 首先,创建一个仓库 填写工程名之后就创建好啦 然后clone代码到本地 就和正常的使用完全一样啦 ~ ...
- scrapy基本使用(二)
scrapy基本使用(二) 参考链接: http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html#id5 scrapy基本使用(一 ...
- js中创建数组,并往数组里添加元素
数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长 ...
- Linux下安装PCRE
原文链接:https://www.linuxidc.com/Linux/2015-03/114986.htm PCRE(Perl Compatible Regular Expressions)是一个轻 ...
- 关于Oracle数据库后台进程
为了最大限度地提高性能并适应许多用户,多进程Oracle数据库系统使用后台进程.后台进程将合并功能,否则这些功能将由运行于每个用户进程的多个数据库程序处理.后台进程异步执行I / O并监视其他Orac ...
- adapter.notifydatasetchanged()没有效果
项目中有个列表的处理,通过一个参数判断是下拉刷新数据还是加载更多数据,结果下拉刷新就是显示不出来界面,数据是有,就开始searching~,搜出很多相关问题,大意如下: 1 当数据源发生变化的时候,我 ...
- 【Linux】时间同步设置+防火墙设置+SELinux设置
时间同步设置 在大数据集群环境中,要求每台集群的时间必须是同步的,这样我们就会要求每台集群的时间必须和一台服务的时间是同步的.接下来介绍一下步骤: 1,设置ntp客户端 yum -y install ...