【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. 程序计数器(线程私有 ...
随机推荐
- 一个简单至极的PHP缓存类代码
https://www.jb51.net/article/73836.htm 直接看代码吧!使用说明:1.实例化$cache = new Cache(); 2.设置缓存时间和缓存目录$cache = ...
- jira和svn关联后,不显示Subversion Commits标签或不显示svn提交信息
1.jira的版本是7.3.6 2.不显示Subversion Commits标签或不显示svn提交信息 其实是权限的分配问题 3.管理员登录 找到对应项目的权限管理 4.[评论权限]——[编辑所有评 ...
- Leetcode#53.Maximum Subarray(最大子序和)
题目描述 给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大. 例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4], 连续子序列 [4,-1,2,1] ...
- java final、finally、finalize
- listView从底部回到顶部代码实现
可用如下方法: 1.平滑的回到顶部,但是会划过中间的每一页 mListView.getRefreshableView().smoothScrollToPosition(0); 2.直接跳到顶部 if ...
- IPC$横向渗透代码实现
思路 IPC$横向渗透的方法,也是病毒常用的扩散方法. 1.建立连接 2.复制文件到共享中C$.D$.E$.F$ 3.获取服务器的时间 3.设定计划任务按时间执行 用到的Windows API 建立网 ...
- 【转】浅析Python中的struct模块
[转]浅析Python中的struct模块 最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概 ...
- ARM的Jazelle技术【转】
转自:https://blog.csdn.net/ken_yjj/article/details/6797290 Come From: http://www.arm.com/zh/products/p ...
- VS2017中用C#调试DLL
1.首先将DLL工程导入到包含C#应用程序工程的解决方案中 2.将DLL和C#工程都改为[Debug]模式 3.设置DLL工程属性,右键点击DLL工程,选择[属性],选择[常规],将[输出目录]改为C ...
- bzoj 1175: The stairways of Saharna
一道杨氏矩阵的题,萌新初入门,还不是很懂,这篇 blog 讲的超级好(就是看图有点麻烦) 据说这玩意儿可以代替堆和平衡树用,支持插入.删除.查询,跑得还挺快的(慢着,复杂度好像是 n^2 ? 而且空间 ...