学习链接:https://blog.csdn.net/u010425776/article/details/51170118

博主整理的条理清晰,在这里先感谢博主分享

去年看视频学习写过一篇JVM的博客,今年已经忘得精光,归根结底是没有结合实践深入理解,为加深记忆,手打重新整理一下,一边思考,加深理解:

JVM内存模型

Java虚拟机(Java Virtual Machine=JVM)的内存空间分为五个部分,分别是:

1. 程序计数器
2. Java虚拟机栈
3. 本地方法栈
4. 堆

5. 方法区

1、程序计数器:

1.1什么是程序计数器:

程序计数器是较小的一块内存空间,记录了当前线程执行到的字节码文件的行号

1.2、程序计数器的作用:

1、字节码解释器通过改变程序计数器依次读取指令,实现代码流程控制,如顺序执行,循环等

2、多线程情况下记录当前线程执行到的位置,方便线程激活时继续执行

1.3、程序计数器的特点:

1、是一片较小的存储空间

2、线程私有,每条线程都有自己的程序计数器

3 、是唯一一个不会出现OutOfMemoryError的内存区域

4、生命周期随线程的创建而创建,随现成的销毁而销毁

2. Java虚拟机栈(JVM Stack)

2.1什么是java虚拟机栈:

java虚拟机栈是描述方法运行过程的内存模型

2.2java虚拟机栈的作用:

java虚拟机栈会为每个即将运行的方法分配内存,称作栈帧,存储运行过程中需要的一些信息。

包括:

1、局部变量表(基本数据类型、引用引用数据类型变量(内存地址?)、returnAddress(没听过))

2、操作数栈

3、动态链接

4、方法出口信息

5、等

2.3过程与特点:

当一个方法即将被运行时,Java虚拟机栈首先会在Java虚拟机栈中为该方法创建一块“栈帧”,栈帧中包含局部变量表、操作数栈、动态链接、方法出口信息等。当方法在运行过程中需要创建局部变量时,就将局部变量的值存入栈帧的局部变量表中(看不懂)。
当这个方法执行完毕后,这个方法所对应的栈帧将会出栈,并释放内存空间。

注意:人们常说,Java的内存空间分为“栈”和“堆”,栈中存放局部变量,堆中存放对象。

这句话不完全正确!这里的“堆”可以这么理解,但这里的“栈”只代表了Java虚拟机栈中的局部变量表部分。真正的Java虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息.

3.本地方法栈

与虚拟机栈类似,好像是用于native修饰的本地方法balabala~

4.堆

4.1什么是堆与堆的作用:

堆是用来存放对象的内存空间,几乎所有的对象都存储在堆中。

4.2堆的特点:

1、线程共享:

整个java虚拟机只有一个堆,所有线程都访问同一个堆。而程序计数器,java虚拟机栈,本地方法栈都是一个线程对应一个。

2、虚拟机启动时创建

3、垃圾回收的主要场所

4、可以进一步细分为新生代,老年代(这个记得JDK7之后与之前有所改动)。新生代又可以分为Eden(伊甸,起点的意思?)、from servior、to servior。不同的区域存放不同周期的对象。虚拟机根据不同的区域采取不同的垃圾回收算法,从而更高效。

5、主流虚拟机堆都是可扩展的,当线程请求虚拟机分配内存,但堆已满的时候,会抛出outofmemoryError

5.方法区

5.1、什么是方法区:

java虚拟机规范中定义方法区是堆的一个逻辑部分。

方法区中存放被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

5.2、方法区的特点:

1、线程共享:由于是堆的一部分,所以和堆一样都是线程共享的,整个虚拟机都只有一个方法区。

2、永久代:方法区中的数据一般要长期存在,而且它又是堆的逻辑分区,所以按照堆的划分方法,我们把方法区称为老年代

3、方法去中的数据一般长期存在,垃圾回收器一次只能回收少量数据,所以垃圾回收策略主要是对常量池的回收以及类型的卸载。

4、java虚拟机规范对方法区要求比较宽松,允许固定或扩展大小,也允许不执行垃圾回收。

5.3、运行时常量池

方法区中存放三种数据:类信息、常量、静态变量、即时编译器编译后的代码(这是啥)。其中常量存储在运行时常量池中。

我们一般在一个类中通过public static final来声明一个常量。这个类被编译后便生成Class文件,这个类的所有信息都存储在这个class文件中。

当这个类被Java虚拟机加载后,class文件中的常量就存放在方法区的运行时常量池中。而且在运行期间,可以向常量池中添加新的常量。如:String类的intern()方法就能在运行期间向常量池中添加字符串常量。

当运行时常量池中的某些常量没有被对象引用,同时也没有被变量引用,那么就需要垃圾收集器回收。

6. 直接内存

直接内存是除Java虚拟机之外的内存,但也有可能被Java使用。

NIO中引入了一种基于通道和缓冲的IO方式(看不懂)。它可以通过调用本地方法直接分配Java虚拟机之外的内存,然后通过一个存储在Java堆中的DirectByteBuffer对象直接操作该内存,而无需先将外面内存中的数据复制到堆中再操作,从而提升了数据操作的效率。

直接内存的大小不受Java虚拟机控制,但既然是内存,当内存不足时就会抛出OOM异常。

创建对象过程与访问对象的过程

创建对象的过程:https://blog.csdn.net/u010425776/article/details/51190801

摘抄对象内存模型:

对象的创建过程

当虚拟机遇到一条含有new的指令时,会进行一系列对象创建的操作:

  1. 检查常量池中是否有即将要创建的这个对象所属的类的符号引用;

    • 若常量池中没有这个类的符号引用,说明这个类还没有被定义!抛出ClassNotFoundException;
    • 若常量池中有这个类的符号引用,则进行下一步工作;
  2. 进而检查这个符号引用所代表的类是否已经被JVM加载;

    • 若该类还没有被加载,就找该类的class文件,并加载进方法区;
    • 若该类已经被JVM加载,则准备为对象分配内存;
  3. 根据方法区中该类的信息确定该类所需的内存大小;
    一个对象所需的内存大小是在这个对象所属类被定义完就能确定的!且一个类所生产的所有对象的内存大小是一样的!JVM在一个类被加载进方法区的时候就知道该类生产的每一个对象所需要的内存大小。

  4. 从堆中划分一块对应大小的内存空间给新的对象;
    分配堆中内存有两种方式:

    • 指针碰撞
      如果JVM的垃圾收集器采用复制算法或标记-整理算法,那么堆中空闲内存是完整的区域,并且空闲内存和已使用内存之间由一个指针标记。那么当为一个对象分配内存时,只需移动指针即可。因此,这种在完整空闲区域上通过移动指针来分配内存的方式就叫做“指针碰撞”。
    • 空闲列表
      如果JVM的垃圾收集器采用标记-清除算法,那么堆中空闲区域和已使用区域交错,因此需要用一张“空闲列表”来记录堆中哪些区域是空闲区域,从而在创建对象的时候根据这张“空闲列表”找到空闲区域,并分配内存。
      综上所述:JVM究竟采用哪种内存分配方法,取决于它使用了何种垃圾收集器。
  5. 为对象中的成员变量赋上初始值(默认初始化);

  6. 设置对象头中的信息;

  7. 调用对象的构造函数进行初始化
    此时,整个对象的创建过程就完成了。

访问对象的过程

我们知道,引用类型的变量中存放的是一个地址,那么根据地址类型的不同,对象有不同的访问方式:

  1. 句柄访问方式
    堆中需要有一块叫做“句柄池”的内存空间,用于存放所有对象的地址和所有对象所属类的类信息。
    引用类型的变量存放的是该对象在句柄池中的地址。访问对象时,首先需要通过引用类型的变量找到该对象的句柄,然后根据句柄中对象的地址再访问对象。

  2. 直接指针访问方式
    引用类型的变量直接存放对象的地址,从而不需要句柄池,通过引用能够直接访问对象。
    但对象所在的内存空间中需要额外的策略存储对象所属的类信息的地址。

【JVM】01虚拟机内存模型的更多相关文章

  1. java中JVM虚拟机内存模型详细说明

    java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03|  分类: JAVA |  标签:java  jvm  堆内存  虚拟机  |举报|字号 订阅     JVM的内部结构 ...

  2. JVM学习笔记——内存模型篇

    JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...

  3. Java虚拟机内存模型及垃圾回收监控调优

    Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...

  4. 【JVM】Java内存模型

    原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...

  5. [转帖]JVM—深入理解内存模型与垃圾收集机制

    JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...

  6. (转载)JVM中的内存模型与垃圾回收

    转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1  内存模型与运行时数据区 Java虚拟机在执行J ...

  7. 栈帧 2.6. Frames 虚拟机内存模型

    https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-2.html#jvms-2.6 小结: 1. https://docs.oracle. ...

  8. Java虚拟机--内存模型与线程

    Java虚拟机--内存模型与线程 高速缓存:处理器要与内存交互,如读取.存储运算结果,而计算机的存储设备和处理器的运算速度差异巨大,所以加入一层读写速度和处理器接近的高速缓存来作为内存和处理器之间的缓 ...

  9. jvm 虚拟机内存模型

    来源:https://blog.csdn.net/A_zhenzhen/article/details/77917991?locationNum=8&fps=1    https://blog ...

随机推荐

  1. 距离北京奥运还有359天,发布WPF版本的北京2008标志(上)

    原文:距离北京奥运还有359天,发布WPF版本的北京2008标志(上) 效果图: XAML代码:<Canvas Width="343.581055" Height=" ...

  2. C#中的MessageBox消息对话框

    关键字:C# MessageBox 消息对话框 在程序中,我们经常使用消息对话框给用户一定的信息提示,如在操作过程中遇到错误或程序异常,经常会使用这种方式给用于以提示.在C#中,MessageBox消 ...

  3. 机器学习: Tensor Flow with CNN 做表情识别

    我们利用 TensorFlow 构造 CNN 做表情识别,我们用的是FER-2013 这个数据库, 这个数据库一共有 35887 张人脸图像,这里只是做一个简单到仿真实验,为了计算方便,我们用其中到 ...

  4. C/C++回调方式系列之一 函数指针和函数回调模式

    一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...

  5. Matlab随笔之插值与拟合(下)

    原文:Matlab随笔之插值与拟合(下) 1.二维插值之插值节点为网格节点 已知m x n个节点:(xi,yj,zij)(i=1…m,j=1…n),且xi,yi递增.求(x,y)处的插值z. Matl ...

  6. WPF 设置类库项目为启动项,设置窗体跟随。

    原文:WPF 设置类库项目为启动项,设置窗体跟随. 1.添加用于启动的类Program.cs,需要一个静态的Main函数入口. using System; using System.Windows; ...

  7. Easyui Tab刷新

    Easyui Tab刷新: function refreshTab(title){ var tab = $('#id').tab('getTab',title); $('#id').tab('upda ...

  8. 读取spring工程中resource的文件

    Resource resource = new ClassPathResource("data.json"); // 读文件到字符串 String fileContent = Fi ...

  9. WPF WindowChrome 自定义窗口

    1.wpf自定义窗口: WindowChrome类描述:https://msdn.microsoft.com/zh-cn/library/system.windows.shell.windowchro ...

  10. fastjson 出现首字母小写的问题

    今天工作使用fastjson要求传过去的参数全为大写,在使用的过程中发现它自动将我的字段首字母转为小写了,在网上查了一些资料,发现下面的这个挺好,比其他的要方便. package com.alibab ...