【JVM】01虚拟机内存模型
学习链接: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的指令时,会进行一系列对象创建的操作:
检查常量池中是否有即将要创建的这个对象所属的类的符号引用;
- 若常量池中没有这个类的符号引用,说明这个类还没有被定义!抛出ClassNotFoundException;
- 若常量池中有这个类的符号引用,则进行下一步工作;
进而检查这个符号引用所代表的类是否已经被JVM加载;
- 若该类还没有被加载,就找该类的class文件,并加载进方法区;
- 若该类已经被JVM加载,则准备为对象分配内存;
根据方法区中该类的信息确定该类所需的内存大小;
一个对象所需的内存大小是在这个对象所属类被定义完就能确定的!且一个类所生产的所有对象的内存大小是一样的!JVM在一个类被加载进方法区的时候就知道该类生产的每一个对象所需要的内存大小。从堆中划分一块对应大小的内存空间给新的对象;
分配堆中内存有两种方式:- 指针碰撞
如果JVM的垃圾收集器采用复制算法或标记-整理算法,那么堆中空闲内存是完整的区域,并且空闲内存和已使用内存之间由一个指针标记。那么当为一个对象分配内存时,只需移动指针即可。因此,这种在完整空闲区域上通过移动指针来分配内存的方式就叫做“指针碰撞”。 - 空闲列表
如果JVM的垃圾收集器采用标记-清除算法,那么堆中空闲区域和已使用区域交错,因此需要用一张“空闲列表”来记录堆中哪些区域是空闲区域,从而在创建对象的时候根据这张“空闲列表”找到空闲区域,并分配内存。
综上所述:JVM究竟采用哪种内存分配方法,取决于它使用了何种垃圾收集器。
- 指针碰撞
为对象中的成员变量赋上初始值(默认初始化);
设置对象头中的信息;
调用对象的构造函数进行初始化
此时,整个对象的创建过程就完成了。
访问对象的过程
我们知道,引用类型的变量中存放的是一个地址,那么根据地址类型的不同,对象有不同的访问方式:
句柄访问方式
堆中需要有一块叫做“句柄池”的内存空间,用于存放所有对象的地址和所有对象所属类的类信息。
引用类型的变量存放的是该对象在句柄池中的地址。访问对象时,首先需要通过引用类型的变量找到该对象的句柄,然后根据句柄中对象的地址再访问对象。直接指针访问方式
引用类型的变量直接存放对象的地址,从而不需要句柄池,通过引用能够直接访问对象。
但对象所在的内存空间中需要额外的策略存储对象所属的类信息的地址。
【JVM】01虚拟机内存模型的更多相关文章
- java中JVM虚拟机内存模型详细说明
java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03| 分类: JAVA | 标签:java jvm 堆内存 虚拟机 |举报|字号 订阅 JVM的内部结构 ...
- JVM学习笔记——内存模型篇
JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...
- Java虚拟机内存模型及垃圾回收监控调优
Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...
- 【JVM】Java内存模型
原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...
- [转帖]JVM—深入理解内存模型与垃圾收集机制
JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...
- (转载)JVM中的内存模型与垃圾回收
转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1 内存模型与运行时数据区 Java虚拟机在执行J ...
- 栈帧 2.6. Frames 虚拟机内存模型
https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-2.html#jvms-2.6 小结: 1. https://docs.oracle. ...
- Java虚拟机--内存模型与线程
Java虚拟机--内存模型与线程 高速缓存:处理器要与内存交互,如读取.存储运算结果,而计算机的存储设备和处理器的运算速度差异巨大,所以加入一层读写速度和处理器接近的高速缓存来作为内存和处理器之间的缓 ...
- jvm 虚拟机内存模型
来源:https://blog.csdn.net/A_zhenzhen/article/details/77917991?locationNum=8&fps=1 https://blog ...
随机推荐
- PHP设置时区,记录日志文件的方法
关键字:PHP 时区 时间 日志 <html> <body> <?php date_default_timezone_set('Asia/Hong_Kong'); //s ...
- VirtualBox虚拟机网络环境Host-Only(对Win10和VirtualBox都有截图)
之前在选择配置虚拟机网络环境的时候 桥接也是不错的,但是自己在使用的时候由于访问频繁会出现断网现象.所以就开始使用Host-Only模式.开始并不是很明白为什么这么设置,也挖了很多坑.经常出现虚拟机无 ...
- c语言指针详细解释
指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最基本的风格之中的一个.利用指针变量能够表示各种数据结构: 能非常方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编出精练而高 ...
- 关于C#你应该知道的2000件事
原文 关于C#你应该知道的2000件事 下面列出了迄今为止你应该了解的关于C#博客的2000件事的所有帖子. 帖子总数= 1,219 大会 #11 -检查IL使用程序Ildasm.exe d #179 ...
- 【C/S通信交互之Http篇】Cocos2dx(Client)使用Curl与Jetty(Server)实现手机网游Http通信框架(内含解决curl.h头文件找不到问题)
之前已经分享过一篇基于Cocos2dx与服务器使用Socket进行通信的框架,还不太熟悉的请移步到如下博文中: [C/S通信交互之Socket篇]Cocos2dx(Client)使用BSD Socke ...
- 更新EF(更新表 添加表…)
- HTTP协议学习 - 9 Method Definitions
# 前言 官方文档简略翻译.9 不是代表第九篇,而是在 RFC2616 中是第九篇.重要加粗,龟速翻译. # Method 9.3 GET The GET method means retrieve ...
- Dynamic proxy (good-原创)
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflec ...
- Android零基础入门第18节:EditText的属性和使用方法
原文:Android零基础入门第18节:EditText的属性和使用方法 EditText与TextView非常相似,它甚至与TextView 共用了绝大部分XML属性和方法.EditText与Tex ...
- C#判断系统是32位还是64位
bool type; type = Environment.Is64BitOperatingSystem; Console.WriteLine(type);