jvm内存模型_四种视角看JVM内存模型

1.JVM运行视角

  • 程序计数器

  • Java虚拟机栈

  • 本地方法栈

  • Java堆

  • 方法区

a80b231b31562f6ec580241dad4e4fe5.png 

        1 .程序计数器

        程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的行号指示器。这个计数器记录的是正在执行的虚拟机字节码指令的地址。此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

        2.Java虚拟机栈

        与程序计数器一样,Java虚拟机栈也是线程私有的。Java虚拟机栈是描述Java方法运行过程的内存模型。Java虚拟机栈会为每个方法在执行的同时都会创建一个栈帧用于存储局部变量(存放基本数据类型变量,引用类型的变量,返回类型的变量),操作数栈,动态链接,方法出口信息。

        3.本地方法栈

        本地方法栈与虚拟机所发挥的作用是非常相似的(HotSpot虚拟机中,直接就把本地方法栈和虚拟机栈合二为一),它们的区别不过是虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。本地方法被执行的时候,在本地方法栈也会创建一个帧栈,用于存放该本地方法的局部变量表、操作数栈,动作链接,出口信息。方法执行完毕后相应的栈帧也会出栈并释放内存空间。

       4.Java堆

       堆是用来存放内存对象的,是Java虚拟机所管理的内存中最大的一块。所有的对象实例以及数组都要在堆上进行分配。

      5.方法区

       方法区育Java堆一样,是一个线程共享的内存区域。它用于存储已被虚拟机加载的类信息,常量,静态变量、即时编译器后的代码等数据。虽然Java虚拟机规范把方法区描述为难的一个逻辑部分,但是它却有个别名叫做Non-Heap(非堆),目的是为了和Java堆区分开来。

      6.直接内存

      直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存也被频繁的使用。在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道和缓冲的IO方式。它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复复制数据。直接内存的大小不受Java虚拟机控制,但是当本机物理内存不足时就会抛出OutOfMemoryErrot错误。

860f20c69255d4caabefd1d2c0d850d9.png

图二 线程共享与独有的数据区

思考问题:为什么局部变量是线程安全的?答案见文末最后

2.JVM内存功能视角

从JVM内存可以分为三部分

  • Heap区(堆内存)

  • 非Heap(非堆内存)

  • 其他区

2ce0a532fb7e2fe23a80b40e2f9f7d2a.png

图三JVM内存功能分区

Heap区:Eden Space(伊甸园),Survivor Space(幸存者区),Tenured Gen(老年代-养老区)

非Heap区:Code Cache(代码缓冲区),Perm Gen(永久代),Java虚拟机栈,本地方法栈。

其他区:直接内存

3.线程运行视角

0c4b5a016ae0af3d3f7b75b15c1ca204.png

图片四线程,工作内存和主内存之间的关系

Java内存模型规定了所有的变量都要存储在主内存中,但是每个线程都有自己的工作内存,线程的工作内存保存了该线程使用的变量。这些变量实际上是主内存的副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不是直接读取主内存的变量。】

思考问题:volatile变量?答案见最后

4.垃圾回收视角

JVM的垃圾回收主要针对的是堆内存。在垃圾回收过程,堆内存有以下特点:

  • 堆内存划分为新生代和老年代两部分,新生代主要用于存放新创建的对象与存活时长小的对象,老年代则用来存放存活时间长的对象

  • 新生代又进一步划分为E,S1,S2三个区,其中,E代表Eden区;S1,S2则代表两个类似的Survior。minorGC时候,Eden区不能被会回收的对象被放入到空的survior,Eden则肯定会被清空。另一个surivor里不能被GC回收的对象也会被放入这个surivor,始终保证一个surivor是空的

  • 一个对象被minorGC回收了N次没有被回收掉,则会被移除到老年区里(该次数通过设置-XX:InitialTenuringThresHold)

  • 当老年代的空间被耗尽了,则触发FullGC

 问题解答:

1.为什么局部变量是线程安全的?

JVM在执行Java程序时,会根据其数据用途把内存划分为若干数据区域,包括方法区,堆,栈(JVM,本地方法栈),程序计数器,其中前两者是所有线程共有的,后两者是每个线程独有的,因此,栈是线程私有的,一个线程一个栈,并且栈由栈帧组成,栈帧保存一个方法的局部变量表(包括参数和局部变量),操作数栈,常量池指针等,每一次方法的调用实际上是创建一个帧栈,并且压栈。

所以方法调用实际是帧栈在入栈和出栈的操作,因为栈是线程私有的,所以每个栈之间是独立的,所以帧栈对于多个线程栈来说不存在共享问题,也就不会存在线程安全的问题了

2.Volatile变量

根据JVM规范的规定,volatile变量依然有工作内存的拷贝,但是由于它特殊的操作顺序规定,所有看起来如同直接在主内存中读写。

如果对申明了volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在工作所在内存的数据写回到主内存,但是,就算写回到主内存,如果其他线程工作内存的值还是旧的,再执行计算操作就会有问题,所以,在多处理器下为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,,每个处理器通过嗅探在总栈上传播的数据来检查自己缓存的值是不是过期了。当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从主内存中把数据读到处理器缓存中。

4d80fffbf43f2f6337df0f948e44ddc7.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538520.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat服务脚本

为什么80%的码农都做不了架构师?>>> #!/bin/bash ### BEGIN INIT INFO # Provides: tomcat # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # S…

oracle 取当前日期时间的前一天前一小时前一分钟前一秒

原文链接:http://wentao365.iteye.com/blog/779492 点击阅读原文 --------------------------------------------------------------------------- SELECT 当前时间 TITLE, TO_CHAR(SYSDATE, yyyy-mm-dd hh24:mi:ss) TIME FROM DUAL --当前时间 UNION ALL S…

mysql8事务级别_Mysql几种事务隔离级别

前言:之前对mysql的基础知识通过了几篇博客进行了一个详解,包括从数据库系统的原理以及最基本的操作使用,此篇博客将主要对mysql的事务级别进行实战分析1.什么是事务?事务是应用程序中一系列严密的操作,所有操作必须成…

控制台应用和空项目有什么区别_互联网小程序的应用以及APP的应用有什么区别及发展...

随时移动互联网进入的千家万户,互联网的手机应用程序也渐渐的在市场上流行起来了。今天主要跟大家谈一下互联网小程序的应用以及APP的应用有什么区别以及未来的发展趋。未来会流行什么手机应用或者APP应用,我带大家都为了解一下。下边先来了解一下小程序…

day19_java基础加强_动态代理+注解+类加载器

一、动态代理 1.1、代理模式 什么是代理模式及其作用? Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一。        代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。 …

使用循环链表实现一个通讯录的管理程序_【LeetCode链表题型总结】

点击上方蓝字,关注公众号链表概念的讲解链表是什么链表是一种线性数据结构,每个节点都存有数据,通过指针将各个节点链接在一起。链表的性质一致性: 每个节点有相同的数据结构,相同的数据大小,内存中占据相同的大小&…

python的kite下载安装及使用_Kite下载|Kite Python编程工具 V1.2020.1203.0 最新版下载 - 下载银行...

Kite是一款专为Python打造的一款代码补全软件,如果你正在学习Python或是从事与Python相关的编程工作,那么这款软件绝对是你的好帮手!其会智能判断用户想要输入的每个代码字段,并在所有库中进行匹配相应的内容,如果看到…

Linux 升级 Python 至 3.x

原文链接:http://blog.csdn.net/liang19890820/article/details/51079633 -------------------------------------------- 简述 CentOS 7 中默认安装了 Python,版本比较低(2.7.5),为了使用新版 3.x,需要对…

Sublime Text 3 配置python交互运行环境的快捷键

2019独角兽企业重金招聘Python工程师标准>>> 使用Sublime Text 3能以轻量级的环境写python脚本,运行python代码。为了更加方便地调用python脚本,通过在Sublime Text 3中绑定快捷键的方式,实现一键调用python交互运行环境&#xff…

xftp如何搜索文件_头条搜索站长平台如何添加网站和sitemap文件?附图文教程

头条搜索站长平台已经上线了,目前我们广大站长都可以登录该平台后添加新网站和提交 sitemap 地图文件,建议大家可以前往尝试一下,多一个搜索平台就多一条路,认为倒是挺好的。下面就跟大家简单介绍头条搜索站长平台如何添加网站和提…

彩铅练习,花船

图片发自简书App图片发自简书App

我的女朋友漏电了–论C++中的失败(failure),缺陷(bug)和异常(exception)

先做个广告置入,如果喜欢这篇文章,你可以到 zhaoyan.website/blog 去查看于此类似的C/C文章。 我承认有点标题党了,不过这真的是一篇写软件的文章,所以如果你已经抽出了一张面巾纸,那么趁早再把它完美的放回去。这篇软…

SQLplus 和mysql区别_mysql和oracle的区别有哪些

MySQL和Oracle都是流行的关系数据库管理系统(RDBMS),在世界各地广泛使用;大多数数据库以类似的方式工作,但MySQL和Oracle的这里和那里总是存在一些差异的。本篇文章就给大家比较Oracle和MySQL,介绍Oracle和MySQL之间的区别&#x…

127.0.0.1与localhost的区别

2019独角兽企业重金招聘Python工程师标准>>> 区别1: localhost也叫local ,正确的解释是:本地服务器 127.0.0.1在windows等系统的正确解释是:本机地址(本机服务器) 他们的解析通过本机的host文件,windows自动将localhost解析为127.…

mysql 索引_MySQL之索引

索引查找算法BTREEBTREE查找算法演变B-TREE :普通 BTREE,平衡多路查找树(B-Tree)BTREE :叶子节点双向指针BTREE(B*TREE):枝节点的双向指针普通B-TREE增强版BTREE(B*TREE)总结:从上图看出,在BTree上有两个头…

java数学计算表达式_Java初学者:内建函数计算简单的数学表达式

这个应该在之前写的,忘记了,补上这次我们说一下如何用java计算数学表达式的值,比如,我们要计算sin(pi/3) cos(pi/6) 5.6^3,怎么计算呢?这里我们需要用到java的math的内建函数,所谓内建函数&am…

谷歌新作gVisor:VM容器融合技术已经到来

作者|秦承刚,吴启翾,喻望,杨伟 编辑|张婵 出处丨高效开发运维 5 月 2 日,谷歌发布了一款新型的沙箱容器运行时 gVisor,号称能够为容器提供更安全的隔离,同时比 VM 更轻量。容器基于共…

安卓androidstudio访问本地接口_安卓开发之数据存储在本地的四种方式

​安卓开发之数据存储在本地的四种方式本地数据存储,在安卓开发过程中是不可避免的一个话题。这些本地的数据可能是用户的设置,程序的设置,用户的数据图片, 也可能是网络传输的一些缓冲数据。基本上我们有4种方法可以存储安卓程序的数据。第1…

java vector 线程安全_关于Vector到底是不是 线程安全的 问题

线程安全,在java的多并发编程中是重要概念,意思是,多个线程同时操作一个对象,在各种不同情况下,都不会造成不同的后果。一个经典问题,Vector到底是不是线程安全的?很多人都会回答,是…

C# Winform使用Windows Media Player播放多媒体整理

一、简单使用示例步骤 1.添加Windows Media Player 组件当前是系统的 Com组件 工具箱》右键“选择项”》选择Com组件 2.控件拖拽到桌面,使用 private void button1_Click(object sender, EventArgs e) {//播放开始声音axWindowsMediaPlayer2.URL "start.mp3&q…