最近看了《深入理解虚拟机》的内存分配与管理这部分的内容,这里做一个的总结,以加深我对知识点的理解,如有错误的地方,还望大神们指出,我及时更正;

  

   内存区域划分

    首先是下面这幅图:

    

                    图 1.0

    这幅图是网上download下来的,但是它可以很直观告诉我们Java虚拟机所管理的几个内存区域(包括方法区、堆、虚拟机栈、本地方法栈、程序计数器五个区域),以及线程作用在这些内存区域时的数据访问方式(虚拟机栈、本地方法栈、程序计数器三个区域是线程独有;方法区、堆两个区域是线程间共享);

    1.我们首先看看灰色模块中的 程序计数器模块;

    它属于灰色模块,所以它的第一个特点就是它是线程私有的,各条线程之间的计数器互不影响,独立存储(在多线程环境下保证每条线程执行字节码指令时,指示的下一条指令不会错乱);

    第二个特点是,它的用途。学过计算机组成原理的都知道PC寄存器,Java虚拟机中的这个PC寄存器功能和硬件级的PC寄存器相似,看作当前线程所执行的字节码的行号指示器(保存着下一条需要执行的字节码指令或者指令的地址),字节码解析器通过改变这个计数器的值来选取下一条需要执行的字节码指令,如条件分支(如if)、循环(如for)、跳转(如switch)、异常处理(异常表跳转地址)、线程恢复等基础功能都需要依赖这个计数器来完成;

    2.再看灰色模块中的 虚拟机栈模块;

    它的一个特点也是线程私有的,它的生命周期和线程相同,即一个线程执行开始,创建一个虚拟机栈,线程结束也会相应的销毁虚拟机栈;

    第二个特点 虚拟机栈中的栈元素叫做栈针(如下图1.1所示),即虚拟机栈中有一个元素就表示还有一个栈针在虚拟机栈中;栈针的入栈和出栈对应着线程中对一个方法的调用到这个方法执行结束返回,当线程中的所有方法调用都执行结束,那么线程栈中的栈针也就全部出栈完成,线程执行结束,线程栈也就相应的被销毁,回收;

    第三,再来看看栈针这个结构中存储的内容是什么;(如下图1.1所示),栈针中主要存有

      1.局部变量表:其实这个表就是用于存储我们当前所调用的函数的参数,以及我们在函数中定义的局部变量;在Java程序被编译成Class文件时,就在方法表集合的Code属性的max_locals数据项中确定了该方法所需要分配的最大局部变量表的容量(方法表集合这部分的知识涉及到Class类文件结构中方法表集合的知识点,请自行查阅),说白了就是编译完成后,局部变量表的最大尺寸就是定了的;局部变量表的容量以变量槽(Slot)为最小单位,32位虚拟机中一个Slot可以存放一个32位以内的数据类型(boolean、byte、char、short、int、float、reference和returnAddress八种)。

      2.操作数栈:Java虚拟机的解释执行引擎被称为"基于栈的执行引擎",其中所指的栈就是指-操作数栈。操作数栈也常被称为操作栈。和局部变量表一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。比如,iadd指令就要从操作数栈中弹出两个整数,执行加法运算,其结果又压回到操作数栈中,看看下面的示例,它演示了虚拟机是如何把两个int类型的局部变量相加,再把结果保存到第三个局部变量的:

Java 字节码指令(可以看解释说明文字)

 begin
iload_0 // push the int in local variable 0 onto the stack
iload_1 // push the int in local variable 1 onto the stack
iadd // pop two ints, add them, push result
istore_2 // pop int, store into local variable 2
end

   

                    图 1.2

   在前边的字节码序列里,前两个指令iload_0和iload_1将存储在局部变量中索引为0和1的整数压入操作数栈中,其后iadd指令从操作数栈中弹出那两个整数相加,再将结果压入操作数栈。第四条指令istore_2则从操作数栈中弹出结果,并把它存储到局部变量区索引为2的位置。上图1.2 详细表述了这个过程中局部变量和操作数栈的状态变化,图中没有使用的局部变量区和操作数栈区域以空白表示。

       3. 动态链接

      这里先解释一下方法调用的静态解析和动态链接,静态解析是指在编译期就确定了要调用方法的具体地址,方法调用指令的符号引用参数就是直接引用;具体在Java语言中的体现为1.类的静态方法调用,类的私有方法调用,对父类的方法调用;动态链接是指,方法调用的具体地址只有在运行时才能确定;具体在Java语言中的体现为1.类的虚方法调用,典型的特征就是有override注解修饰的方法;就是,如果符号引用是在类加载阶段或者第一次使用的时候转化为直接,那么这种转换成为静态解析,如果是在运行期间转换为直接引用,那么这种转换就成为动态连接;动态链接用于存储运行期转换的直接引用;

       4.返回地址

       方法的返回分为两种情况,一种是正常退出,退出后会根据方法的定义来决定是否要传返回值给上层的调用者,一种是异常导致的方法结束,这种情况是不会传返回值给上层的调用方法.对于异常退出的情况如果这个异常没有在方法体内被catch捕获并处理,那么这个方法是不会给它的上层调用者产生任何返回值的;程序会直接跳到匹配的异常处理器的位置,第一个能够catch到这个异常的位置;

        

    

            图 1.1

    虚拟机栈学习体会:用了较长的篇幅介绍虚拟机栈,主要是因为这部分的内容和我们编程中的最经常使用的方法调用息息相关,理解了这些,我们在编写代码时就会有更全面和深入的考虑,写出的代码也会更健壮;

    3. 接下来看图1.0中的 的第三个灰色模块 本地方法栈;

    它和虚拟机栈发挥的作用非常相似,它们的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务, 而本地方法栈则为虚拟机使用到的Native方法服务;在 HotSpot虚拟机中直接就把它们合二为一;

    4. 线程独占的内存区域都说完了,接下来看一看线程间共享的内存区域 绿色区域中的方法区;

    它用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码、 等数据;

    这里是一篇对方法区进行了详细介绍的博文,写的很详细;

    http://blog.csdn.net/bingduanlbd/article/details/8548916/

    5.绿色区域的 Java堆

    Java堆随虚拟机启动时创建,它的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存;这也是GC主要管理的区域;当我们new 一个对象时,对象的数据部分就存储在堆中,该对象的引用则通常存储在栈中;

    需要注意的特点是它是线程间共享访问的,所以在使用堆中的对象时,在多线程的环境下需要考虑,线程对对象的并发访问的问题;
  

  内存泄漏和内存溢出的区别

  1.内存泄漏是指我们不再使用的需要清理的对象,由于还存在引用链,这些对象仍然占用着内存,虚拟机迟迟没有进行清理,这一部分没有被正常清理的内存就是内存泄漏;  

  2.内存溢出是指我们真正需要使用的对象内存,超出了虚拟机能够分配给我们的内存,这时就会造成内存溢出;

Java 内存区域划分 备忘录的更多相关文章

  1. Java 内存区域划分

            JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的 ...

  2. Java内存区域划分和GC机制

    Java 内存区域和GC机制   目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Ga ...

  3. 深入理解JVM - 1 - Java内存区域划分

    作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...

  4. Java内存区域划分、内存分配原理(转)

    文章引用自 http://blog.csdn.net/OyangYujun/article/details/41173747 运行时数据区域 Java虚拟机在执行Java的过程中会把管理的内存划分为若 ...

  5. Java内存区域划分、内存分配原理(深入理解JVM一)

    Java虚拟机在执行Java的过程中会把管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,而有的区域则依赖线程的启动和结束而创建和销 ...

  6. 【java】JVM的内存区域划分

    学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的呢? 由于Java程序是交由JVM执行 ...

  7. JVM的内存区域划分

            JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的 ...

  8. Java虚拟机-----------Java内存区域与内存溢出异常

    Java内存区域划分 Java虚拟机运行时的数据区大致可划分为五部分:方法区,堆(两部分组成Java堆内存),虚拟机栈,本地方法栈(Java栈内存),程序计数器. 1.程序计数器 程序计数器占较小的内 ...

  9. JVM的内存区域划分(转)

    原文链接:JVM的内存区域划分 JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内 ...

随机推荐

  1. 偏置-方差分解(Bias-Variance Decomposition)

    本文地址为:http://www.cnblogs.com/kemaswill/,作者联系方式为kemaswill@163.com,转载请注明出处. 机器学习的目标是学得一个泛化能力比较好的模型.所谓泛 ...

  2. ch1-vuejs基础入门(hw v-bind v-if v-for v-on v-model 应用组件简介 小案例)

    1 hello world 引入vue.min.js 代码: ----2.0+版本 <div id="test"> {{str}} </div> <s ...

  3. zoj3961(区间问题)

    点击打开zoj1961Let's Chat Time Limit: 1 Second      Memory Limit:65536 KB ACM (ACMers' Chatting Messenge ...

  4. Sql Server合并多行询数据到一行:使用自连接、FOR XML PATH('')、STUFF或REPLACE函数

    示例表 tb 数据如下 id value ----- 1 aa 1 bb 2 aaa 2 bbb 2 ccc SELECT id, [val] = ( SELECT [value] + ',' FRO ...

  5. 第七章 DAO模式

    第七章 DAO模式 一.JDBC的封装 1.JDBC的封装: DAO位于业务逻辑和持久化数据之间,实现对持久化数据的访问.将数据库都封装起来,对外提供相应的接口 2.DAO模式的作用: 1.隔离业务逻 ...

  6. ES6的变量解构赋值

      前  言 ES6 解构赋值: ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构. 1.1 数组的结构赋值 1.1.1基本用法 JS中,为变量赋值直接指定.例如下面代码: ...

  7. python re模块findall()详解

    今天写代码,在写到郑泽的时候遇到了一个坑,这个坑是re模块下的findall()函数. 下面我将结合代码,记录一下 import re string="abcdefg acbdgef abc ...

  8. Hadoop2.7.3集群搭建

    hadoop2.0已经发布了稳定版本了,增加了很多特性,比如HDFS HA.YARN等.最新的hadoop-2.4.1又增加了YARN HA   注意:apache提供的hadoop-2.4.1的安装 ...

  9. property--staticmethod--classmethod

    特性(property): 作为装饰器使用,调用方式从最初的方法调用改变为属性调用 类方法(classmethod):和类进行交互,单不和实例进行交互 在函数中可以不用上传参数 静态方法(static ...

  10. BootStrap教程完整版

    http://www.runoob.com/bootstrap/bootstrap-navbar.html