JVM内存结构与内存模型
这篇文章重点讲一下jvm的内存结构和内存模型的知识点。(2023.3.11)
1、内存结构
jvm内存区域主要分为线程私有区域【程序计数器,虚拟机栈,本地方法栈】,线程共享区域【堆,方法区】,直接内存,其中线程私有区域和线程共享区域又统称为运行时数据区
- 程序计数器并不是物理存储器,而是jvm对物理pc计数器的模拟,是一块较小的内存,可以看作是字节码文件的行号指示器,指针指的就是当前字节码执行的指令地址,这个区域是整个jvm内存区域中唯一的没有OOM的
- 虚拟机栈,里面存储的是栈帧,遇到调动方法帧,则压入栈,调用完了则出栈,此外这块区域不存在垃圾回收问题,而且这个区域大小可固定也可以动态,如果是固定虚拟机栈,可能存在方法帧无法压入栈的情况,发生StackOverflow异常,如果是动态虚拟机栈,则新线程没有足够内存创建这块区域,发生OOM异常,而且也要关注下栈帧的结构
操作数栈存放的是计算过程中的临时变量或者中间结果
动态连接就是对运行常量池的引用,类加载机制过程中解析那一步的作用是将常量池中的符号引用替换成直接引用,这叫静态链接,而这里的动态连接的意思是在运行过程中转换成直接引用。 - 本地方法栈,顾名思义,调用本地方法时使用的栈,所谓本地方法就是java程序使用非java语言编写的接口
----在有一些JVM并不支持本地方法栈,Hotspot jvm更是将虚拟机栈和本地方法栈合并
宏观来看,两者都是栈,是程序运行时的数据结构,帮助程序执行,处理数据,而堆是存储数据结构,解决数据存储问题 - java堆
java堆分成了两个部分,分为新生代和老年代,新生代有分为Eden区,servivorFrom区,servivorTo区
新生代占java堆三分之一大小,存放新对象(不过如果新对象无法在新生代存放,则放入老年代),由于新对象频繁创建销毁,所以在新生代经常发生MinorGC。
Eden区是新对象的出生地,如果Eden区内存不够,则触发MinorGC,From,To区域又叫幸存者区,多次GC后还幸存者就会转换到老年代。
MinorGC的过程主要可以概括成 “复制”-->“清空”-->“交换”,“复制”指得是每一次GC后,把Eden和From区域的存活的对象复制到To区域,年龄+1,如果年龄过大则会放入老年代内存中,然后清空Eden和From区域,最后From和To区域身份互换
而老年代存放的是年龄大的对象和大对象,采用的MajorGC,MajorGC主要分为两步“扫描”-->“清除”,所以又叫标记清除算法,先扫描整个老年代,标记可以存活的对象,将没有标记的对象清除 - 方法区
方法区在JAVA7及之前由JVM 堆中永久带实现,JDK8之后永久代取消了,这不是说没有了方法区(注意这只是JVM的内存结构,不同的JVM有不同的实现),此外编译后和解析后又不一样,总得来说分成了一个作用,就是存放加载后字节码文件内容的,两个部分,第一个是存放类的基本信息,比如版本,接口,字段等,第二个就是运行时常量池,存放的是字节码文件中常量池中书面量和符号引用。
2.GC
请参考GC详解
在讲GC算法之前,要了解如何判断为垃圾
有两种方法,一是计数引用,顾名思义,对象如果没有任何与之关
联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。但存在bug就是循环引用(类似死锁)的问题,所以第二种方法就是可达性分析,从GC root到对象没有一个可以到达的路径,存是不可达对象,两次标记为不可打对象则转换为可回收的垃圾。GCRoot指得是的当前活跃的栈帧中指向堆对象的引用
GC方法可以分为MinorGC(复制-->清除-->交换),MajorGc(扫描标记-->清除),Full GC
* 垃圾收集器
新生代垃圾收集器有Serial,ParNew,Parallel Scavenge
1.Serial的特点是单线程,使用复制算法,启动Serial垃圾收集器要停止其他的用户工作线程,优点就是没有线程交互,效率高,是JVM客户端默认的收集器
2.ParNew就是Serial+多线程,也要暂停所有用户线程,是JVM服务端默认的收集器
3.Parallel Scavenge也是多线程,使用复制算法,也要暂停所有用户线程,这个收集器更关注的是吞吐量指标,吞吐量就是运行用户代码时间/(运行用户代码时间+垃圾收集时间)),所以它也采用了一个自适应调节策略,这也是与ParNEW最大的区别
老年代垃圾收集器有Serial Old,Parallel Old,CMS
Serial Old是老年代的Serial,不同的是采用的是标记整理算法,Parallel Old是Parallel Scavenge老年版,采用的是标记整理算法,重点理解一下CMS
CMS(Concurrent Mark Sweep),使用的是标记清除算法,他分为四个阶段,初始标记阶段,并发标记阶段,重新标记阶段,并发清除四个阶段,并发标记和并发清除是垃圾回收线程和用户线程一起工作,占用大部分时间,所以CMS整体来看是与用户线程并发执行的
除次之外,还有个G1收集器,它的特点是可以同时作用于新生代和老年代,采用的分区划分,把整个堆内存分成几块,同时追踪,优先清除垃圾较多的区域,使用的标记整理算法,避免造成内存碎片,G1回收器避免了全区域垃圾收集,同时也避免了内存碎片
3.JVM内存模型(JMM)
在学习JMM之前,要对堆、栈的概念十分清楚,可以试着回答下堆、栈分别存储什么,从JVM角度回答堆、栈的区别。我的理解是从存储内容角度上看,堆存储实例对象,而栈存储基本数据类型以及堆上对象的引用,从功能上看,堆主要负责存储数据,栈是处理数据,因为栈的单元是方法帧,有出栈,入栈的动作,此外,jvm角度,堆是线程共享的而栈是线程私有的。
上图有两个线程栈,代码是一样的,都是调用methodOne,methodOne再调用methodTwo,
但不同局部变量的引用是不一样的,首先看,methodOne的local variable 1没有堆中对象的引用,所以是基本类型变量,local variable 2指向了堆上同一个实例对象,这是个静态变量,同时这个静态变量Object 3也有两个引用Object2和Object4,这应该是Object3对象中有两个实例对象,不同线程的methodTwo的local variable 1对应着不同的Object的引用,所以这应该是一个普通实例对象,不同线程不同引用。
但无论是堆还是栈,都是存储在主存储器上的(也有可能存储在寄存器缓存以及CPU高速缓存中),所以要保证共享对象的修改是对所有线程是可见的,这里就涉及到并发关键字volatile,还有就是多个线程操作共享变量的竞态问题,这就涉及到了并发关键字synchronize,总之JMM的诞生是为了解决共享变量操作问题。JMM抽象了线程与主内存的关系,共享变量存储在主内存中,线程有一块工作内存存储共享变量的副本。
更详细的JMM请参考我的另一篇博客(https://www.cnblogs.com/spark-cc/p/17100278.html)
本人菜鸡,哪里写的有问题欢迎指正。
JVM内存结构与内存模型的更多相关文章
- JVM内存区域的划分(内存结构或者内存模型)
JVM内存区域的划分(内存结构或者内存模型) 运行时数据区域: 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 程序计数器(线程私有): 是当前线程所 ...
- JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)
一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...
- 面试突击(八)——JVM的结构及内存模型,是怎么划分的?
声明:本文图片均来自网络,我只是进行了选择,利用一图胜千言的力量来帮助自己快速的回忆相关的知识点 0:再上一张Java代码的转换流程图 .java——Java程序员编写,给人看的 .class——Ja ...
- struct class 内存结构初探-内存模型顺序和变量的实际添加顺序一致
typedef struct structTest { char xchar; int xint; int yint; }xStruct; @interface ViewController () { ...
- 【Java】JMM内存模型和JVM内存结构
JMM内存模型和JVM内存结构 JAVA内存模型(Java Memory Model) Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由JSR-133: JavaTM Memor ...
- 万万没想到,JVM内存结构的面试题可以问的这么难?
在我的博客中,之前有很多文章介绍过JVM内存结构,相信很多看多我文章的朋友对这部分知识都有一定的了解了. 那么,请大家尝试着回答一下以下问题: 1.JVM管理的内存结构是怎样的? 2.不同的虚拟机在实 ...
- JVM专题2: JVM内存结构
合集目录 JVM专题2: JVM内存结构 Java 内存分配 JVM 内存结构 The JVM is an abstract computing machine that enables a comp ...
- 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
一.JVM内存结构 ▷ 谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期.数据共享:是否GC.是否OOM 答:jvm 内存结构包括程序计数器.虚拟机栈.本地方法栈.堆.方法区:它是字节码运行时 ...
- [转]oracle学习入门系列之五内存结构、数据库结构、进程
原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...
- Java 内存结构备忘录
本文详细描述了 Java 堆内存模型,垃圾回收算法以及处理内存泄露的最佳方案,并辅之以图表,希望能对理解 Java 内存结构有所帮助.原文作者 Sumith Puri,本文系 OneAPM 工程师编译 ...
随机推荐
- PSPNet 代码分析
https://www.lmlphp.com/user/62501/article/item/1225624/ train.py 网络训练主函数,主要操作有: 传入训练参数:通常采用argparse库 ...
- vue后台管理系统
1. 项目概述: 根据不同的应用场景,电商系统一般都提供了 PC 端.移动 APP.移动 Web.微信小程序等多种终端访问方式. 2. 电商后台管理系统的功能 电商后台管理系统用于管理用户账号.商品分 ...
- 【python基础笔记-3】decimal模块解决浮点数计算精度问题
通过Decimal('123.456')对象实例化后做 + - * / 等运算符操作计算结果不会出现精度问题. Tips:值得注意的2点是 1.Decimal接收的入参是str,所以如果原本操作的数据 ...
- #PHP #MySQL数据操作 #在线聊天 PHP实现在线聊天与MySQL的“增查删改”
目录 1.目标图 2.项目简介 3.目录结构 4.建立MySQL表 5.实现过程 5.1 index.php 5.2 data.php 5.2 method.php 5.3 case.php 5.4 ...
- C++ 用运算符重载 实现复数相加
#include "stdafx.h" #include <iostream> using namespace std; class Complex {public: ...
- LSP原则中的逆变和协变
在复习过程中,LSP原则是个很重要的内容.这里先给出LSP原则的定义. LSP定义Functions that use pointers or referrnces to base classes m ...
- Springboot项目记录1配置环境
一.电脑商城项目: 项目功能:登录,注册,热销商品,用户管理(密码,个人信息,头像,收货地址).购物车(展示.增加.删除).订单模块. 二.开发顺序: 注册.登录.用户管理.购物车.商品.订单模块 三 ...
- day01学习小记
# Markdown学习 ## 标题 ### 三级标题 #### 四级标题 ## 字体 Hellow,World! Hellow,world hellow,world! hellow,world ## ...
- SpringBoot+MybatisPlus 多数据源问题
SpringBoot+Mybatis 多数据源报错 使用了2个数据源 @Bean("dataSource") @ConfigurationProperties(prefix = & ...
- 【Unity】关于VS条件编译符号
写在前面 起因:我在回顾LuaFramework_UGUI(作者Jarjin Lee)代码时,看到了C#代码中的条件编译符号,比如下图的ASYNC_MODE.虽然字面上知道是什么意思,但我对VS的条件 ...