初识JMM

参考《Inside JVM》

what is JMM?

从单词字面意思(java Memory Model)java内存模型。JMM阐述了程序中各变量的关系,比如实例变量,静态变量,数组。学过计算机底层原理的,应该还知道寄存器到内存,内存到寄存器的关系,说的白一点就是 :JMM是计算机操作系统中将变量存储到内存中,再从内存中取出变量的底层细节。

JMM变量存储结构

在java中所有的变量都是存储在主内存(Main Memory或Java Heap Memory)中的,所以这些变量对线程可以共享的,每个线程也都会有自己的工作内存(Working Memory)。当需要使用主内存中的一些变量时,线程中的工作内存就会对这些主内存中的变量进行copy然后并保存到自己的工作内存。(原因:线程中对主内存中变量的操作并不是发生在主内存,而是在每个线程自己的工作内存中进行,所以当线程之间互相访问工作内存中的变量时,是要通过java主内存为桥梁进行互相访问的)

上图可见 ,个线程将自己工作内存中变量刷新到主内存中,再由其它线程更新获取主内存中的共享变量。

JMM三大特性

原子性

执行一个程序时,从头到尾没有中断,执行完毕,或者出现异常时,程序回滚到程序最处始状态。数据的读取和存储单元的写入操作,包括实例变量,数组,静态变量都是属于原子级别的。

可见性

一个共享变量,由一个线程通过一系列操作来改变这个共享变量的值时,其它线程来读取的这个共享变量值也会随之改变。

有序性

对于平常的线程程序而言,我们都认为程序都是从前向后,依次执行的。在单线程中确实是这样,然而在多线程中,所有的执行都是没有顺序的

java 堆栈

讲堆栈之前,我们先说下java的内存管理。java中自带内存管理,也就是我们常说的GC(垃圾回收)。当JVM发现一些不再引用的对象时,就会释放这些内存,让其它需要内存的对象使用。垃圾回收器避免了悬挂引用的问题,GC同样解决来内存泄漏的问题。
Inside JVM书中的概念(比本人概括太好了,直接引用下)[编译原理]学过编译原理的人都明白,程序运行时有三种内存分配策略:静态的、栈式的、堆式的

静态存储

  静态存储——是指在编译时就能够确定每个数据目标在运行时的存储空间需求,因而在编译时就可以给它们分配固定的内存空间。这种分配策略要求程序代码中不允许有可变数据结构的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间。

栈式存储

  栈式存储——该分配可成为动态存储分配,是由一个类似于堆栈的运行栈来实现的,和静态存储的分配方式相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到了运行的时候才能知道,但是规定在运行中进入一个程序模块的时候,必须知道该程序模块所需要的数据区的大小才能分配其内存。和我们在数据结构中所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。

堆式存储

  堆式存储——堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例,堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。

JVM是啥

在Java虚拟机规范中,虚拟机实例的行为描述子系统而言,内存区域,数据类型和指令。这些组件描述抽象的内部架构的抽象的Java虚拟机。这些组件的目的与其说是决定内部架构的实现。更提供了一种严格定义的外部行为的实现。规范定义了所需的行为的任何Java虚拟机实现这些抽象组件及其之间的交互。每个Java虚拟机有一个类装入器子系统:加载机制类型(类和接口)指定完全限定的名称。每个Java虚拟机还提供一个执行引擎:一种机制负责执行的指令包含在加载的类的方法。

当一个Java虚拟机运行一个程序,它需要内存来存储很多东西,包括字节码和其他信息摘录加载类文件,程序实例化对象,参数方法,返回值,局部变量,计算的中间结果。Java虚拟机把这些数据都需要执行一个程序分成几个运行时数据区。虽然相同的运行时数据区以某种形式存在于每一个Java虚拟机实现,规范是相当抽象的。不同的虚拟机的实现可以有非常不同的内存限制。有些实现可能有很多内存,其它占用的内存却很少。有些实现可以利用虚拟内存,抽象性质的规范运行时数据区帮助更容易实现Java虚拟机在各种各样的电脑和设备中运行。
一些运行中的数据被当前的共享线程和其他各个线程所特有的。Java虚拟机的每个实例都有一个区域和一堆的方法。这些区域内运行的所有线程共享虚拟机。当虚拟机加载一个类文件,它解析信息类型的二进制数据中包含的类文件。这地方类型信息的方法。当程序运行时,虚拟机程序所有对象实例化到堆的地方。
Java堆栈由堆栈帧(帧)。一个堆栈帧包含一个Java方法调用的状态。当一个线程调用一个方法时,Java虚拟机把一个新的frame给Java堆栈的线程。方法完成时,虚拟机就会释放frame中的方法。Java虚拟机没有寄存器来保存中间数据值。指令集使用Java堆栈存储中间数据值。

ps: 看着英文书籍,后半部分的理解比较吃力,得苦练英文了。后续会接着上面的继续深入理解JMM,JVM的内部原理。

posted @ 2018-08-12 20:53  Levcon  阅读(250)  评论(0编辑  收藏  举报