Java内存模型与JVM运行时数据区的区别详解
首先,这两者是完全不同的概念,绝对不能混为一谈。
1.什么是Java内存模型?
Java内存模型是Java语言在多线程并发情况下对于共享变量读写(实际是共享变量对应的内存操作)的规范,主要是为了解决多线程可见性、原子性的问题,解决共享变量的多线程操作冲突问题。
多线程编程的普遍问题是:
- 所见非所得
- 无法肉眼检测程序的准确性
- 不同的运行平台表现不同
- 错误很难复现
故JVM规范规定了Java虚拟机对多线程内存操作的一些规则,主要集中体现在volatile和synchronized这两个关键字。
- volatile 是JVM提供的对共享变量在多线程读写时的可见性保证,主要作用是对volatile修饰的共享变量禁止被缓存(这里跟CPU的高速缓存和缓存一致性协议有关),不做重排序(重排序:在CPU处理速度远大于内存读写速度的现状下为了提高性能而进行的优化),但是并不保证共享变量操作的原子性。
- synchronized 是JVM提供的锁机制,通过锁的特性和内存屏障保证锁住区域操作的原子性、可见性、有序性。
- 锁争抢的是对象(static锁的是类对象,非static锁的是当前对象,即this,锁方法块锁的是自定义对象)在堆内存中对象头的一块内存的“主权”,只有一个线程能获取该“主权”,即排他性,通过锁的排他性保证对锁住区域的操作的原子性
- 通过在代码前后加入加载屏障(Load Barrier)和存储屏障(Store Barrier),能保证锁住代码块或者方法中对共享变量的操作的可见性
- 通过在代码前后加入获取屏障(Acquire Barrier)和释放屏障(Release Barrier),能保证锁住代码块或者方法中对共享变量的操作的有序性
2.什么是JVM运行时数据区?
JVM运行时数据区,是Java虚拟机在运行时对该Java进程占用的内存进行的一种逻辑上的划分,包括方法区、堆内存、虚拟机栈、本地方法栈、程序计数器。这些区块实际都是Java进程在Java虚拟机的运作下通过不同数据结构来对申请到的内存进行不同使用。
- 方法区:JVM用来存储加载的类信息、常量、静态变量、编译后的代码等数据。不同虚拟机有不同的实现,oracle的HotSpot在Java7中方法区放在永久代,Java8中方法区放在元空间,并通过GC机制来管理。
- 虚拟机栈:每个线程私有的空间,由多个栈帧组成,一个方法对应一个栈帧,栈帧包括局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。栈内存默认最大1M,超出跑出StackOverFlowError。
- 本地方法栈:类似虚拟机栈,是为虚拟机使用native本地方法而准备的。具体实现由虚拟机厂商来实现。HotSpot虚拟机中实现与虚拟机栈一致,同时超出大小抛StackOverFlowError。
- 程序计数器:记录当前线程执行字节码的位置,存储的是字节码指令地址,如果native方法,则为空。CPU同一时间只能执行一条线程中的指令,线程切换后通过程序计数器来恢复正确的执行位置。
- 堆内存:所有线程都可以访问修改,存放的是对象实例,是数据区中占用空间最大的部分,在HotSpot虚拟机中分为新生代和老年代,新生代又分为Eden区和Survivor0区、Survivor1区。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
相关推荐
-
浅析Java内存模型与垃圾回收
1.Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示: 程序计数器:一块较小内存区域,指向当前所执行的字节码.如果线程正在执行一个Java方法,这个计数器记录正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计算器值为空. Java虚拟机栈:线程私有的,其生命周期和线程一致,每个方法执行时都会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 本地方法栈:与虚拟机栈功能类似,只不过虚拟机栈为虚拟机执行J
-
Java内存模型JMM详解
Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性.是否可以重排序等问题的无关具体平台的统一的保证.(可能在术语上与Java运行时内存分布有歧义,后者指堆.方法区.线程栈等内存区域). 并发编程有多种风格,除了CSP(通信顺序进程).Actor等模型外,大家最熟悉的应该是基于线程和锁的共享内存模型了.在多线程编程中,需要注意三类并发问题: ·原子性 ·可见性 ·重排序 原子性涉及到,一个线程执行一个复合操作的时候,其他线程是否能够看
-
Java虚拟机JVM优化实战的过程全记录
前言 Java虚拟机是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最具吸引力的特性之一.Java虚拟机是通过在实际的计算机上仿真模拟各种计算机功能模拟来实现的,通过Java虚拟机,您只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行. 最近在看JVM群里有人发了一个GC情况,让人帮忙看优化的,于是我也凑热闹发了出来想让群里的大神们指导优化一下,以下是优化过程记录. 一开始我贴了下面的两张图 jstat看GC记录
-
Java 高并发三:Java内存模型和线程安全详解
网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存.数据在主存中会有一份,在工作内存中也有一份.工作内存和主存之间会有各种原子操作去进行同步. 下图来源于这篇Blog 但是由于Java版本的不断演变,内存模型也进行了改变.本文只讲述Java内存模型的一些特性,无论是新的内存模型还是旧的内存模型,在明白了这些特性以后,看起来也会更加清晰. 1. 原子性 原子性是指一个操作是不可中断的.即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰
-
在Java内存模型中测试并发程序代码
让我们来看看这段代码: import java.util.BitSet; import java.util.concurrent.CountDownLatch; public class AnExample { public static void main(String[] args) throws Exception { BitSet bs = new BitSet(); CountDownLatch latch = new CountDownLatch(1); Thread t1 = ne
-
学习Java内存模型JMM心得
有时候编译器.处理器的优化会导致runtime与我们设想的不一样,为此Java对编译器和处理器做了一些限制,JAVA内存模型(JMM)将这些抽象出来,这样编写代码时就无需考虑那么多底层细节,并保证"只要遵循JMM的规则编写程序,其运行结果一定是正确的". JMM的抽象结构 在Java中,所有的实例.静态变量存储在堆内存中,堆内存是可以在线程间共享的,这部分也称为共享变量.而局部变量.方法定义参数.异常处理参数是在栈中的,栈内存不在线程间共享. 而由于编译器.处理器的优化,会导致共享变量
-
java中JVM中如何存取数据和相关信息详解
前言: 我们每天都在编写Java代码,编译,执行.很多人已经知道Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行. 那在整个程序执行过程中,JVM中怎么存取数据和相关信息呢? 事实上在JVM中是用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存. 一.运行时数据区域包括
-
Java内存模型与JVM运行时数据区的区别详解
首先,这两者是完全不同的概念,绝对不能混为一谈. 1.什么是Java内存模型? Java内存模型是Java语言在多线程并发情况下对于共享变量读写(实际是共享变量对应的内存操作)的规范,主要是为了解决多线程可见性.原子性的问题,解决共享变量的多线程操作冲突问题. 多线程编程的普遍问题是: 所见非所得 无法肉眼检测程序的准确性 不同的运行平台表现不同 错误很难复现 故JVM规范规定了Java虚拟机对多线程内存操作的一些规则,主要集中体现在volatile和synchronized这两个关键字. vo
-
JVM运行时数据区划分原理详解
Java内存空间 内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行.JVM内存布局规定了JAVA在运行过程中内存申请.分配.管理的策略,保证了JVM的高效稳定运行.不同的jvm对于内存的划分方式和管理机制存在着部分差异(对于Hotspot主要指方法区) (图源阿里)JDK8的元数据区+JIT编译产物 就是JDK8以前的方法区 JavaAPI中的Runtime public class Runtime extends Object Every Java
-
JVM 运行时数据区与JMM 内存模型
目录 1. JVM 运行时数据区 2. JMM 内存模型 硬件内存模型 JMM 3. 可见行与 volatile 关键字 1. JVM 运行时数据区 JVM运行时数据区可以分为元空间,堆,虚拟机栈,本地方法栈,程序计数器五大块. 元空间(方法区):存放类模版对象,是线程共享的区域,在磁盘上,一般不会GC 堆空间:线程共享的区域,对象创建与GC的主要阵地 虚拟机栈:线程私有的,基本组成单位是栈帧,每个栈帧对应一个方法,栈帧组成如下 局部变量表:存放方法变量信息 操作数栈:方法运行的区域 动态链接:
-
Java JVM运行时数据区(Run-Time Data Areas)
1.官网概括 引用官网说法: The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits.
-
JAVA JVM运行时数据区详解
目录 一.前言 二.运行时数据区整体概架构 三.程序计数器 四.虚拟机栈 1.栈的特点 2.栈帧的内部结构 3.局部变量表 4.操作数栈 5.动态链接 6.方法返回地址 五.本地方法栈 六.堆 1.设置堆大小的参数 2.对象分配过程 3.堆中的GC 4.内存分配策略 5.什么是TLAB 6.堆是分配对象存储的唯一选择吗? 七.方法区 1.方法区概述 2.设置方法区内存大小 3.如何解决OOM问题? 4.方法区存储什么 5.方法区的演进细节 6.方法区的GC 总结 一.前言 这是JVM系列文章的第
-
面试时必问的JVM运行时数据区详解
目录 前言 正文 1.运行时数据区(Run-Time Data Areas) 1)程序计数器(Program Counter Register) 2)Java虚拟机栈(Java Virtual Machine Stacks) 3)本地方法栈(Native Method Stacks) 4)堆(Heap) 5)方法区(Method Area) 6)运行时常量池(Run-Time Constant Pool) 2.Java 中有哪几种常量池? 3.class 文件常量池 4.运行时常量池 5.字符串
-
java运行时数据区域和类结构详解
Java运行时数据区域 java运行时数据区可以分为:方法区.虚拟机栈.本地方法栈.堆和程序计数器 线程私有:虚拟机栈.本地方法栈.程序计数器 线程共享:方法区.堆 程序计数器 一块较小的内存空间,当前线程所执行字节码的行号指示器,它是程序控制流的指示器,分支.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成. 每条线程都拥有一个独立的程序计数器. Java虚拟机栈 线程私有的,它的生命周期与线程相同. 每个方法被执行时,java虚拟机都会创建一个栈帧,用于存储 局部变量表.操
-
JVM运行时数据区原理解析
前言 Java虚拟机定义了若干种程序运行期间会使用的运行时数据区域,其中一些会随着虚拟机启动而创建,随着虚拟机的退出而销毁.另外一些则是和线程一一对应,这些与线程对应的数据区域随着线程开始而创建,线程的结束而销毁. PC寄存器 PC寄存器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器,每条线程都要一个独立的PC寄存器,这个内存也是线程私有的内存.正在执行 java 方法的话,PC寄存器是记录的是虚拟机字节码指令的地址(当前指令的地址).如果还是 Native 方法,则为und
-
深入理解Java运行时数据区_动力节点Java学院整理
JVM体系结构和运行时数据区概述 要理解JVM的运行时数据区, 必须先要理解JVM的体系结构, 因为虚拟机的体系结构基本上解释了"为什么会有这些运行时数据区" . JVM的体系结构如下: 由此可见, 运行时数据区的划分, 是和JVM的体系结构相关的. 本文主要介绍运行时数据区的划分, 对体系结构不做深入的讲解. 简单概括一下, 类加载器子系统用于将class文件加载到虚拟机的运行时数据区中(准确的说应该是方法区) . 可以认为执行引擎是字节码的执行机制, 一个线程可以看做是一个执行引擎
-
JVM内存模型/内存空间:运行时数据区
目录 JVM内存模型/内存空间 ① 程序计数器 (Program Counter Register) ② Java虚拟机栈 (VM Stack) ③ 本地方法栈 (Native Method Stack) ④ Java堆 (Java Heap) ⑤ 方法区(Method Area) ⑥ 运行时常量池 (Running Constant Pool) [特] 直接内存 总结 JVM内存模型/内存空间 Java虚拟机JVM运行起来,就会给内存划分空间,这块空间成为运行时数据区. 运行时数据区主要划分为
随机推荐
- centos6.7安装python2.7.11的具体方法
- Android PopupWindow被输入法弹上去之后无法恢复原位的解决办法
- JavaScript实现带有子菜单和控件的slider轮播图效果
- PowerShell入门教程之编写和使用脚本模块实例
- MySql避免重复插入记录的几种方法
- jQuery中select与datalist制作下拉菜单时的区别浅析
- 基于jQuery实现中英文切换导航条效果
- ajax的hide隐藏问题解决方法
- JavaScript 参考教程
- 在Spring Boot中使用Spring-data-jpa实现分页查询
- JSP页面pageEncoding和contentType属性
- php小技巧 把数组的键和值交换形成了新的数组,查找值取得键
- PHP获取表单textarea数据中的换行问题
- Python 编码规范(Google Python Style Guide)
- jQuery基于随机数解决中午吃什么去哪吃问题示例
- python 同时读取多个文件的例子
- 原生js实现的移动端可拖动进度条插件功能详解
- VMWare中Ubuntu重启后无法上网的解决方法
- C#如何添加PPT背景
- Python数据分析:手把手教你用Pandas生成可视化图表的教程