java对象的内存分配流程
了解对象的内存分配流程对常见内存溢出问题、jvm优化有很大作用。
内存分配原则
对象栈内分配
通常理解new对象都在堆中分配存储空间,但是当(通过逃逸分析 确定)对象仅在方法内使用而未被外部访问的时候,jvm会将对象分配到栈内。
逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数(或者return)传递到其他地方中。
对应参数:-XX:+DoEscapeAnalysis;JDK7之后默认开启逃逸分析
减量保证对象在Eden区分配
了解这一原则,必须先掌握gc流程:
- 对象首先分配到Edgn,存满之后触发minor gc,剩余仍然存活的对象会被存到from区;
- 下次Edgn存满之后再次出发minor gc,回收Edgn和from区,把剩余存活的对象转移到to 区(转移的原因参见之后的垃圾回收算法),然后form区和to区对换;
那么为什么尽量保证对象尽量存活在Edgn区呢?我们先来看看 Minor GC和Full GC 有什么不同呢?
Minor GC/Young GC:指发生新生代的的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。
Major GC/Full GC:一般会回收老年代 ,年轻代,方法区的垃圾,Major GC的速度一般会比Minor GC的慢10倍以上。
Eden与Survivor区默认8:1:1,但是jvm有默认参数 -XX:+UseAdaptiveSizePolicy(默认开启),会调节默认比例。
大对象直接进入老年代
大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。JVM参数 -XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下有效。
长期存活的对象将进入老年代
这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代
jvm采用分代收集思想来回收内存,因此每个对象必须有个年龄计数器。具体计数规则:
Edgn中对象在minor gc后存活,而且可以被survivor容纳的情况下,年龄+1;之后每次在survivor中经历一次minor gc,就会年龄+1;当年龄增加到一定程度就会移动到老年代中,具体通过参数 -XX:MaxTenuringThreshold配置
对象动态年龄判断
这个规则和上个规则一样:其实是希望那些可能是长期存活的对象,尽早进入老年代
具体实现:survivor区域中,当前存放的的对象占当前区域的50%(具体可以通过 -XX:TargetSurvivorRatio 指定),那么年龄大于等于这批对象中最大值的对象,可以全部移动到老年代中了。
老年代空间分配担保机制
目的:确保对象进入老年代之前有足够的空间;具体实现步骤如下:
年轻代每次minor gc之前JVM都会计算下老年代剩余可用空间
如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象)
就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了
如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次minor gc后进入老年代的对象的平均大小。
如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full gc,对老年代和年轻代一起回收一次垃圾,
如果回收完还是没有足够空间存放新的对象就会发生"OOM"
当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可用空间,那么也会触发full gc,full
gc完之后如果还是没有空间放minor gc之后的存活对象,则也会发生“OOM”
判断哪些对象已经死亡
引用计数法
可能存在相互引用的问题
可达性分析算法
将“GC Roots” 对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象
GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等
参考链接:
java对象的内存分配流程 - 前度刘郎 - 博客园
java对象的内存分配流程相关推荐
- 独占设备的分配与回收_灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?...
点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 作者 l Hollis JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆.栈. ...
- 原创 | 灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?
△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 222 篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) JVM内存结构,是很 ...
- 源码分析:Java对象的内存分配
Java对象的分配,根据其过程,将其分为快速分配和慢速分配两种形式,其中快速分配使用无锁的指针碰撞技术在新生代的Eden区上进行分配,而慢速分配根据堆的实现方式.GC的实现方式.代的实现方式不同而具有 ...
- java对象的内存分配
(1) 寄存器(register).这是最快的保存区域,这是主要由于它位于处理器内部.然而,寄存器的数量十分有限,所以寄存器是需要由编译器分配的.我们对此没有直接的控制权,也不可能在自己的程序里找到寄 ...
- jvm学习笔记(3)——java对象的内存分配和对象的回收(GC)
引言: 之前的文章已经提过,java对象实例是存放在堆上的,至于是在伊甸区.存活区还是老年区,这些都是从对象回收(GC)角度来进行的逻辑划分.所以我们先说对象的回收(GC),然后再依据GC的策略来说明 ...
- java对象的内存分配_java对象在内存的分配问题
今天看到一个不错的PPT:Build Memory-efficient Java Applications,开篇便提出了一个问题,在Hotspot JVM中,32位机器下,Integer对象的大小是i ...
- JVM-剖析对象内存分配流程
文章目录 Pre 对象分配流程总览 流程分解 栈上分配对象 (逃逸分析) Eden区分配对象 -XX:+UseAdaptiveSizePolicy 默认开启 Eden区域分配对象Demo 大对象直接进 ...
- 对象创建方法,对象的内存分配,对象的访问定位
对象创建方法: JVM遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.连接和初始化过. 如果没有,那必须先执行相应的类的加 ...
- Java 对象占用内存大小
Java 对象 如果想要了解java对象在内存中的大小,必须先要了解java对象的结构. HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instan ...
最新文章
- java soa例子_哪位大牛能举个实例讲下SOA与传统架构的区别?
- C++源码的调用图生成
- linux脚本获取usb设备,Linux基于USB端口执行脚本
- mysql 实例复制_MySQL 复制详解及简单实例
- linux内核的队列实现移植
- 利用HTML5开发Android笔记(中篇)
- Troubleshoot: R.Layout.Main cannot be resolved
- 为何要学习 Linux?
- JXNU Linux 学习通单元测试题 和 答案
- 最经典的人生定律、法则、效应总结
- 无法加载计算机管理,电脑中无法打开Internet选项中的管理加载项如何解决
- 记:疯狂的程序员 (连续n天写n个代码)
- 格拉姆角场GAF将时序数据转换为图像并应用于故障诊断
- 【工作笔记】004 tapestry框架
- 游戏环境公示及处罚名单9月18日
- 数据结构-二叉树-详解
- 机器人导航技术的研究现状和发展趋势
- 入侵必读:网警如何找到你
- 俞敏洪励志演讲稿【三】
- Appium基础篇15-模拟手指点击tap方法