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

  

   内存区域划分

    首先是下面这幅图:

    

                    图 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 字节码指令(可以看解释说明文字)

  1. begin
  2. iload_0 // push the int in local variable 0 onto the stack
  3. iload_1 // push the int in local variable 1 onto the stack
  4. iadd // pop two ints, add them, push result
  5. istore_2 // pop int, store into local variable 2
  6. 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. bzoj3224 普通平衡树(c++vector)

    Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...

  2. js-异步机制与同步机制

    Javascript的优势之一是其如何处理异步代码.异步代码会被放入一个事件队列,等到所有其他代码执行后才进行,而不会阻塞线程 1 理解异步代码: 1.1 JavaScript最基础的异步函数是set ...

  3. Jquery实现数据双向绑定(赋值和取值),类似AngularJS

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  4. 【转载】使用CSS将图片转换成黑白(灰色、置灰)

    文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=2547原文摘要: . ...

  5. Mysql数据库导出数据字典文档Word或者HTML的3个工具

    最近需要将Mysql的数据库导出一份Word的文档出来,本文记录调研后几个可用的工具和方法: 阿里云DMS工具导出 适用于存储在阿里云RDS服务中的Mysql数据库 导出格式支持:Word.Excel ...

  6. win10 uwp MVVM入门

    MVVM 是一个强大的架构,基本从 WPF 开始,wr(我说的就是微软)就提倡使用 MVVM.它可以将界面和后台分离,让开发人员可以不关心界面是怎样,全心投入到后台代码编写中. 然后在编写完后台代码后 ...

  7. node+vue进阶【课程学习系统项目实战详细讲解】打通前后端全栈开发(1):创建项目,完成登录功能

    第一章 建议学习时间8小时·分两次学习      总项目预计10章 学习方式:详细阅读,并手动实现相关代码(如果没有node和vue基础,请学习前面的vue和node基础博客[共10章]) 视频教程地 ...

  8. 【转】ATA Secure Erase

    ATA Secure Erase     This procedure describes how to use the hdparm command to issue a Secure Erase  ...

  9. [ACdream]瑶瑶带你玩激光坦克

    题目链接:http://acdream.info/contest?cid=1269#problem-B Problem Description 有一款名为激光坦克的游戏,游戏规则是用一个坦克发出激光来 ...

  10. APUE 4 - 线程<2> : 线程同步

    当控件的多个线程共享统一内存时,我们需要确定各个线程访问到的数据的一致性.在cpu结构中,修改操作由多个内存读写周期(memory cycle),而在这些内存周期之间, 有可能会发生其他线程的内存读操 ...