【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. 程序计数器(线程私有 ...
随机推荐
- Debian Security Advisory(Debian安全报告) DSA-4412-1 drupal7 security update
Debian Security Advisory(Debian安全报告) DSA-4412-1 drupal7 security update Package:drupal7 CVE ID:暂无 Dr ...
- luogu P4389 付公主的背包
传送门 神仙题鸭!orz dkw 暴力就是完全背包 而完全背包可以和生成函数扯上关系,记第i种物品质量为\(a_i\),那么这种物品的生成函数\(G(i)=\sum_{j=0}^{\infty}x^{ ...
- 贝叶斯网络与LDA
一.一些概念 互信息: 两个随机变量x和Y的互信息,定义X, Y的联合分布和独立分布乘积的相对熵. 贝叶斯公式: 贝叶斯带来的思考: 给定某些样本D,在这些样本中计算某结论出现的概率,即 给定样本D ...
- java伪代码 大道至简第一章
import.java.大道至简.*; //一·编程的精义 import.java.编程的精义.*; public class BIANCHENGDEJINGYI { if(愚公死了) 愚公的儿子,孙 ...
- 解决ASP.NET中ServiceStack.Redis每小时6000次访问请求的问题
1.可以使用3.0的版本: Install-Package ServiceStack.Redis -Version 3.0 2.使用ServiceStack.Redis.Complete: Insta ...
- 【译】第七篇 SQL Server安全跨数据库所有权链接
本篇文章是SQL Server安全系列的第七篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...
- lua 语法的使用总结
1.字符串连接 local tmp = "abc" local tmp1 = "ddd" tmp..tmp1 2. table 类型 就是关联数组 local ...
- Android RecyclerView 瀑布流滑动到最后自动加载更多
mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener(){ //用来标记是否正在向最后一个滑动,既是否向下滑动 bool ...
- redis设置开机自启
开机自启动redis(其他服务类似) centos 7以上是用Systemd进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvini ...
- python读取两个文件并且判断是否一致
''' 判断两个文件是否相同,如果不同请指出第几行不相同 ''' def f1vsf2(name1,name2): f1 = open(name1) f2 = open(name2) count = ...