博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JVM 系列》- Java内存模型
阅读量:6428 次
发布时间:2019-06-23

本文共 1980 字,大约阅读时间需要 6 分钟。

hot3.png

一、内存划分

虚拟机规范中,将内存划分为六大部分,分别是方法区、JAVA堆、JAVA虚拟机栈、PC寄存器、本地方法栈以及运行时常量池。

其中运行时常量池是由方法区分配出来的一块区域。

 二、JAVA虚拟机规范与JAVA虚拟机

JAVA虚拟机规范是一种对JAVA虚拟机实现的规范要求,由oracle制定,而我们平时常说的JAVA虚拟机一般是指的一种具体的JAVA虚拟机规范的实现。

我们最经常使用的JAVA虚拟机是hotspot

三、结构图

程序要运行,在内存中就要有数据空间。在JVM中这块数据空间被称为运行时数据区。

150812_cqIT_2330610.png

另一张图

144730_vDM7_2330610.png

四、内存区域详解

方法区(全局共享)

方法区保存了运行时常量池、字段信息、方法信息、构造方法与普通函数的字节码内容以及一些特殊方法。

方法区主要重要的有三块:1.类的常量池;2.指向当前类Class类对象的引用;3.指向当前类ClassLoader类对象的引用

方法区与Java堆除了存储的信息不一样之外,这一部分Java虚拟机规范不强制要求实现自动内存管理系统(GC)。

Java堆(全局共享)

Java堆随着JAVA虚拟机的启动创建,储存着所有对象实例以及数组对象,而且内置了“自动内存管理系统”,也就是我们常说的垃圾搜集器(GC)。

对于JAVA虚拟机如何实现垃圾搜集器,JAVA虚拟机规范没有明确的规定,也正因如此,我们平时使用的JAVA虚拟机中提供了许多种垃圾搜集器,它们采用不同的算法以及实现方式,满足多方面的性能需求。

JAVA虚拟机栈(线程独有)

JAVA虚拟机栈是在创建线程的同时创建的,用于存储栈帧,JAVA虚拟机栈也是线程独有的。它的基本单位是栈帧。

栈帧

栈帧保存了局部变量表、操作数栈、程序计数器,以及对当前类的运行时常量池的引用。

栈帧是随着方法的调用而创建,随着方法的结束而销毁,如果方法抛出异常,也算方法结束。

它又肩负着处理方法返回值、动态链接以及异常分派的任务

局部变量表

是在编译时期就写入了class文件当中。

可以将它理解为一个对象数组,而里面按照索引0到length-1分别对应于每一个局部变量。

如果是实例方法的局部变量表,第0个局部变量会是一个指向当前实例的引用,也就是this关键字,其余的局部变量则从索引1开始。

操作数栈

它是一个后进先出(LIFO)栈,而它的长度也是在编译时期就写入了class文件当中,是固定的。它的作用就是提供字节码指令操作变量计算的空间,比如简单的,对于int a=9这句话来说,就需要先将9压入操作数栈,再将9赋给a这个变量。

PC寄存器(线程独有)

程序计数器(Program Counter Register),它记载着每一个线程当前运行的JAVA方法的地址,如果是当前执行的是本地方法,则程序计数器会是一个空地址(undefined)。

PC在每次指令执行后自增,维护下一个将要执行指令的地址。

在JVM模型中, 字节码解释器就是通过改变PC值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖PC完成。

本地方法栈(线程独有)

本地方法栈是一个传统的栈,它用来支持native方法的执行。

如果JAVA虚拟机是使用的其它语言实现指令集解释器的时候,也会用到本地方法栈。

如果前面这两种都未发生,也就是说如果JAVA虚拟机不依赖于本地方法栈,而且JAVA虚拟机也不支持native方法,则不需要本地方法栈。而如果需要的话,则本地方法栈也是随每一个线程的启动而创建的。

五、内存管理

内存管理分为内存分配和内存释放。大致分为两部分,一部分是全局共享,一部分是线程独有。

线程独有

对于线程独有的这部分内存,都是随着线程的启动而创建,而当线程被销毁时,内存也就随之释放。

这一部分内存,不需要垃圾搜集器的管理,而是JAVA虚拟机来主动管理,每当一个线程被创建的时候,JAVA虚拟机就会为其分配相应的PC寄存器和JAVA虚拟机栈,如果需要的话,还会有本地方法栈。相应的,当一个线程被销毁的时候,JAVA虚拟机也会将这个线程所占有的内存全部释放。

全局共享

全局共享的这部分内存(以下简称堆),内存分配主要是由程序员显示的使用new关键字来触发的,至于new出来的这部分内存在哪分配,如何分配,则是JAVA虚拟机来决定。而这部分内存的释放,则是由自动内存管理系统(以下简称GC)来管理的。

通常情况下,堆内存分配是要依赖于GC的策略与实现的,在分配的时候,就要考虑好到时候如何回收这部分内存。也是正因为如此,对于内存分配这一部分的讲解来说,我们必须得先了解内存是如何被回收的,才能更好的理解内存要怎么被分配。

 

参考资料

 

 

 

 

转载于:https://my.oschina.net/kimisme/blog/1593265

你可能感兴趣的文章
在SpeedDialPlus中使用EarthViewfromGoogleEarth图片作背景
查看>>
负载均衡的基础架构与使用场景
查看>>
Node内存限制和垃圾回收
查看>>
系列:iOS开发-从扩展UIButton到自定义控件
查看>>
1 Java NIO概述-翻译
查看>>
前端加解密
查看>>
【vue插件篇】vue-options-events 事件总线触发
查看>>
如何架构自己的Android项目
查看>>
Java基础之死锁与线程通信
查看>>
给 console 添加颜色
查看>>
安卓移动端video标签将页面元素覆盖。
查看>>
报表性能优化
查看>>
区块链是什么?能干什么?
查看>>
用一张图总结web缓存策略
查看>>
关于Two pointers的个人理解
查看>>
大话转岗 PHP 开发小结
查看>>
PAT A1017 优先队列
查看>>
2019年Java面试-并发容器篇
查看>>
微信小程序 WePy Utils 工具集整合并封装了常用的小程序 API 和 HTTP Request
查看>>
leetcode378. Kth Smallest Element in a Sorted Matrix
查看>>