8.JVM内存分配机制超详细解析.pdf

  1. 1、本文档共11页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
8.JVM内存分配机制超详细解析 ⼀、对象的加载过程 之前研究过类的加载过程。具体详情可查看⽂章: 那么,当⼀个对象被new的时候,是如何加载的呢?有哪些步骤,如何分配内存空间的呢? 1.1对象创建的主要流程 还是这段代码为例说明: public static void main(String[] args) { Math math = new Math(); pute(); new Thread().start(); } 当我们new⼀个Math对象的时候,其实是执⾏了⼀个new指令创建对象。我们之前研究过类加载的流程,那么创建⼀个对象的流程是怎样的呢?如下图所⽰。下⾯我们⼀个环节 ⼀个环节的分析。 1.1.1类加载检查 当虚拟机执⾏到⼀条new指令时,⾸先去检查这个指令的参数是否能在常量池中定位到⼀个类的符号引⽤,并且检查这个 符号引⽤代表的类是否已经被加载、解析和初始化过(也就是检查类是否已经被加载过)。如果没有,那必须先执⾏相应的类加载流程。 1.1.2分配内存空间 类加载检查通过以后,接下来就是给new的这个对象分配内存空间。对象需要多⼤内存是在类加载的时候就已经确定了的。为对象分配空间的过程就是从java 堆中划分出⼀块确 定⼤⼩的内存给到这个对象。那么到底如何划分内存呢?如果存在并发,多个对象同时都想占⽤同⼀块内存该如何处理呢? 1)如何给对象划分内存空间? 通常,给对象分配内存有两种⽅式:⼀种是指针碰撞,另⼀种是空闲列表。 指针碰撞 指针碰撞(Bump the Pointer),默认采⽤的是指针碰撞的⽅式。如果Java堆中内存是绝对规整的,所有⽤过的内存都放在⼀边,空闲的内存放在另⼀边,中间放着⼀个指针作 为分界点的指⽰器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动⼀段与对象⼤⼩相等的距离。 空闲列表 如果Java堆中的内存不是规整的,已使⽤的内存和空闲的内存相互交错,那就没有办法简单地进⾏指针碰撞了,虚拟机就必须维护⼀个列表,记录上哪些内存块是可⽤的,在分 配的时候从列表中找到⼀块⾜够⼤的空间划分给对象实例,并更新列表上的记录 不同的内存分配⽅式,在垃圾回收的时候采⽤不同的⽅法。 2)如何解决多个对象并发占⽤空间的问题? 当有多个线程同时启动的时候,多个线程new的对象都要分配内存,不管内存分配使⽤的是哪种⽅式,指针碰撞也好,空闲列表也好,这些对象都要去争抢这块内存。当多个线 程都想争抢某⼀块内存的时候,这时该如何处理呢?通常有两种⽅式:CAS和本地线程分配缓冲。 CAS (compare and swap) CAS可以理解为多个线程同时去争抢⼀个快内存,抢到了的就使⽤,没抢到的就重试去抢下⼀块内存。 虚拟机采⽤CAS配上失败重试的⽅式保证更新操作的原⼦性来对分配内存空间的动作进⾏同步处理。 本地线程分配缓冲(Thread Local Allocation Buffer,TLAB ) 什么是TLAB 呢?简单说,TLAB 是为了避免多线程争抢内存,在每个线程初始化的时候,就在堆空间中为线程分配⼀块专属的内存。⾃⼰线程的对象就往⾃⼰专属的那块内存存 放就可以了。这样多个线程之间就不会去哄抢同⼀块内存了。jdk8 默认使⽤的就是TLAB 的⽅式分配内存。 把内存分配的动作按照线程划分在不同的空间之中进⾏,即每个线程在Java堆中预先分配⼀⼩块内存。通过-XX:+UseTLAB参数来设定虚拟机是否使⽤TLAB(JVM会默认开启- XX:+UseTLAB) ,-XX:TLABSize 指定TLAB⼤⼩。 1.1.3 初始化 内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),如果使⽤TLAB ,这⼀⼯作过程也 可以提前⾄TLAB分配时进⾏。这⼀步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使⽤,程序能访问 到这些字段的数据类型所对应的零值。 1.1.4 设置对象头 我们来看看这个类: public class Math { public static int initData = 666; public static User user = new User(); public int compute() { int a = 1; int b = 2; int c = (a + b) * 10; return c; }

文档评论(0)

152****1430 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档