网站首页 > 技术文章 正文
我们在面试的时候,经常会被问到一些关于内存的问题,或许有很多小伙伴就在JMM与JVM之间犯迷糊i,今天就来聊聊这两者的相关内容。
JMM: java memory model 翻译过来就是Java 内存模型。
为什么会有这个东西呢?
在操作系统层面,cpu的执行速度是很快的,而磁盘的读取速度很慢,由于磁盘的io操作涉及到磁盘的寻址,寻道加数据传输(io操作不是本文重点,下次再讲)很耗性能。因此cpu读取磁盘上的数据的性能瓶颈就是io,目前基于高速缓存的存储交互很好的解决了cpu和内存等其他硬件之间的速度矛盾,多核情况下各个处理器(核)都要遵循一定的诸如MSI、MESI等协议来保证内存的各个处理器高速缓存和主内存的数据的一致性
cpu不会直接去操作磁盘等硬件,而是操作高速缓存,这样性能上是提升上来了,但是在多cpu情况下,就会出现数据安全问题,例如:两个线程同时修改主内存中的一个值X,过程是线程a先从主内存将X的值读到a的工作内存,当a要对X进行+1操作时,突然a的cpu时间到了,切换到线程b,b也是和a一样的操作,然后切换到a将X+1的值更新到主内存,然后b再将X+1的值更新到主内存,本来在主内存中是X+2,但是实际上却是X+1,此时就发生了线程不安全的情况。也就是我们所说的X+1不是一个原子操作,X的值的变更对线程来说是不可见的。在java中可以通过用volate修饰变量来达到可见性。下期讲volate用法。
JVM: Java Virtual Machine,是java虚拟机的一个数据结构,java程序都是运行在虚拟机上。
可以理解是java运行时数据区域。
从上图可以看出,JVM由堆、虚拟机栈、本地方法栈、程序计数器、方法区组成
堆:jvm管理的最大的一块内存区域,所有线程共享堆数据
- 存储内容:new创建的对象和数组,垃圾收集器就是收集这些对象,然后根据GC算法回收
- 区域分配:分为eden区,s0区也叫from区,s1区也叫to区,老年代
- 堆的大小可以通过JVM选项-Xms和-Xmx来进行调整
分配比例:
Eden区 —— 新对象或者生命周期很短的对象会存储在这个区域中,这个区的大小可以通过-XX:NewSize和-XX:MaxNewSize参数来调整
Survivor区 —— 那些历经了Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域。这个区的大小可以由JVM参数-XX:SurvivorRatio来进行调节。
老年代 —— 那些在历经了Eden区和Survivor区的多次GC后仍然存活下来的对象(当然了,是拜那些挥之不去的引用所赐)会存储在这个区里。这个区会由一个特殊的垃圾回收器来负责。年老代中的对象的回收是由老年代的GC(major GC)来进行的。
新生代gc:Minor GC,gc算法是复制算法(从from区复制到to区)。
MinorGC的过程:采用复制算法。
- 首先,把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,一般是15,则赋值到老年代区)
- 同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区)
- 然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区
老年代gc:MajorGC 标记—清除算法:
- 首先扫描一次所有老年代,标记出存活的对象
- 然后回收没有标记的对象。
MajorGC的耗时比较长,因为要扫描再回收。MajorGC会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。
当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。
堆是最容易发生内存溢出和内存泄漏;
内存溢出:新创建的对象在堆中申请内存空间,内存空间不够时发生gc,gc后还是内存不够,就会发生内存溢出
内存泄漏:需要被gc的对象没有及时清除,在需要给对象申请内存空间时空间不足,就会发生内存泄漏
栈:栈分为本地方法栈和虚拟机栈
本地方法栈是调用一些底层的native方法。
虚拟机栈是线程私有的,其基本单元是栈帧,每个方法代表一个栈帧,存储的是一些据补变量表,操作涉数栈、动态链接、方法出口等,栈是一个先进后出的数据结构,一个方法的调用表示压栈,方法结束后出栈,有些递归的方法,如果没有出口或者递归层数很深,会引发栈内存溢出。可以通过JVM选项
-Xss来进行调整
程序计数器:是记录代码执行的行号,通过字节码执行引擎来对行号进行修改,如果执行的方法是native,则计数器为undinfined,
方法区:jdk1.7也叫永久代,jdk1.8则是将元空间代替了永久代,因为永久代用的是jvm内存,不可动态调整,而且会占用jvm内存,而在1.8用元空间代替,元空间则是一块物理内存区域,可通过增加物理内存来调整。
猜你喜欢
- 2024-10-28 美团面试:熟悉哪些JVM调优参数,幸好我准备过
- 2024-10-28 Java虚拟机:Jvm概念和原理详解以及GC机制的分析
- 2024-10-28 JVM 的内存模型(jvm1.8内存模型)
- 2024-10-28 JDK、JRE、JVM,是什么关系?(jdk jrejvm的区别)
- 2024-10-28 一个 JVM 参数引发的频繁 CMS GC(当产生一个异常时,jvm会做什么)
- 2024-10-28 JVM系列一:JVM内存组成及分配(jvm的内存分配)
- 2024-10-28 常见的JVM参数配置(常见的JVM参数配置有哪些)
- 2024-10-28 一份详细介绍JVM的资料(对比JDK8和JDK7)
- 2024-10-28 理解JVM运行时数据区域,看这一篇文章就够了
- 2024-10-28 2万字!JVM核心知识总结(jvm基础知识)
- 最近发表
-
- 如何在 Linux 上安装 Java_怎么在linux中安装jdk
- Linux中tar命令打包路径相关问题_linux怎么用tar打包一个目录
- 常用linux系统常用扫描命令汇总_常用linux系统常用扫描命令汇总表
- VM下linux虚拟机新建过程(有图)_linux虚拟机创建新用户命令
- 系统小技巧:迁移通过Wubi方式安装的Ubuntu系统
- 文件系统(八):Linux JFFS2文件系统工作原理、优势与局限
- 如何利用ftrace精确跟踪特定进程调度信息
- prometheus网络监控之fping-exporter
- hyper linux的实操步骤,hyper-v批量管理工具的使用指南
- 2021年,运维工程师笔试真题(二)(附带答案)
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)