【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. 程序计数器(线程私有 ...
随机推荐
- Linux 下磁盘挂载
Linux 磁盘挂载 新硬盘挂载: fdisk /dev/sdb p # 打印分区 d # 删除分区 n # 创建分区,(一块硬盘最多4个主分区,扩展占一个主分区位置.p主分区 e扩展) w # 保存 ...
- es6写法
我们在日常开发中,如果我们使用es5则可以直接在浏览器里面写JavaScript脚本.一点问题也没有. 但是在写es6语法的JavaScript代码的时候,我们就需要引入babel翻译器了. 例如: ...
- UE4 二维相关
SceneCapture2D (类似相机组件)可将视口内的图像转化为平面二维纹理资源渲染到 RenderTargetRenderTarget 可以被 Material直接使用例:做小地图SceneC ...
- 异步Async
1.c#异步介绍 异步必须基于委托,有委托才有异步 新建一个window Form程序MyAsync,添加一个按钮,(name)=btnAsync 后台代码如下: using System;using ...
- Flask中Mysql数据库的常见操作
from flask import Flask,render_template #导入第三方链接库sql点金术 from flask_sqlalchemy import SQLAlchemy #建立对 ...
- JDBC、DBCP、C3P0、jdbc-pool--链接方式?连接池?
连接方式: java连接数据库的四种方式 - Cece_2012的专栏 - CSDN博客http://blog.csdn.net/cece_2012/article/details/7485482 J ...
- wait/notify实现线程间的通信
使线程之间进行通信之后,系统间的交互性更加强大,在大大提高CPU利用率的同时还会使程序对各线程任务在处理的过程中进行有效的把控与监督. 1.不使用wait/notify实现线程间通信 使用sleep( ...
- 20165325《Java程序设计》第九周学习总结
一.教材学习笔记 ch13 1.URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符,使用URL创建对象的应用程序称作客户端程序. 一个URL对象通常包含最基本 ...
- Faster_RCNN 2.模型准备(上)
总结自论文:Faster_RCNN,与Pytorch代码: 本文主要介绍代码第二部分:model/utils , 首先分析一些主要理论操作,然后在代码分析里详细介绍其具体实现. 一. 主要操作 1. ...
- Python3-递归函数
什么是递归? 递归,就是函数在运行的过程中调用自己. 代码示例 def recursion(n): print(n) recursion(n+) recursion() 出现的效果就是,这个函数在不断 ...