JVM(十一):内存分配

在前面的章节中,我们花了大量的篇幅去介绍 JVM 内的内存布局、对象在内存中的状态、垃圾回收的算法和具体实现等。今天让我们探讨一下对象是如何分配内存的。

堆内存划分

前面说过,从内存回收的角度来看,堆被分为以下几个部分:

开始创建的对象大多都会直接分配到新生代一块区域中,只有大对象和经过多次 GC 后依然存活的对象会放置在老年代中。

那么一个对象在被创建出来后,何时存在与哪个内存区域中呢,其具体的分配策略又是什么呢?下面就让我们一起来看一下几个具体的内存分配策略,了解一个对象在产生后该何去何从。

对象优先在Eden分配

首先,我们先复习一下 GC 的两种分类:

Minor GC,又叫新生代GC:发生在新生代的 GC,由于大多数 Java 对象都是朝生夕死的,因此发生这种 GC 十分的频繁,回收速度一般也会比较快。
Full/Major GC,又叫老年代GC:发生在老年代的 GC,一般会比 Minor GC 慢 10倍以上。

在大多数情况下,对象优先在 Eden 区进行分配。当 Eden 区空间不足时,将会发起一次 Minor GC。

大对象直接进入老年代

首先,我们来看一下什么是大对象,其一般是指需要大量连续内存空间的 Java 对象。最典型的就是很长的字符串和数组。对虚拟机来说大对象是很难处理的对象,因为虚拟机需要一块连续的大空间进行分配,不过更加难以处理的是朝生夕死的大对象,经常出现的大对象,导致频繁地触发 GC 来空出大量连续空间来安置它们,影响了性能。因此,这种情况也警醒开发人员在开发过程中要尽量避免这种问题。

长期存活对象进入老年代

因为 Java 的垃圾回收是采取的分代收集思想。因此新生代的对象也有一定的途径进入老年代,对应的就是存活时间,为了定位每个对象的存活时间,JVM 给每个对象定义了一个对象年龄计数器,当对象在 Survivor 区每熬过一次 Minor GC,对象的年龄就 +1,当对象的年龄满足一定的条件(默认为15),就将其晋升到老年代。

前面这种晋升老年代的条件显得比较的死板。因此在 JVM 中还有一种灵活的方式:如果在 Survivor 空间中相同年龄的所有对象综合大于 Survivor 空间的一半,那么年龄大于等于该阀值的对象就可以直接进入老年代,而无须等到满足要求的年龄。

空间分配担保

上面说过,在新生代经过 Minor GC 存活的对象,满足一定的条件会进入老年代 , 因此就需要保证老年代有充足的空间能够分配 。这种担保方式让 JVM 在进行 Full GC 的时候,可以进行大胆的操作 (因为 Full GC 十分的耗时,影响性能, 因此在 Minor GC 前需要进行一定的判断)。

上图就是空间分配担保的流程,此种方式可以避免 Full GC 过于频繁,影响性能。

总结

在本文中,我们详细讲述了对象内存分配的一些通用策略。了解这些策略可以让我们明白 JVM 分配对象的逻辑,写出更加高效健壮的代码。

文章在公众号「iceWang」第一手更新,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

本系列文章主要借鉴自《深入分析 JavaWeb 技术内幕》和《深入理解 Java 虚拟机-JVM 高级特性与最佳实践》。

JVM(十一):内存分配的更多相关文章

  1. JVM初探- 内存分配、GC原理与垃圾收集器

    JVM初探- 内存分配.GC原理与垃圾收集器 标签 : JVM JVM内存的分配与回收大致可分为如下4个步骤: 何时分配 -> 怎样分配 -> 何时回收 -> 怎样回收. 除了在概念 ...

  2. JVM总结(二):JVM的内存分配策略

    这节我们总结一下JVM中的内存分配策略.目录如下: 内存分配策略 对象优先在新生代Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保 内存分配策略 Java ...

  3. JVM的内存分配垃圾回收策略

    之前看过<深入了解Java虚拟机>感觉容易忘,今天写一篇博客加深一下印象. JVM的内存分配和垃圾回收(GC)主要发生在Java堆中.而Java堆根据对象的存活时间可以分为新生代和老年代, ...

  4. 一夜搞懂 | JVM GC&内存分配

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习GC&内存分配? 时代发展到现在,如今的内存动态分配与内存回收技术已经相当成 ...

  5. jvm的内存分配总结

    最近看了周志明版本的<深入理解Java虚拟机>第一版和第二版,写的很好,收获很多,此处总结一下.   jvm中内存划分:   如上图,一共分为五块,其中: 线程共享区域为: 1.java堆 ...

  6. JVM的内存分配与垃圾回收策略

    自动内存管理机制主要解决了两个问题:给对象分配内存以及回收分配给对象的内存. >>垃圾回收的区域 前面的笔记中整理过虚拟机运行数据区,再看一下这个区域: 注意在这个Runtime Data ...

  7. 浅谈JVM与内存分配

    一.程序内存分配 初始内存分配 当一个程序准备运行时,它首先向java虚拟机要内存,但是java虚拟机本身没有权限,它只能向操作系统申请内存,此时java虚拟机会拥有一个初始内存, 此处额外说明一下e ...

  8. jvm对象内存分配

    一.jvm简单结构图 1.jvm内存对象分配整体流程: 1.类加载子系统和方法区 类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间.除了类的信息外, ...

  9. 【面试必备】小伙伴栽在了JVM的内存分配策略。。。

    周末有小伙伴留言说上周面试时被问到内存分配策略的问题,但回答的不够理想,小伙伴说之前公号里看过这一块的文章的,当时看时很清楚,也知道各个策略是干嘛的,但面试时脑子里清楚,心里很明白,但嘴里就是说不清楚 ...

  10. 认识JVM的内存分配

    当我们在JVM中运行一段程序代码,JVM初始运行的时候都会分配好Method Area(方法区)和Heap(堆),而JVM每遇到一个线程,就为其分配一个Program Counter Register ...

随机推荐

  1. 为使用mock方案测试,而重构代码的小小案例

    import com.sun.deploy.config.DefaultConfig; import javax.security.auth.login.Configuration; import j ...

  2. 数组指针&&指针数组

    数组指针: 定义 int (*p)[n];      占用内存中一个指针的存储空间 ()优先级高,首先说明p是一个指针,指向一个int型的一维数组,故名数组(的)指针.指向的一维数组的长度是n,也可以 ...

  3. CSharp初级篇 1-4 this、索引器、静态、常量以及只读

    .NET Core CSharp初级篇 1-4 本节内容为this.索引器.静态.常量以及只读 简介 在之前的课程中,我们谈论过了静态函数和字段的一小部分知识,本节内容中,我们将详细的讲解关于对象操作 ...

  4. UVA1103 古代象形符号 Ancient Messages 题解

    题目链接: https://www.luogu.org/problemnew/show/UVA1103 题目分析: 我们可以先进行矩阵的还原 for(int k=1;k<=4;k++) { a[ ...

  5. [HAOI2006]聪明的猴子 题解

    题意: 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,部分植物的树冠露在水面上.猴子不会游泳,但跳跃能力比较强,它们仍然可以在 ...

  6. 个人永久性免费-Excel催化剂功能第35波-Excel版最全单位换算,从此不用到处百度找答案

    全球化的今天,相信我们经常可以有机会接触到外国的产品,同时我们也有许多产品出口到外国,国与国之间的度量单位不一,经常需要做一些转换运算,一般网页提供这样的转换,但没有什么比在Excel上计算来得更为方 ...

  7. F#周报2019年第29期

    新闻 ML.NET 1.2发布,包含Model Builder升级 NuGet.org上现在显示GitHub的使用情况 微基准测试设计准则 为线程添加mono.wasm支持 Haskell--经验总结 ...

  8. git rebase 理解

    摘录自:https://blog.csdn.net/wangnan9279/article/details/79287631

  9. SQLyog连接数据库报错plugin caching_sha2_password could not be loaded

    摘录自: https://blog.csdn.net/lihua5419/article/details/80394716

  10. hdu多校第八场Parentheses Matrix

    #include<bits/stdc++.h> using namespace std; ][]; int main() { int t; scanf("%d",&am ...