jvm虚拟机中运行时数据区域介绍
jvm虚拟机中,运行时数据区域包括七大部分
i. 程序计算器
i. 定义
1) 极小的内存空间;
2) 行号指示器,程序的分支、循环、跳转、异常处理、线程恢复等基本功能都需要依赖程序计算器;
3) 线程私有的。
ii. 由来
因为java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在一个确定的时刻,一个cpu只执行一条线程中的指令;为了线程切换后能
恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间计数器互不影响,独立存储,此内存为线程私有。
iii. 不同的使用场景
1) 线程执行的是java方法,计数器记录的是正在执行的虚拟机字节码指令的地址;
2) Native方法,计数器值为空;
iv. 注意
在java虚拟机规范中唯一没有规定任何OutOfMemoryError情况的区域
ii. java虚拟机栈
i. 定义
1) 线程私有的,生命周期与线程相同;
2) 虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
3) 方法的调用直至执行完成的过程,对应着栈帧在虚拟机栈中入栈到出栈的过程。
ii. 虚拟机栈主要的部分是局部变量表
1) 存放了编译器可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double-8 种)、对象引用和returnAddress类型(指向了一条字节码指令的地址);
2) 局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小;
3) 64位的long和double类型的数据占据2个局部变量空间。
iii. 两种异常
1) 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
2) 如果虚拟机可以动态扩展,如果扩展时无法申请到足够的内存,将会抛出OutOfMemoryErro异常。
iii. 本地方法栈
1) 与虚拟机栈作用类似,本地方法栈是虚拟机栈使用到的Native方法服务;
2) 在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构没有强制规定,具体的虚拟机可以自由实现;
3) Sun HotSpot虚拟机把本地方法栈和虚拟机栈结合;
4) 本地方法栈也会报虚拟机栈的两种异常。
iv. java堆
i. 定义
1) java虚拟机管理的最大的一块内存;
2) 所有线程共享的内存区域;
3) 目的:存放对象实例,几乎所有的对象实例都在这里分配内存;(所有的对象实例以及数组都要在堆上分配)
4) 特别注意的是: 随着JIT编译器的发展与逃逸分析技术的成熟,栈上分配、标量替换优化技术带来了变化。
ii. 垃圾收集器
1) 垃圾收集的主要区域,也称为“GC堆”;
2) 从内存回收的角度:基本采用分代收集算法,一:java堆分为新生代和老年代;二:Eden空间、From Survivor空间、To Survivor空间等;
3) 从内存分配的角度:线程共享的java堆中可能划分出多个线程私有的分配缓冲区。目的是为了更好地、更快地回收内存;
iii. 物理内存的划分
1) java虚拟机规范规定,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可;
2) 实现时,即可是固定大小的,也可是可扩展的;当前主流的虚拟机都是可扩展的,通过-Xmx和-Xms控制;
3) 如果堆中没有内存,并且堆也无法扩展 ,抛出OutOfMemoryError异常。
v. 方法区
i. 定义
1) 所有线程共享的内存区域;
2) 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
ii. 方法区等于永久代?
1) 在HostSpot虚拟机中, 使用永久代来实现方法区,这样的话垃圾收集器可以像管理Java堆一样管理这部分内存;
2) 原则上,如何实现方法区属于虚拟机实现细节,不受虚拟机规范约束,使用永久代来是实现方法区是不合理的;因为容易出现内存溢出的问题;
3) Jdk1.7中,永久代中的字符串常量池中移出。
iii. 垃圾收集
1) 方法区和java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集;
2) 垃圾收集行为在方法区较少出现,方法区的内存回收目标主要是针对常量池的回收和对类型的卸载;(回收效果差,类型卸载要求高)
3) 回收非常有必要,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
vi. 运行时常量池
i. 定义
1) 方法区的一部分;
2) 存放的是: 类加载后class文件中常量池的信息;
3) Class文件包括: 1 常量池 2 类的基本描述信息(字段、方法、接口)
ii. 运行时常量池和Class文件中的常量池
1) 运行时常量池,细节要求不高,可以根据不同的需求来实现该内存区域;
2) Class包括其中的常量池,格式要求严格,具体到每一个字节存储的数据都必须符合才能被虚拟机认可、装载和执行;
3) 运行时常量池,不仅保存Class文件中描述的符号引用,而且也保存翻译的直接引用。
iii. 动态性
1) java语言并不要求常量一定只有编译器才能产生,也就是说不是只有提前放置在Class文件常量池中的内容才能进入方法区的运行时常量池;
2) 在运行期也可以将新的常量放入运行时常量池,比如String的intern()方法、
3) 常量池可能报OutOfMemoryError异常。
vii. 直接内存
i. 定义
1) Nio类,一种基于通道与缓存区的I/o方式,可以使用Native函数库直接分配堆外内存,通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用;
2) Nio的使用在某些场合避免了在java堆和Native堆中来回复制数据,提高了性能;
3) 直接内存不受java堆大小的控制,但是受到本机总内存大小以及处理器寻址空间的限制;
4) 也是会报OutOfMemoryError异常。
参考: java虚拟机第二版

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
最长公共子序列(LCS)
问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与母串保持一致,我们将其称为公共子序列。最长公共子序列(Longest Common Subsequence,LCS),顾名思义,是指在所有的子序列中最长的那一个。子串是要求更严格的一种子序列,要求在母串中连续地出现。在上述例子的中,最长公共子序列为blog(cnblogs,belong),最长公共子串为lo(cnblogs, belong)。 求解算法 对于母串X=, Y=,求LCS与最长公共子串。假设Z=是X与Y的LCS, 我们观察到: 如果Xm=Yn,则Zk=Xm=Yn,有:Zk−1是Xm−1与Yn−1的LCS; 如果Xm≠Yn,则Zk是Xm与Yn−1的LCS,或者是Xm−1与Yn的LCS。 因此,求解LCS的问题则变成递归求解的两个子问题。但是,上述的递归求解的办法中,重复的子问题多,效率低下。改进的办法——用空间换时间,用数组保存中间状态,方便后面的计算。这就是动态规划(DP)的核心思想...
-
下一篇
Python爬虫入门教程 52-100 Python3爬虫获取博客园文章定时发送到邮箱
写在前面 关于获取文章自动发送到邮箱,这类需求其实可以写好几个网站,弄完博客园,弄CSDN,弄掘金,弄其他的,网站多的是呢~哈哈 先从博客园开始,基本需求,获取python板块下面的新文章,间隔60分钟发送一次,时间太短估摸着没有多少新博客产出~ 抓取的页面就是这个 https://www.cnblogs.com/cate/python 需求整理 获取指定页面的所有文章,记录文章相关信息,并且记录最后一篇文章的时间 将文章发送到指定邮箱,更新最后一篇文章的时间 实际编码环节 查看一下需要导入的模块 模块清单 import requests import time import re import smtplib from email.mime.text import MIMEText from email.utils import formatadd
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 面试大杂烩
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长