内存分配策略与回收策略

内存分配策略与回收策略

给对象分配内存以及回收给对象分配的内存。对象的内存分配绝大部分主要是在Java堆上,有一部分特殊的就是JIT编译器,经过JIT编译后被拆散为标量类型并间接地在栈上分配内存。

对象主要分配集中在新生代的Eden区,如果启动了本地线程分配缓冲,按照线程优先在TLAB上分配。少数分配在老年代,分配在哪里取决于当前使用的垃圾回收器组合和虚拟机中相关内存参数的设定。

  • 新生代GC :Minor GC,发生在新生代的垃圾回收动作,非常频繁,速度很快。
  • 老年代GC :Major GC/Full GC,指发生在老年代,发生了Major GC,经常会出现至少一次的Minor GC,但不是绝对的,在parallel scavenge收集器的收集策略里就有直接进行Major gc的策略选择过程。Major GC的速度比Minor GC慢10倍以上。

1、对象优先在新生代的Eden区分配

一般情况下,新对象优先在新生代的Eden区分配,当eden区没有足够的内存空间时,虚拟机将发起一次Minor GC.

2、大对象直接进入老年代

大对象指,需要大量连续内存空间的Java 对象。典型的就是很长的字符串以及数组。

3、长期存活的对象将进入老年代

由于虚拟机采用了分代思想管理内存,那么内存回收时就必须能识别那些对象应放在新生代,那些对象放在老年代。为了做到这一点,Java虚拟机给每个对象定义了一个对象年龄计数器(Age)。

如果对象在Eden区出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且年龄对象设为1.对象在survivor区中每熬过一次minor GC,年龄对象就加1;当他的年龄增加到一定程度,默认为15岁,就将晋升到老年代中。对象晋升老年代的阀值可以通过-XX:MaxTenuringThreshold设置。

4、动态对象年龄判定

为了更好的适应不同的内存状况,虚拟机并不是永远的要求对象的年龄必须到达阀值才能进入老年代。

如果 在survivor空间中相同年龄所有对象大小的总和大于survivor空间的一半,那么这些对象就直接进入老年代。

5、空间分配担保

在发生minor gc之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果条件成立,那么minor gc 可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。

如果允许,那么继续查看老年代的最大可用的连续内存是否大于历次晋升到老年代对象的平均大小,

如果大于,那么尝试进行一次minor gc,尽管是有风险的,

如果小于或者不允许,那么直接进行一次Full GC.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 21:17:01

内存分配策略与回收策略的相关文章

Node.js的内存分配和垃圾回收

简单介绍Node.js的内存分配和垃圾回收 内存分配 Node.js是一个由JavaScript V8引擎控制的C++程序V8的内存管理模式一个运行的程序通常是通过在内存中分配一部分空间来表示的.这部分空间被称为驻留集(Resident Set).V8的内存管理模式有点类似于Java虚拟机(JVM),它会将内存进行分段: 代码 Code:实际被执行的代码 栈 Stack:包括所有的携带指针引用堆上对象的值类型(原始类型,例如整型和布尔),以及定义程序控制流的指针. 堆 Heap:用于保存引用类型

jvm的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集(转)

深入Java虚拟机:JVM中的Stack和Heap(转自:http://www.cnblogs.com/laoyangHJ/archive/2011/08/17/gc-Stack.html) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题. 一般,JVM的内存分为两部分:Stack和Heap. Stack(栈)是JVM的内存指令区.Stack管理很简单,push

Java内存分配与垃圾回收

1.JVM管理的内存包含下图所示的几个运行时数据区域,其中方法区和堆为线程共享的数据区域,程序计数器,虚拟机栈以及本地方法栈为线程私有的数据区域. 程序计数器:可以看做是当前线程所执行的字节码的行号指示器,告诉字节码解释器该读取哪条指令 虚拟机栈:生命周期和线程相同,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法从调用到完成的过程就对应了一个栈帧在虚拟机中入栈到出栈的过程.栈中存放了编译器可知的各种基本数据类型和对象引用. 本地方法栈:与

Java中的内存分配与垃圾回收

一.内存分配 Java程序运行时的内存分配,按照JVM规范,包括以下几个区域:程序计数器.虚拟机栈.本地方法栈.方法区.堆.其中,前三个是线程私有的,与线程生命周期相同,线程退出内存自动回收:后两者是所有线程共享内存的,只在垃圾回收机制被触发时,被动回收. * 程序计数器,内存区域极小,是当前线程的字节码执行行号指示器: * 虚拟机栈.本地方法栈,即平时所说的“栈”,是虚拟机用来执行方法(包括Java.非Java方法)时,使用的临时内存空间,用来存储当前方法.局部变量等,全部基本类型变量,以及类

jvm 深入理解自动内存分配与垃圾回收

要想了解jvm自动内存分配,首先必须了解jvm的运行时数据区域,否则如何知道在哪里进行自动内存分配,如何进行内存分配,回收哪里的垃圾对象? jvm运行时数据区:程序计数器,虚拟机栈,本地方法栈,方法区,堆 程序计数器:由于程序指令是一条一条顺序执行,一条执行完之后必须知道下一条该执行那条指令,那么程序计数器就是来记录下一条指令的地址,如果调用本地方法,则程序计数器记录空值,还有由于java线程由cpu调度并发执行,所以程序计数器也有助于线程状态的恢复,程序计数器如果线程共享,在频繁的线程调度下保

Java 内存分配及垃圾回收机制初探

一.运行时内存分配 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁. 线程私有区域(生命周期与线程相同) a)  虚拟机栈 虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame[1])用于存储局部变量表. 操作数栈. 动态链接. 方法出口等信息. 每一个方法从调用直至执行完成的

Redis过期键删除策略及回收策略

一.前言 Redis的所有键都可以设置过期策略,Redis的每个设置了过期时间的key都会被放在一个独立的字典中,用于遍历删除. 二.过期策略 1.先区分两个概念,被动删除与主动删除 1)被动删除:key再被操作时,Redis主动检查key是否过期,过期则删除:   优劣:对CPU友好,只有CPU在被操作时删除,不浪费CPU时间:对内存不友好,如果同时大量key过期,这些key在被使用前不会被删除造成资源浪费: 2)主动删除:Redis会定期随机扫描一批设置了过期时间的key并进行删除处理:当已

JVM学习之内存分配和垃圾回收

阅读书籍:Java虚拟机精讲(仅个人阅读后总结) 根据受访权限可分为:线程共享内存区和线程私有区 线程共享区: 1.java堆区:储存对象实例: 2.方法区:储存 运行时常量池.字段和数据.构造函数和普通方法的字节码内容以及类.实例.接口初始化需要用到的特殊方法等数据: 3.运行时常量池: 线程私有内存区: 1.PC寄存器:如果当前线程所执行的方法是一个java方法,那么PC寄存器就会存储正在执行的字节码指令地址,反之如果是native方法,这是PC寄存器的值为空(undefined): 2.j

垃圾收集器与内存分配策略-垃圾收集器

(A).图中展示了7种不同分代的收集器: Serial.ParNew.Parallel Scavenge.Serial Old.Parallel Old.CMS.G1: (B).而它们所处区域,则表明其是属于新生代收集器还是老年代收集器:       新生代收集器:Serial.ParNew.Parallel Scavenge:       老年代收集器:Serial Old.Parallel Old.CMS:       整堆收集器:G1: (C).两个收集器间有连线,表明它们可以搭配使用: