JVM内存模型结构浅析

前言

Java的平台无关性
Java之所以能一次开发,多处部署,实现平台无关性,就是因为JVM底层实现了与操作系统交互的相关操作,从而让Java开发者不再关心会放在上面系统上运行。

Java的内存自动管理
Java相比较C++, 之所以不需要手动释放内存,就是因为JVM实现了内存自动回收机制。从而让Java开发者不需要关心内存问题,专注的开发具体业务。

《本章基于Java 1.8版本 Hotspot虚拟机》

构成

基本上所有的共识都是由以下几部分组成:
1. 程序计数器
2. 虚拟机栈
3. 本地方法栈
4. 堆
5. 方法区

但是个人认为这样划分有点笼统,应该从JVM共享模型的角度来说起。
Java虚拟机是模仿操作系统来构建的。
首先,堆区是JVM中最大的区域,模拟的操作系统中的内存。可供所有线程共享。所以JVM共享模型可以理解为:
线程私有区和线程共享区

在这里插入图片描述

一、线程共享区

数据存储区域是JVM中占用最大的区域。在Java 1.8版本中,它包含堆和方法区两部分。

方法区

在JVM虚拟机规范中,常用的HotSpot在1.8版本中将方法区的定义通过本地内存来实现了,取名——元空间。
所以在这个版本中,元空间就是对方法区定义的实现。

方法区的用途:
主要用于存放类的元信息、常量池、方法信息等。

堆中主要有新生代和老年代。

其中,新生代中有三个部分,Eden区、S0区、S1区。
S0的区域大小等于S1的区域大小。
在这里插入图片描述

堆的作用:
主要存放所有的实例对象及数组。

二、线程私有区

数据操作区域主要指线程中。其分类大概包含程序计数器、本地方法栈、虚拟机栈三部分。
在这里插入图片描述

程序计数器

为什么要设计程序计数器呢?
计算机发展到今天,cpu已经是采用分时复用技术,当有多个线程同时在一个cpu上执行时,线程之间的调度是来回切换的。在JVM的线程中,为了让cpu每次执行到当前线程时都知道应该继续执行的代码位置,设计了程序计数器。
通俗的讲,就是个记录器,存储了下一个要执行的地址,以供cpu读取。有点像文件的断点续传。

程序计数器是JVM规范中唯一不可能出现OOM的区域,因为大小是恒定的。

本地方法栈

本地方法就是native关键字修饰的方法。Java是在C语言之上演变出来的,native方法就是C语言的。调用native方法时,也需要一个栈,同虚拟机栈基本一致。

虚拟机栈

虚拟机栈就是JVM栈,也是一个线程调用链中最重要的部分。
在Java中有个Thread类,Thread类就是Java语言对线程概念的具象表现。当开启一个线程时,需要调用Thread类中的start()方法,start()方法中调用了start0()方法,start0()是一个native方法,它将会告诉操作系统启用一个线程并初始化相关的空间和数据。线程就是从start()方法开始被创建的。

start()方法开启一个线程后将会执行run()方法,在java中,可以把run()方法看成是程序执行的入口。
在run()中一层又一层的方法调用形成了虚拟机栈。
每调用一个方法,就会创建一个栈帧,然后压入虚拟机栈中。
在这里插入图片描述
虚拟机栈就是一个栈的数据结构,里面的元素就是栈帧。而栈帧在java中并不是无迹可寻。
StackTraceElement类就是对栈帧的一个简单具象表现。
在Thread类中,或者Exception类中都可以打印出栈帧的轨迹。
在这里插入图片描述
在这里插入图片描述

是不是再熟悉不过了…下面着重讲讲栈帧。

栈帧

那么栈帧是什么? 栈帧是方法的另一种表现形式,从java的角度来理解,栈帧也可以是个对象,毕竟万物皆对象。

如果它是一个对象,那么成员变量有哪些?

  1. 局部变量表
  2. 操作数栈
  3. 动态链接
  4. 方法返回地址
  5. 附加信息

又懵逼了,越来越多的东西出来了。

1、局部变量表
什么是局部变量?在方法中定义的基本数据类型(int、double、char等)和对象的引用都属于局部变量。
而这些局部变量需要存放起来,形成了局部变量表。局部变量是在编译期间就确定大小的。

结构:
局部变量表的数据结构是一个数组,基本储存单位是变量槽Slot. 32位以内的类型占1个槽,64位的类型占两个槽,如long和double。引用类型占1个槽。如果一个变量占用了两个slot,那么访问时只需要定位到前面的slot就可以了。
在这里插入图片描述

变量槽的复用:
如果一个方法中有for循环,循环中有很多局部变量,并且循环次数是外部传入进来,那么编译期应该怎么确定局部变量表的大小呢?
这里就是槽位的复用。在for循环中的变量定义作用域范围仅在for循环中,如果要进行下次循环,只需要复用原来的几个变量槽位就可以了,从而节省空间。

2、操作数栈

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值