实战:内存分配与回收策略

​ Java技术体系的自动内存管理,最核心的目标就是自动化的解决两个问题:内存分配内存回收,在之前我们讲的都是内存回收,现在我们来看一下内存分配的细节,这里我是使用JDK1.8,HotSpot虚拟机,使用的ParallelGC

这里有一个很细的点:《深入理解Java虚拟机》使用的Serial+Serial Old客户端默认收集器组合下的内存分配和回收策略,但咱们的jvm是服务端的,说是只能在32位机jvm.cfg修改文件使用客户端,所以当我运行书上第一个代码块儿时,就发现结果与书上不对,想不出原因,所以如果你也是ParallelGC,那么书本上本章上许多代码结果都是不一样的。一些VM参数也是无法使用的或者没有效果的。

  1. java -XX:+PrintCommandLineFlags -version 输出JVM默认垃圾收集器,第四行的UseParallelGC和最后一行的Server VM
[root@jeespring ~]# java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=132500800 -XX:MaxHeapSize=2120012800 -XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode
  1. /usr/libexec/java_home -V 这个是在mac上找我的jvm在哪
  2. find . -name “jvm.cfg” 如果你找不到jvm.cfg,通过它去找,表示在当前路径下找
  3. JVM的Server端和Client端区别网上有详细介绍,通俗的讲就是Client端轻量快速,Server端重量性能好(默认)。

对象的内存分配从概念上来讲,应该是在堆上分配,不过实际中也可能通过即时编译后拆分为标量间接存储在栈上(这个在我之前写的逃逸分析中有说明)

### 对象优先在Eden分配(书本原题目)
  1. Serial:当大对象要分配内存时,发现Eden区已经满了,而且Survivor区也不够,会将Eden区原来的对象直接放入老年代,再把新的对象放入Eden区。
  2. Parallel(我测试的):发现Eden区满了,Survivor区不够,会直接把大对象放到老年代,Eden区对象不变。读者可以自己再测试一遍
/*** 对象分配*/
public class no1 {private static final int _1MB  = 1024*1024;/*** VM: -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8  -XX:+PrintGCDetails* 堆空间分配20m,新生代10m,新生代中的Eden和Survivor为8:1:1* @param args*/public static void main(String[] args) {byte[] a1,a2,a3,a4;a1 = new byte[2*_1MB];a2 = new byte[2*_1MB];a3 = new byte[2*_1MB];/*** 上面已经创建了8m,相当于Eden区已经满了,现在我们再放一个4M的对象* Eden已经放不下了,会启动一次MinorGC,我们看一下会之前的对象和新来的对象如何分配* *  PSYoungGen      total 9216K, used 8001K*      eden space 8192K, 97% used*      from space 1024K, 0% used*  ParOldGen       total 10240K, used 4096K*/a4 = new byte[4*_1MB];}
}

大对象直接进入老年代

​ 我们知道一般对象不会直接到老年区,得现在Eden区和Survivor区熬几轮,但如果有大的对象已经在里面了,那么就很容易触犯minor GC,导致对象进行标记-复制,所以可以可以通过设置XX:PretenureSizeThreshold来指定超过多大的对象直接去了老年区(注意这个参数Parallel无法使用)

/*** 对象分配*/
public class no1 {private static final int _1MB  = 1024*1024;/*** VM:  -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8  -XX:+PrintGCDetails -XX:PretenureSizeThreshold=3145728* 堆空间分配20m,新生代10m,新生代中的Eden和Survivor为8:1:1* -XX:PretenureSizeThreshold 表示 需要分配的对象只要大于3M,就直接分配到老年区,注意:这个参数只能Serial使用,ParallelGC无法使用* @param args*/public static void main(String[] args) {byte[] a4;a4 = new byte[4*_1MB];}
}

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

​ 意思就是我们给每个对象定义一个对象年龄计数器,存储在对象头中,每经历一次Minor GC后存活,并可以存储到Survivor区时,年龄就+1,当长到系统-MaxTenuringThreshold设定值时(默认值15),就去老年代.

动态对象年龄判定

​ 这里就是说系统可以动态判断,如果每个对象都得等15轮minor GC,那就会导致频繁的GC,影响性能,如果Survivor区中对低于或者等于某个年龄的对象总和超过了Survivor空间的一半,那这个年龄及其以上的对象直接进入老年区。

空间分配担保

​ 我们在前面就提到,其实老年代就是新生代的担保人,如果新生代放不下的对象,我就把对象放到老年代。根据这第一点我们就可以推断出每次Minor GC前,虚拟机都应检查老年代最大的连续空间是否有足够的空间装下新生代所有对象,如果空间足够,那我们就放心的Minor GC,如果不够了,虚拟机去查看-XX:HandlePromotionFailur参数是否允许担保失败,如果允许,继续检查老年代之前进来对象的平均大小是否小于老年代最大连续空间(简单来说:通过以前来的,猜测后面来的应该差不多大),如果足够,进行Minor GC,虽然有风险,如果不够,或者是没有担保,则直接Full GC,这就很影响性能了。所以一般都会将-XX:HandlePromotionFailur打开,来避免频繁的FUll GC。这个参数在JDK6 Update24后就不再使用了。

​ 也就是现在只要老年代的连续空间大于新生代对象总大小或者以往对象的平均值大小,就会进行Minor GC,否则将进行Full GC。

总结

​ 垃圾收集器在许多场景都是影响系统停顿时间和吞吐能力的重要因素,虚拟机之所以提供各种不同的收集器和大量的调节参数就是因为各种有各种的适用场景,需要我们不断探索,不断组合。当然我们也需要知道每种收集器的特点以及范围。

实战:内存分配与回收策略相关推荐

  1. JVM3:实战:内存分配与回收策略

    实战:内存分配与回收策略 文章目录 实战:内存分配与回收策略 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保 对象优先在Eden分配 试分配三 ...

  2. JVM:内存分配与回收策略?Full GC 的触发条件?StopTheWorld ?

    内存分配与回收策略 Minor GC 和 Full GC Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快. Full GC: ...

  3. 【拥抱大厂系列】百度面试官问过的 “JVM内存分配与回收策略原理”,我用这篇文章搞定了

    点个赞,看一看,好习惯!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了3个月总结的一线大厂Java面试总结,本人已拿腾 ...

  4. 深入理解Java虚拟机(第三弹)- JVM 内存分配与回收策略原理,从此告别 JVM 内存分配文盲

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:打卡活动第二期来啦,100% 能获得奖品个人原创+1博客:点击前往,查看更多 虚拟机系列文章 深入理解 Java ...

  5. Java 虚拟机内存分配与回收策略

    垃圾收集器与内存分配策略参考目录: 1.判断 Java 对象实例是否死亡 2. Java 中的四种引用 3.垃圾收集算法 4. Java9 中的 GC 调优 5.内存分配与回收策略 一.对象优先在 E ...

  6. JVM之内存分配与回收策略

    JVM之内存分配与回收策略 来源 https://www.cnblogs.com/xiaoxi/p/6557473.html JVM分代垃圾回收策略的基础概念 来源 https://www.cnblo ...

  7. JVM 之 内存分配与回收策略

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-[https://blog.csdn.net/cjm2484836553/article/details/103842357] <J ...

  8. jvm深入理解:内存分配与回收策略(优先在Eden分配、大对象直接进入老年代、长期存活的对象将进入老年代、动态对象年龄判定、空间分配担保)

    出入:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) Java技术体系的自动内存管理,最根本的目标是自动化地解决两个问题:自动给对象分配内存以及自动回收分配给对象的内存. 象的内存分配,从 ...

  9. JVM 优化实操 - 内存分配与回收策略

    JVM 体系难学的一个地方就是理论一大堆,却难以实践.今天就尝试着在本地实践一把,体会 JVM 内存分配和垃圾回收的过程,尽可能的能够通过本地实际操作感受一下之前学习到的一些理论知识,作为一名初学者, ...

最新文章

  1. 变换判断滤波器类型_7.4 低通IIR滤波器的频率变换
  2. 线程同步 阻塞 异步 非阻塞(转)
  3. IT精英们!一路走好!
  4. [你必须知道的.NET]第十三回:从Hello, world开始认识IL
  5. 暑假旅游小高峰,旅游行业都在烧钱赚人气
  6. python 一行_一行 Python 代码搞定炫酷可视化
  7. 工作395-路由选择
  8. .NET混淆器 Dotfuscator如何保护应用程序?控制流了解一下!
  9. mysql 设置时区_MySQL实战干货 | 如何处理由时区设置引发的 SQL 执行“卡顿”?...
  10. python方法大全参数是对象_向对象方法Python传递太多参数
  11. 《Effective C#》读书笔记(4)
  12. 【程序员学习运筹学】什么是运筹学
  13. 拓扑排序算法原理及Java代码实现
  14. 51单片机流水灯从原理图到PCB转化
  15. Python——轮盘抽奖游戏
  16. 计算机每天定时开机设置方法,电脑如何设置每天定时开机
  17. 编程语言入门YC创始人Paul Graham:如何开始创业
  18. 成功解决failed: The TLS connection was non-properly terminated
  19. bzoj2565题解
  20. pdf解密工具(超实用)

热门文章

  1. 74HC02或非门仿真示例
  2. 【Kafka】Kafka的安装
  3. 捍宇医疗再冲刺科创板上市:核心产品专利来自购买,暂未商业化
  4. 小学期助教感受-Funcode游戏编程
  5. 计算机网络的利与弊,网络的利与弊辩论会总结.doc
  6. 生命中最美的风景就是曾经遇见了你
  7. 人生25句最美丽的名句
  8. 华清远见-重庆中心-JAVA基础阶段技术总结/知识点梳理/个人总结/关于JAVA技术的解析(看法)/面试题解析
  9. buu-[ACTF新生赛2020]SoulLike
  10. AutoCAD家具设计入门到精通视频教程