JVM的内存划分管理

一、什么是JVM的内存

首先是java源代码被java编译器编译成.class字节码文件,然后由JVM的类加载器加载执行中需要的各个类的字节码文件,加载完成后交由JVM执行引擎执行。在整个执行过程中,jvm会使用一段内存空间来存储执行期间需要用到的数据和相关信息,这段空间被称作运行时数据区,也就是我们常说的内存,我们常说的内存管理 也就是对这块内存的分配和回收管理。

二、运行时数据区也就是内存又包括几部分呢?

堆、栈、方法区、本地方法栈、程序计数器

三、分别介绍

堆:堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,主要用来存放对象实例,所有的对象实例以及数组都要在堆上分配,同时堆也是垃圾回收的主要地方,如果分配失败则报错outofmemoryerror异常。java8把运行时常量池、静态变量也移到了堆中进行存储。那么什么是运行时常量池呢?比如我们在代码中定义的静态常量,编译期生成的各种字面量和符号引用(最常见的就是字符串常量),这类信息就会以运行时常量池的形式存在内存,1.7之前在方法区,1.7之后就在堆内存当中存储了,好处就是当我们在堆中再创建这样一个变量的时候可以直接指向,节省空间。

栈:也叫做虚拟机栈,它是线程私有的内存区域,生命周期与线程相同,它描述的是方法执行的内存模型,每个方法的执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至完成,都会在栈中对应着入栈、出栈的过程,方法执行完之后,该栈帧就会弹出栈帧的元素作为其返回值,并清除这个栈帧,java栈顶的栈帧就是当前正在执行的方法,方法的调用就是由栈帧的切换来完成的。局部变量表存放了基本数据类型、引用类型(比如堆内存中的引用地址、句柄等)。栈中规定了两种异常,一种是线程请求深度大于虚拟机允许的深度,抛出stackoverflowerror,最常见与递归操作,还有一种是如果虚拟机栈可动态扩展,但是在扩展时获取不到足够内存就会抛出outfomemoryerror

方法区:与堆一样也是各个线程共享的区域,用于存储即时编译后的类的元信息,在方法区中,存储了编译器编译后的代码类的版本、方法、接口信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及等。1.8之前方法区是由Hotspot的永久代实现的,而1.8之后就是使用元空间实现了,并且元空间不再使用jvm内存,而是使用系统内存。通过抛出的异常就可以看出一个是永久代一个是元空间。永久带属于堆,又叫Perm区,只存在于hotspot jvm中,并且只存在于jdk7和之前的版本中,jdk8中已经彻底移除了永久带,jdk8中引入了一个新的内存区域叫metaspace。(1)并不是所有的jvm中都有永久带,ibm的j9,oracle的JRocket都没有永久带。(2)永久带是实现层面的东西。(3)永久带里面存的东西基本上就是方法区规定的那些东西。方法区与永久代/元空间的区别:(1)方法区是规范层面的东西,规定了这一个区域要存放哪些东西(2)永久带或者是metaspace是对方法区的不同实现,是实现层面的东西。

本地方法栈:本地方法栈和虚拟机栈作用比较相似,区别在于虚拟机栈是为java的方法服务,而本地方法栈是为虚拟机使用到的native方法服务。

程序计数器:占用内存空间较小,它可以看做是当前程序执行的行号指示器。分支、跳转、循环、异常处理等都是这个行号计数器来完成的,它是线程私有的,并且此线程区域是唯一一个在JVM当中没有规定outofmemoryerror的区域。

 

参考博文:

https://www.cnblogs.com/dolphin0520/p/3613043.html

https://www.liangzl.com/get-article-detail-38199.html

https://www.cnblogs.com/paddix/p/5309550.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值