(四)-对象内存的分配策略

简介: Java所承诺的自动内存管理主要是:给对象分配内存,回收分配给对象的内存.在Java虚拟机的五块内存空间中,程序计数器、Java虚拟机栈、本地方法栈内存的分配和回收都具有确定性,一般在编译阶段就能确定需要分配的内存大小,并且由于都是线程私有,因此它们的内存空间都随着线程的创建而创建,线程的结束而回收.也就是这三个区域的内存分配和回收都具有确定性,垃圾回收器不需要在这里花费太大的精力.而Java虚拟机中的方法区因为是用来存储类信息、常量、静态变量,这些数据的变动性较小,因此不是Java内存管理重点需要关注的区域.而对于堆,所有线程共享,所有的对象都需要在堆中创建和回收.虽然每个对象的

1 对象优先在Eden区中分配

目前主流的垃圾收集器都会采用分代回收算法,因此需要将堆内存分为新生代和老年代.


在新生代中为了防止内存碎片,垃圾收集器一般都选用”复制”算法.因此,堆内存的新生代被进一步分为:Eden区+Survior1区+Survior2区.


每次创建对象时,首先会在Eden区中分配.

若Eden区已满,则在Survior1区中分配.

若Eden区+Survior1区剩余内存太少,导致对象无法放入该区域时,就会启用”分配担保”,将当前Eden区+Survior1区中的对象转移到老年代中,然后再将新对象存入Eden区.


2 大对象直接进入老年代

所谓”大对象”就是指一个占用大量连续内存空间的对象,如很长的字符串及数组.


当发现一个大对象在Eden区+Survior1区中存不下的时候就需要分配担保机制把当前Eden区+Survior1区的所有对象都复制到老年代中去.

一个大对象能够存入Eden区+Survior1区的概率比较小,发生分配担保的概率比较大,而分配担保需要涉及到大量的复制,就会造成效率低下.

因此,对于大对象我们直接把他放到老年代中去,从而就能避免大量的复制操作.

那么,什么样的对象才是”大对象”呢?


  • -XX:PretrnureSizeThreshold参数
    该参数用于设置大小超过该参数的对象被认为是”大对象”,直接分配在老年代.
    注意:该参数只对Serial和ParNew收集器有效.

3 生命周期较长的对象进入老年代

老年代用于存储生命周期较长的对象,那么我们如何判断一个对象的年龄呢?


新生代中的每个对象都有一个年龄计数器,当新生代发生一次MinorGC后,存活下来的被移动到Survivor空间的对象的年龄就加一,在Survivor区每熬过一次MinorGC,年龄就加一,当年龄超过一定值(默认15)时,就将该对象转移到老年代中.


  • -XXMaxTenuringThreshold参数
    设置该参数后,只要超过该参数的新生代对象都会被转移到老年代中.

4 对象年龄的动态判定

在Survivor空间中,如果年龄相同的对象的内存大小总和超过了Survivor空间的一半,那么所有年龄相同的对象和超过该年龄的对象都会被转移到老年代中.无须等到MaxTenuringThreshold要求的年龄.

5 “分配担保”策略详解

在发生MinorGC前,JVM首先会检查老年代中最大可用的的连续空间是否大于新生代中所有对象的大小.若此条件


  • 成立,那么MinorGC可以确保安全进行.
  • 不成立,JVM会查看HandlePromotionFailure设置值是否允许担保失败.若允许,继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小
  • 若大于,将尝试一次MinorGC,虽然此次MinorGC是有风险的.
  • 若小于或HandlePromotionFailure设置不允许冒险,则进行一次FullGC.通过清除老年代中废弃数据来扩大老年代空闲空间,以便给新生代作担保.

注意:

1. 分配担保是老年代为新生代作担保.

2. 新生代中使用”复制”算法实现垃圾回收,老年代中使用’标记-清除”或”标记-整理”算法实现垃圾回收,只有使用”复制”算法的区域才需要分配担保,因此新生代需要分配担保,而老年代不需要分配担保.


目录
相关文章
|
9天前
|
存储 缓存 JavaScript
JavaScript内存泄漏通常发生在对象不再需要时
【6月更文挑战第16天】JavaScript内存泄漏常由闭包引起,当不再需要的对象仍被闭包引用时,垃圾回收机制无法清理。例如,创建返回大型对象引用的闭包函数会导致内存泄漏。避免泄漏需及时解除引用,清除事件监听器,利用WeakMap或WeakSet,以及定期清理缓存。使用性能分析工具监控内存使用也有助于检测和解决问题。
23 8
|
5天前
|
算法 Java 程序员
Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A->B->A)可导致内存泄漏。
【6月更文挑战第20天】Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A->B->A)可导致内存泄漏。为解决此问题,Python使用`gc`模块检测并清理循环引用,可通过`gc.collect()`手动回收。此外,Python结合标记清除和分代回收策略,针对不同生命周期的对象优化垃圾回收效率,确保内存有效释放。
13 3
|
7天前
|
算法 Java
Java垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一种自动内存管理机制,用于在运行时自动回收不再使用的对象所占的内存空间
【6月更文挑战第18天】Java的GC自动回收内存,包括标记清除(产生碎片)、复制(效率低)、标记整理(兼顾连续性与效率)和分代收集(区分新生代和老年代,用不同算法优化)等策略。现代JVM通常采用分代收集,以平衡性能和内存利用率。
33 3
|
13天前
|
算法 安全 Java
JVM系列4-垃圾收集器与内存分配策略(二)
JVM系列4-垃圾收集器与内存分配策略(二)
20 0
JVM系列4-垃圾收集器与内存分配策略(二)
|
25天前
|
安全 网络安全 量子技术
网络安全与信息安全:漏洞、加密技术与安全意识的探索安卓应用开发中的内存管理策略
【5月更文挑战第31天】随着互联网的普及,网络安全问题日益严重。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的问题,以期提高公众对网络安全的认识和防范能力。
|
26天前
|
C语言
如何建立内存的动态分配
如何建立内存的动态分配
20 2
|
26天前
|
C语言
内存的动态分配
内存的动态分配
19 2
|
4天前
|
算法 调度 内存技术
操作系统中的内存管理优化策略
在数字时代的浪潮中,操作系统的高效运行成为了技术发展的关键。本文深入探讨了操作系统中内存管理的优化策略,旨在通过先进的技术和方法提高系统性能。文章首先概述了内存管理的基本概念和重要性,随后详细介绍了几种主要的内存优化技术,包括分页机制、虚拟内存以及内存泄漏检测等。最后,文章分析了这些优化措施对提升系统性能的实际影响,并展望了内存管理技术的未来发展方向。
15 0
|
13天前
|
存储 监控 算法
JVM系列4-垃圾收集器与内存分配策略(一)
JVM系列4-垃圾收集器与内存分配策略(一)
24 0
|
26天前
|
缓存 监控 Android开发
Android 开发中的内存优化策略
【5月更文挑战第30天】在移动应用的开发过程中,性能和用户体验始终是核心关注点。对于基于Android平台的应用程序,有效的内存管理是确保流畅运行和优异性能的关键因素之一。本文将深入探讨Android开发中常见的内存问题,并提出一系列实用的内存优化策略。我们将从内存泄漏的识别与防止开始,到合理使用内存缓存技巧,以及高效的数据结构选择等方面进行详细阐述。通过这些策略的实施,开发者可以显著减少应用的内存占用,提升应用的稳定性和响应速度,进而改善最终用户的体验。