空间分配

目前主流的垃圾收集器都会采用分代回收算法,因此需要将堆内存分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

大多数情况下,对象在新生代中 eden 区分配。当 eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC.下面我们来进行实际测试以下。

在测试之前我们先来看看 Minor GC 和 Full GC 有什么不同呢?

  • 新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
  • 老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。

测试:

public class GCTest {public static void main(String[] args) {byte[] allocation1, allocation2;allocation1 = new byte[30900*1024];//allocation2 = new byte[900*1024];}
}

通过以下方式运行: 

添加的参数:-XX:+PrintGCDetails 

运行结果 (红色字体描述有误,应该是对应于 JDK1.7 的永久代):

从上图我们可以看出 eden 区内存几乎已经被分配完全(即使程序什么也不做,新生代也会使用 2000 多 k 内存)。假如我们再为 allocation2 分配内存会出现什么情况呢?

allocation2 = new byte[900*1024];

简单解释一下为什么会出现这种情况: 因为给 allocation2 分配内存的时候 eden 区内存几乎已经被分配完了,我们刚刚讲了当 Eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC.GC 期间虚拟机又发现 allocation1 无法存入 Survivor 空间,所以只好通过 分配担保机制 把新生代的对象提前转移到老年代中去,老年代上的空间足够存放 allocation1,所以不会出现 Full GC。执行 Minor GC 后,后面分配的对象如果能够存在 eden 区的话,还是会在 eden 区分配内存。可以执行如下代码验证:

public class GCTest {public static void main(String[] args) {byte[] allocation1, allocation2,allocation3,allocation4,allocation5;allocation1 = new byte[32000*1024];allocation2 = new byte[1000*1024];allocation3 = new byte[1000*1024];allocation4 = new byte[1000*1024];allocation5 = new byte[1000*1024];}
}

大对象直接进入老年代

大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。

为什么要这样呢?

为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率。

private static final int _1MB = 1024 * 1024;/*** VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8* -XX:PretenureSizeThreshold=3145728*/
public static void testPretenureSizeThreshold() {byte[] allocation;allocation = new byte[4 * _1MB];  //直接分配在老年代中
}

执行后我们发现,新生代几乎没有被使用,老年代被使用了40%,因为超过一定数值的对象就会直接被分配到老年代。

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

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

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

private static final int _1MB = 1024 * 1024;/*** VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1* -XX:+PrintTenuringDistribution*/
@SuppressWarnings("unused")
public static void testTenuringThreshold() {byte[] allocation1, allocation2, allocation3;allocation1 = new byte[_1MB / 4];  // 什么时候进入老年代决定于XX:MaxTenuringThreshold设置allocation2 = new byte[4 * _1MB];allocation3 = new byte[4 * _1MB];allocation3 = null;allocation3 = new byte[4 * _1MB];
}

年龄判定

为了更好的适应不同程序的内存情况,虚拟机不是永远要求对象年龄必须达到了某个值才能进入老年代,如果 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需达到要求的年龄。

分配担保

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于uint32_t uint8_t uint64_t 的问题

怎么又是u又是_t的?u代表的是unsigned相信大家都知道,那么_t又是什么呢?我认为它就是一个结构的标注,可以理解为type/typedef的缩写,表示它是通过typedef定义的,而不是其它数据类型。 uint8_t,uint16_t,uint32_t等都不是什么新的数据类型,它们只是使用typedef给类型起…

学点数学(4)-协方差矩阵

协方差矩阵协方差矩阵(从随机变量讲起)随机变量x:表示随机试验各种结果的 实值 单值函数,就是说随机变量x是一个函数映射,其取值为标量。随机变量有离散型和连续型,离散型:抛10次硬币&#xff…

RedLock

概念 Redis 官方站这篇文章提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock,此种方式比原先的单节点的方法更安全。它可以保证以下特性: 安全特性:互斥访问,即永远只有一个 client 能拿到锁避免死锁:最终…

GCC中常用的优化的参数

-pipe 的作用: 使用管道代替编译中临时文件, -pipe 加速编译 gcc -pipe foo.c -o foo 加速 在将源代码变成可执行文件的过程中,需要经过许多中间步骤,包含预处理、编译、汇编和连接。这些过程实际上是由不同的程序负责完成的。大多数情况下 GCC 可以为 …

Linux与时间相关的结构体及相关用法

1. Linux下与时间有关的结构体 struct timeval { int tv_sec; int tv_usec; }; 其中tv_sec是由凌晨开始算起的秒数,tv_usec则是微秒(10E-6 second)。 struct timezone { …

算法(3)-数据结构-数组和字符串

leetcode-explore-learn-数据结构-数据结构-数组和字符串1. 一维数组1.0 概况1.1 寻找数组的中心索引1.2 搜索插入位置1.3 合并区间1.4 至少是其他数字两倍大的最大数1.5 加一2. 二维数组2.1旋转矩阵本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处…

redis的入门/原理/实战大总结

入门 Redis是一款基于键值对的NoSQL数据库,它的值支持多种数据结构: 字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。 • Redis将所有的数据都存放在内存中,所以它的读写性能十分惊人,用作数…

创建与打开IPC通道的POSIX和SYSTEM V方法

先说POSIX的吧: mq_open,sem_open,shm_open着三个函数用于创建或者打开一个IPC通道。 由此可见,消息队列的读写权限是任意的,然而信号灯就没有,…

算法(4)-leetcode-explore-learn-数据结构-数组2

leetcode-explore-learn-数据结构-数组21.简述2.例题2.1 二维数组的对角线遍历2.2 螺旋遍历2.3 杨辉三角本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card/ar…

软件测试基础知识

第一章 1.1 软件测试背景知识和发展史 互联网公司职位架构:产品 运营 技术 市场 行政软件测试:使用人工或自动化手段,来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别&#…

key_t IPC键和ftok函数详解和剖析

统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。 ftok原型如下: key_t ftok( char * fname, int id ) fname就时你指定的文件名(该文件必须是存在而且可以访问的),id是子…

算法(5)-leetcode-explore-learn-数据结构-字符串

leetcode-explore-learn-数据结构-数组3-字符串1.简述2.例题2.1 二进制求和2.2实现strStr()2.3最长公共前缀本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card…

ipcs命令查看管道,消息队列,共享内存

修改消息队列大小: root:用户: /etc/sysctl.conf kernel.msgmnb 4203520 #kernel.msgmnb 3520 kernel.msgmni 2878 保存后需要执行 sysctl -p ,然后重建所有消息队列 ipcs -q : 显示所有的消息队列 ipcs -qt : 显示消息队列的创建时…

Jmeter-基础篇

常用压力测试工具对比 1、loadrunner 性能稳定,压测结果及细粒度大,可以自定义脚本进行压测,但是太过于重大,功能比较繁多 2、apache ab(单接口压测最方便) 模拟多线程并发请求,ab命令对发出负载的计算机…

消息队列接口API(posix 接口和 system v接口)

消息队列 posix API消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点。信号这种通信方式更像\"即时\"的通信方式,它要求接受信号的进程在某个时间范围内对信号做出反应,因此该信号最多在接受信号进程的生命…

算法(6)-leetcode-explore-learn-数据结构-数组字符串的双指针技巧

leetcode-explore-learn-数据结构-数组4-双指针技巧1.双指针技巧--适用情形11.1概述1.2 例题1.2.1 反转字符串1.2.2数组拆分1.2.3 两数之和22双指针技巧-适用情形22.1概述2.2例题2.2.1 移除元素2.2.2 最大连续1的个数2.2.3长度最小的子数组本系列博文为leetcode-explore-learn子…

POSIX和SYSTEM的消息队列应该注意的问题

首先看看POSIX的代码&#xff1a; 1.posix_mq_server.c #include <mqueue.h> #include <sys/stat.h> #include <string.h> #include <stdio.h> #define MQ_FILE "/mq_test" #define BUF_LEN 128 int main() { mqd_t mqd; char b…

算法(7)-leetcode-explore-learn-数据结构-数组-小结

leetcode-explore-learn-数据结构-数组5-小结1.概述2.例题2.1旋转数组2.2 杨辉三角22.3翻转字符串里的单词2.4反转字符串中的单词32.5 删除排序数组中的重复项2.6 移动零本系列博文为leetcode-explore-learn子栏目学习笔记&#xff0c;如有不详之处&#xff0c;请参考leetcode官…

fcntl函数详解

功能描述&#xff1a;根据文件描述词来操作文件的特性。 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock); [描述] fcntl()针对(文件)描述符提供控…

使用nohup让程序永远后台运行

使用nohup让程序永远后台运行 Unix/Linux下一般比如想让某个程序在后台运行&#xff0c;很多都是使用 & 在程序结尾来让程序自动运行。比如我们要运行mysql在后台&#xff1a; /usr/local/mysql/bin/mysqld_safe --usermysql &但是加入我们很多程序并不象mysqld一样做…