空间分配

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

大多数情况下,对象在新生代中 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,一经查实,立即删除!

相关文章

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

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

软件测试基础知识

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

Jmeter-基础篇

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

shell一文入门通

简单来说“Shell编程就是对一堆Linux命令的逻辑化处理”。 W3Cschool 上的一篇文章是这样介绍 Shell的 hello world 学习任何一门编程语言第一件事就是输出HelloWord了!下面我会从新建文件到shell代码编写来说下Shell 编程如何输出Hello World。 (1)新建一个文件…

RPC编程

图 3 说明在客户机和服务器之间完成 RPC 涉及的步骤。 图 3. 在客户机和服务器之间完成 RPC 涉及的步骤服务器 RPC 应用程序初始化期间它会向 RPC 运行时库注册接口。需要注册接口是因为,客户机在向服务器发出远程过程调用时,要检查它是否与服务器兼容。…

synchronized使用和原理全解

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 修饰一个方法 被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 修饰一个静态的方法 其作用的范围是整个…

算法(11)-leetcode-explore-learn-数据结构-链表的经典问题

leetcode-explore-learn-数据结构-链表31.反转一个链表2.移除链表元素3.奇偶链表4.回文链表5.小结本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card/linked-l…

Linux线程池的设计

我设计这个线程池的初衷是为了与socket对接的。线程池的实现千变万化,我得这个并不一定是最好的,但却是否和我心目中需求模型的。现把部分设计思路和代码贴出,以期抛砖引玉。个人比较喜欢搞开源,所以大家如果觉得有什么需要改善的…

leetcode121买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 注意你不能在买入股票前卖出股票。 示例 1: 输入: [7,1,5,3,6,…

epoll的内核实现

epoll是由一组系统调用组成。 int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); select/poll的缺点在于&#xff1…

leetcode322 零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 示例 1: 输入: coins [1, 2, 5], amount 11 输出: 3 解释: 11 5 5 1 示例 2: 输入: coins [2],…

leetcode538 把二叉搜索树转换成累加树

给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。 对于每一个点来说,自己的父,和自己父的右子树都是大…

leetcode15 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a b c 0 ?找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。 例如, 给定数组 nums [-1, 0, 1,…

leetcode19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 示例: 给定一个链表: 1->2->3->4->5, 和 n 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5. 说明: 给定的 n 保证是有效…

python模块(5)-Matplotlib 简易使用教程

Matplotlib简易使用教程0.matplotlib的安装1.导入相关库2.画布初始化2.1 隐式创建2.2 显示创建2.3 设置画布大小2.4 plt.figure()常用参数3.plt. 能够绘制图像类型3.1等高线3.2 箭头arrow4.简单绘制小demodemo1.曲线图demo2-柱状、饼状、曲线子图5.plt.plot()--设置曲线颜色,粗…

leetcode20 有效的括号

给定一个只包括 (,),{,},[,] 的字符串,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。 示…

leetcode1 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums [2, 7, 11, 15], t…

leetcode3 无重复字符最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符…

Linux(6)-命令行的使用,history,shell脚本

命令行的使用,shell脚本1.终端shell,man1.1 Ctrlr--匹配查找历史命令1.2 history [n] --列出历史命令1.3!--执行历史命令2.shell 编程2.1 shell脚本2.2 注释2.3 指明所用的shell2.4 支持函数2.5 使用变量2.6 解析命令行参数2.7 if, for, case, while2.8 shell脚本中…

程序以及论文

本人长期承接大学计算机专业的毕业设计和论文的编写。 主要开发语言C,C (windows或linux平台皆可),php,c#,VC 。 课题内容可以是 管理系统,可以是 网站设计开发 可以是 网络聊天 可以是 应用…