java虚拟机在运行java程序的内存分配机制
最近在看jvm特性与实践书籍,所以觉得有必要做个学习笔记,可是笔者一个一个字敲出来的哦大家认真看会有收获的;
java虚拟机在运行java程序的过程中会把它管理的内存划分为若干个不同的数据区域。这些区域都有自己的用途,以及创建和销毁的时间,有的区域随着虚拟机的启动而存在,有的区域则随着用户线程的启动和结束而创建和销毁,虚拟机所管理的数据区域分为如下图几个数据区域;
图上的区域跟所占内存占大小是不成比率的,下面来介绍这些数据区域;
1程序计算器
程序计算器(Program Counter Register) 是一块很小的内存空间,它可以看做是当前线程所执行的字节码行号指标器,字节码计时器工作的时候就是通过改变这个计算器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要这个计算器来完成;
由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间来实现的,在任何一个确定的时刻,一个处理器都只会处理一条线程中的指令,为了线程切换之后能恢复到正确的位置,每条线程都需要一个独立的程序计算器,各线程的程序计算器是相互独立的,互不影响,这类线程的内存区域成为线程的“线程私有内存”区域;
2虚拟机栈
虚拟机栈(Java Virtual Machine Stacks),与程序计算器一样,java虚拟机栈也是线程私有的,它的生命周期与线程一样,虚拟机栈描述的是java方法执行的内存模型,每个方法执行的时候都会创建一个栈帧,用于储存局部变量表,操作数栈,动态链接,方法出口等信息,每个方法从调用到执行结束,在虚拟机中对对应着一个栈帧,从入栈到出栈的过程;
看过一些对内存分配机制的解说,很多人都将内存分堆区和栈区,这种分法是比较粗糙,java内存的分配比这这复杂得多;
局部变量表:用于储存编译期可知的所有基本数据类型和对象引用类型,注意这里说的只是引用不是对象本身,其中64位长度的long和double类型占用两个局部变量空间,其余的都只占用一个局部变量空间,局部变量表所需要的内存空间在编译期的时候就分配完成,当进入一个方法的时候,这个方法需要在帧中分配多大的局部变量空间是完全可以确定的,方法运行期间不会改变局部变量表的大小;
3本地方法栈
本地方法栈(Native Method Stack), 与虚拟机栈发挥的作用其实是非常相似的,他们的区别不过是虚拟机栈是为虚拟机执行java方法(也就是字节码)服务的,而本地方法栈则是为虚拟机使用的Native方法服务的,注意有的虚拟机是将虚拟机栈和本地方法栈合二为一使用的;
4java堆
对于大多数的应用来说,java堆算是虚拟机管理的最大的一块内存区域了,java堆是被所有线程共享的一块内存区域,在虚拟机启动的时候创建,此内存唯一的目的就是存放所有实例对象,几乎所有实例对象都在这里分配内存的,为什么说是几乎而不是全部呢?因为随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配和标量优化技术会导致一些微妙的变化,所有对象都在堆上分配已将不是那么绝对了;
java堆是垃圾处理器主要管理的区域,所以很多时候也叫GC堆(Garbage Collected Heap),可别翻译成垃圾堆哦 哈哈,从内存回收的角度来看,由于现在收集器基本都是基于分代收集算法,所以java对还可以分为新生代和老生代,再细一点又可以分 Eden空间,from,survivor,to等
根据虚拟机规范规定,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的就可以,就像我们的磁盘空间一样;
5方法区
方法区和java堆一样,是各个线程共享的内存区,它用于已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,虽然java虚拟机规范将方法区划分为堆的一个逻辑部分,但它有一个别名即非堆,目的应该是将它和java堆区分开来;
对于习惯在HotSpot虚拟机上开发,部署的开发者来说,很多人愿意把方法区称为“永久代”,
HotSpot虚拟机 https://www.cnblogs.com/charlesblc/p/5993804.html
java虚拟机规范对方法区的限制非常松懈,除了和java堆一样不需要连续的内存和可以选择固定大小的或者可扩展外,可以选择不实现垃圾收集;
6运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息就是常量池(Constant Pool Table),用于存放编译器生成的字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中储存;
java虚拟机对Class文件的每一部分(包括常量池)的格式都有严格规定,每一个字节用来储存哪一种数据都要严格按照规范要求才会被虚拟机认可,装载和执行,但对于运行时常量池java虚拟机没有做任何细节上的要求,不同的提供商实现的虚拟机可以根据自己的需要去实现这个内存区域 ,
既然运行时常量池属于方法区的一部分自然受方法区内存的限制,当常量池无法申请到内存的时候就会报OutOfMemoryError异常;
好了就介绍到这里了,希望大家看完之后能有所收获;
- go语言读取csv文件并输出的方法
- HDUOJ----3342Legal or Not
- go语言基本类型
- HDUOJ----2647Reward
- hduoj------确定比赛名次
- HDUOJ----1165Eddy's research II
- HDUOJ-----1556Color the ball
- HDUOJ-----2175取(m堆)石子游戏
- Golang语言社区-Go语言递归
- go语言mongdb管道使用(一)
- HDUOJ---------2255奔小康赚大钱
- HDUOJ------1711Number Sequence
- HDUOJ---1712 ACboy needs your help
- HDUOJ---1867 A + B for you again
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- spring-boot项目优雅的http客户端工具,真香!
- 人人都可以学会生存分析(学徒数据挖掘)
- 谈谈const跟Object.freeze()
- Java String类源码阅读笔记
- 别再用JSON配置文件了
- 什么,你一定要基于FPKM标准化表达矩阵做单细胞差异分析
- Tomcat 9最新版安装与使用手册,tomcat更改端口号,tomcat控制台乱码问题解决方法
- Python 技术篇-读取遍历指定路径的文件,区分文件和文件夹
- MySQL蜜罐获取攻击者微信ID
- PyQt5 技巧篇-增加一个类级变量,类级变量的设置方法,类级"常量"设置方法
- PyQt5 技巧篇-按钮隐藏并保留位置,设置按钮的可见度,设置按钮透明度
- PyQt5 技巧篇-复选框绑定行内容,全选、清空、展示选中的内容功能实现演示,设置复选框选中,检查复选框选中状态
- PyQt5 技巧篇-QWidget、Dialog界面固定大小设置
- 力扣:地下城游戏,手把手教你做困难题
- RN布局