java面试-JVM内存区域划分

JVM内存划分

说到Java内存区域,刚开始接触java的人会下意识说出“堆栈”。这里要明确堆栈不是一个概念,而是两个概念,堆和栈是两块不同的内存区域,简单理解的话,堆是用来存放对象而栈是用来执行程序的。其次,堆内存和栈内存的这种划分方式比较粗糙,这种划分方式只能说明大多数程序员最关注的、与对象内存分配关系最密切的内存区域是这两块,Java内存区域的划分实际上远比这复杂。对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去配对delete/free代码,不容易出现内存泄露和内存溢出问题。但是,也正是因为Java把内存控制权交给了虚拟机,一旦出现内存泄露和内存溢出的问题,就难以排查,因此一个好的Java程序员应该去了解虚拟机的内存区域以及会引起内存泄露和内存溢出的场景。

 

之所以要划分这么多区域出来是因为这些区域都有自己的用途,以及创建和销毁的时间。有些区域随着虚拟机进程的启动而存在,有的区域则依赖用户线程的启动和结束而销毁和建立。图中绿色部分就是所有线程之间共享的内存区域,而其余部分则是线程运行时独有的数据区域,从这个分类角度来看一下这几个数据区。

 

线程独占区域

 

PROGRAM COUNTER REGISTER,程序计数器

程序计数器是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令

在JVM规范中规定,如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。

由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

总结:
当前线程所执行的字节码的行号指示器;
当前线程私有;
不会出现OutOfMemoryError情况。

JAVA STACK,虚拟机栈

Java栈也称作虚拟机栈(Java Vitual Machine Stack),也就是我们常常所说的栈,跟C语言的数据段中的栈类似。事实上,Java栈是Java方法执行的内存模型

每个线程每执行一个方法就会创建一个栈帧,并将其压栈,在方法执行完成后,将其出栈,栈的大小一般在256K~756K之间,取决于jvm的实现,当无法申请到足够的内存,或者是超过了jvm虚拟机允许的最大深度,就会出现栈溢出或者oom异常,接下来说明一下栈帧中各个变量的意义

  1. 局部变量表:用来存储方法中的局部变量,对于基本变量直接存放其值,对于引用类型的变量,则存放其引用
  2. 操作数栈:用于存放进行计算的值
  3. 指向运行时常量池引用:方法在运行时,可能会用到类中的常量,所以必须要有引用指向运行时常量
  4. 方法返回地址:在一个方法执行完成后,需要返回调用它的位置,这里记录了调用这个方法的位置

总结:
线程私有,生命周期与线程相同;
java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧,存储局部变量表(基本类型、对象引用)、操作数栈、动态链接、方法出口等信息;
StackOverflowError异常:当线程请求的栈深度大于虚拟机所允许的深度;
OutOfMemoryError异常:如果栈的扩展时无法申请到足够的内存。

NATIVE METHOD STACK,本地方法栈

本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。 

线程间共享区域

HEAP,堆

堆在虚拟机启动的时候创建,此内存的唯一的目的就是保存对象实例,为了对不同生命周期的对象进行管理,提升性能,现在的垃圾收集器都会采用分代的垃圾收集算法,所以堆也可以分为年轻代和老年代,再细分可以划分为Eden区、From Survivior区、To Survivor区

总结:

可以通过-Xmx和-Xms控制堆的大小;

OutOfMemoryError异常:当需要分配对象实例,但剩余的堆内存无法完成分配,并且无法在进行扩展的时候

METHOD AREA,方法区

块区域用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,虚拟机规范是把这块区域描述为堆的一个逻辑部分的,但实际它应该是要和堆区分开的。从上面提到的分代收集算法的角度看,HotSpot中,方法区≈永久代。不过JDK 7之后,我们使用的HotSpot应该就没有永久代这个概念了,会采用Native Memory来实现方法区的规划了。

总结:
线程间共享;
用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
OutOfMemoryError异常:当方法区无法满足内存的分配需求时。

RUNTIME CONSTANT POOL,运行时常量池

 上面的图中没有画出来,因为它是方法区的一部分。Class文件中除了有类的版本信息、字段、方法、接口等描述信息外,还有一项信息就是常量池,用于存放编译期间生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中,另外翻译出来的直接引用也会存储在这个区域中。这个区域另外一个特点就是动态性,Java并不要求常量就一定要在编译期间才能产生,运行期间也可以在这个区域放入新的内容,String.intern()方法就是这个特性的应用。

总结:
方法区的一部分;
用于存放编译期生成的各种字面量与符号引用;
OutOfMemoryError异常:当常量池无法再申请到内存时。

热门文章

暂无图片
编程学习 ·

vue打包后修改服务器地址

1.在public文件下新建config.js文件2.修改config.js文件 var PLATFROM_CONFIG = {}; // 本地环境 PLATFROM_CONFIG.baseUrl = "服务器地址" // 正式环境 // PLATFROM_CONFIG.baseUrl = "服务器地址"3.在封装好的axios里面去修改,我的是4.在index.html中引…
暂无图片
编程学习 ·

JS基础知识总结(十三):ES6 对象的扩展

“ 关注 前端开发社区 ,回复"1"即可加入 前端技术交流群,回复 "2"即可免费领取 500G前端干货!上一节主要是总结了ES6中和数组有关的内容。本节主要总结ES6中对象的扩展,具体内容包括以下几个方面: 会介绍以下内容: [外链图片转存失败,源站可能有防盗…
暂无图片
编程学习 ·

火箭少女101毕业,rocketgirls.fans粉丝站上线震撼饭圈

2年前的2018年6月23日晚:经过一百零四天的艰苦训练和比赛,由457家公司、13778名练习生中层层挑选出的11名女孩站上成团出道位,组成为期2年的限定女团,火箭少女101成团出道。两年后的2020年6月23日晚:火箭少女101的2年限定组合期限已到,晚上8点 “遇见再见”火箭少女101告…
暂无图片
编程学习 ·

mac mysql更改了目录所遇到的坑

之前安装的目录为/usr/local/develope/mysql后来改了下目录 同时也改了MySQL文件夹名现在为/usr/local/develope/develop/mysql5.6 同时data目录还是在的配置文件已经修改 MySQL在安装或者启动的时候没有指定配置文件时候 默认找的配置文件/etc/my.cnf将basedir目录和data目录修…
暂无图片
编程学习 ·

MySql简单入门_第四篇(2)_存储

5、存储过程:为以后的使用而保存的一条或多条MySql语句的集合存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(…
暂无图片
编程学习 ·

maven 有时候parent项目版本没更新的版本问题

对于parent工程,一般规定了版本,并且包含了子模块。如果首次编译整个项目,可能导致编译不成功,因为子模块需要父工程版本号。父工程想连同子模块一起编译,所以首次编译的时候,注释掉parent工程的子模块。先编译版本,成功后放开子模块。就可以了。如果parent的版本发生变…
暂无图片
编程学习 ·

模板字符串

模板字符串是在 JS 中创建字符串的一种新方法。我们可以通过使用反引号使模板字符串化。//ES5 Versionvar greet = Hi I\m Mark;//ES6 Versionlet greet = `Hi Im Mark`;在 ES5 中我们需要使用一些转义字符来达到多行的效果,在模板字符串不需要这么麻烦//ES5 Versionvar lastW…
暂无图片
编程学习 ·

Java继承多态面试题

1.多态的实现原理2.面向对象的特征之一——多态2.1多态的定义多态是同一个行为具有不同的表现形式或形态的能力。允许不同类的对象对同一消息做出响应,同一消息可以根据发送的对象不同采用不同的行为方式。对于面向对象,多态分为编译时多态和运行时多态,编译时多态是静态的,…
暂无图片
编程学习 ·

Linux系统编程4:IPC消息队列

Linux系统编程4:IPC消息队列0. 消息队列1. POSIX 消息队列1.1 查看1.2 接口1.3 结构体1.4 函数1.4.1 创建消息队列1.4.2 删除消息队列1.4.3 打开消息队列1.4.4 关闭消息队列1.4.5 发送消息1.4.6 接收消息1.4.7 设置消息队列属性1.4.8 获取消息队列属性 0. 消息队列背景 管道和…
暂无图片
编程学习 ·

【游记】2020联合省选

说在前面 今年的省选是在本校考的,非常幸运。但俗话说得好,祸福相依。 day  0\tt day\;0day0 最后一个突击冲刺的夜晚,天上一颗星星也没有。机房里是几个年轻人,其中的一位正在复习 NTT\tt NTTNTT ,他还没有意识到将要到来的考试是个灭顶之灾。 我们的教练显然并不相信临…
暂无图片
编程学习 ·

Hadoop(七)——中下下

shuffle MapReduce的shuffle分为map阶段的shuffle和reduce阶段的shuffle,下面就分别来做介绍。 map阶段的shuffle: 之前我们学的是map阶段并不是直接把数据给reduce,而是会把数据分好,该分区的分区,该封装的封装,该合并的合并再给到reduce,下面就来详细介绍这个过程。1.…
暂无图片
编程学习 ·

【漏洞通告】Treck TCP/IP协议库“ Ripple20”漏洞通告

【漏洞通告】Treck TCP/IP协议库“ Ripple20”漏洞通告 威胁对抗能力部 [绿盟科技安全情报](javascript:void(0)😉 昨天 通告编号:NS-2020-0039 2020-06-30TA****G: Treck、TCP/IP协议库、Ripple20漏洞危害: 攻击者利用此类漏洞,可造成拒绝服务、远程代码执行等。版本: 1…
暂无图片
编程学习 ·

你想要的Python面试题都在这里了!

第三部分 数据库和缓存(46题) 1. 列举常见的关系型数据库和非关系型都有那些? 关系型数据库: Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL 非关系型数据库: NoSql、Cloudant、MongoDb、Redis、HBase 2. MySQL常见数据库引擎及比较? 在实际工作中,选择一…
暂无图片
编程学习 ·

企业实战--kubernetes(八)---存储(ConfigMap)

一、Configmap简介 Configmap用于保存配置数据,以键值对的形式存储 Configmap资源提供了向Pod诸如配置数据的方法 旨在让镜像和配置文件解偶,以便实现镜像的可移植性和可复用性 典型的使用场景: 填充环境变量的值 设置容器内的命令行参数 填充卷的配置文件创建Configmap的方…
暂无图片
编程学习 ·

返回什么才好c++编程题第三周

此题主要考察this指针,以及引用作左值 #include using namespace std; class A{ public: int val; // 在此处补充你的代码 (需要我自己注意的是对象已经被分配了空间了,构造函数和析构函数只是起到一个修饰或者清洁的作用) A(int x = 123 ) { val = x; …