Java JVM堆空间的概述

  • 1.设置堆空间初始值和最大值
  • 2.堆的核心概述
    • 内存细分
  • 3.堆空间大小的设置
  • 4.新生代与老年代
  • 5.图解对象分配的过程
  • 6.常用调优工具
  • 7.Minor GC、Major GC与Full GC
  • 8.堆空间分代思想
  • 9.内存分配策略
  • 10.对象分配过程: TLAB
  • 11.堆空间常用的VM参数
  • 12.通过逃逸分析看堆空间的对象分配策略
    • 1.堆是分配对象存储的唯一选择吗?
    • 2.逃逸分析概述
  • 3.逃逸分析:代码优化
    • 4.逃逸分析的缺点

1.设置堆空间初始值和最大值

通过idea 的-VM参数设置,如下图:

2.堆的核心概述

内存细分

3.堆空间大小的设置

  • 详情请看 Java SE8 官方文档 Ctrl+F 搜索 -Xms

  • 通过JVM参数来设置堆空间的初始值

    • -Xms用来设置堆空间(年轻代+老年代)的初始内存大小
    • -X是jvm的运行参数
    • ms是memory start
  • 通过JVM参数来设置堆空间的最大值

    • -Xmx用来设置堆空间(年轻代+老年代)的最大内存大小
  • 堆的初始大小(以字节为单位)。

    • 此值必须是1024的倍数且大于1 MB。在字母后面加上kK表示千字节,mM表示兆字节,gG表示千兆字节。
    • 以下示例说明如何使用各种单位将分配的内存大小设置为6 MB:
      • -Xms6291456
      • -Xms6144k
      • -Xms6m
      • 如果未设置此选项,则初始大小将设置为为老一代和年轻一代分配的大小之和。可以使用-Xmn选项或-XX:NewSize选项设置年轻代的堆的初始大小。
  • 开发中建议将初始堆内存和最大的堆内存设置成相同的值。

  • 打印GC过程的细节

    • JVM参数设置:-XX:+PrintGCDetails

添加代码测试**

public class HeapSpaceInitial {public static void main(String[] args) {//返回Java虚拟机中的堆内存总量long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;//返回Java虚拟机试图使用的最大堆内存量long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;System.out.println("-Xms : " + initialMemory + "M");System.out.println("-Xmx : " + maxMemory + "M");System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");System.out.println("系统内存大小为:" + maxMemory * 4.0 / 1024 + "G");}
}

打印GC日志(详情信息看后期博客)

4.新生代与老年代

  • -XX:NewRatio:设置新生代与老年代的比例。

    • 设置新老一代大小之间的比率。默认情况下,此选项设置为2。下面的示例演示如何将年轻/老人比率设置为1:1(这里就是年轻代占堆空间1:2,老年的占1:2)

      -XX:NewRatio =3 //设置老年代占堆空间的3:4
      
  • -XX:SurvivorRatio:设置新生代中Eden区与survivor区的比例

  • -XX: -UseAdaptivesizePolicy :关闭自适应的内存分配策略( 暂时用不到)

  • Xmn:设置新生代的空间的大小。 ( 一般不设置)

5.图解对象分配的过程

6.常用调优工具

  1. JDK命令行
  2. Eclipse :Memory Analyzer Tool
  3. Jconsole
  4. Vi sual VM
  5. Jprofiler(暂时使用) 下载及破解
  6. Java Flight Recorder
  7. GCViewerGC Easy

7.Minor GC、Major GC与Full GC

  • 年轻代GC(Minor GC) 触发机制:

    • 当年轻代空间不足时,就会触发Minor GC,这里的年轻代满指的是
      Eden代满,Survivor满不会引发GCI(每次Minor GC会清理年轻
      代的内存。)
    • 因为Java对象大多都具备朝生夕灭的特性,所以MinorGC非常频
      繁,一般回收速度也比较快。这一-定义既清晰又易于理解。
    • Minor GC会引发STW,暂停其它用户的线程,等垃圾回收结束,用户线
      程才恢复运行。
  • 老年代GC (Major GC/Fu11 GC)触发机制:

    • 指发生在老年代的GC, 对象从老年代消失时,我们说“Major GC”或“Fu11 GC”
      发生了。
    • 出现了Major GC, 经常会伴随至少一.次的Minor GC (但非绝对的,在Paral1el
      Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。

      • 也就是在老年代空间不足时,会先尝试触发Minor GC。如果之后空间还不足,
        则触发Major GC
    • Major GC的速度一般会比Minor GC慢10倍以上,STW的时间更长。
    • 如果Major GC后,内存还不足,就报00M了。
    • Major GC的速度- -般会比Minor GC慢10倍以上。
  • Fu11 GC,触发Fu1l GC执行的情况有如下五种:

    1. 调用System. gc()时,系统建议执行Fu1l GC,但是不必然执行
    2. 老年代空间不足
    3. 方法区空间不足
    4. 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
    5. 由Eden区、survivor space0 (From Space)区向survivor space1 (To
      Space)区复制时,对象大小大于To Space可 用内存,则把该对象转存到老年代,且
      老年代的可用内存小于该对象大小;
      说明: full gc是开发或调优中尽量要避免的。这样暂时时间会短一些。

8.堆空间分代思想

9.内存分配策略

  • 如果对象在Eden(伊甸园区)出生并经过第一次MinorGC 后仍然存活,并且能被Survivor
    容纳的话,将被移动到Survivor空间中,并将对象年龄设为1 。对象在
    Survivor区中每熬过一次MinorGC ,年龄就增加1 岁,当它的年龄增加到- -定
    程度(默认为15岁,其实每个JVM、每个GC都有所不同)时,就会被晋升到老年代
    中。

  • 对象晋升老年代的年龄阈值,可以通过选项-XX: MaxTenuringThreshold来设置。

  • 针对不同年龄段的对象分配原则如下所示:|

    • 优先分 配到Eden

    • 大对象直接分配到老年代

      • 尽量避免程序中出现过多的大对象长期存活的对象分配到老年代
    • 动态对象年龄判断

      • 如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空
        间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无须等到
        MaxTenur ingThreshold中要求的年龄。
    • 空间分配担保

      • -XX: Handle PromotionFailure

10.对象分配过程: TLAB

  • 为什么有TLAB ( Thread Local Allocation Buffer ) ?

    • 堆区是线程共享区域,任何线程都可以访问到堆区中的共享数据
    • 由于对象实例的创建在JVM中非常频繁,因此在并发环境下从堆区中划分内
      存空间是线程不安全的;
    • 为避免多个线程操作同一地址,需要使用加锁等机制,进而影响分配速度。
  • 什么是TLAB ?

    • 从内存模型而不是垃圾收集的角度,对Eden区域继续进行划分,JVM为
      每个线程分配了一个私有缓存区域,它包含在Eden空间内。
    • 多线程同时分配内存时,使用TLAB可以避免一系列的非线程安全问题,
      同时还能够提升内存分配的吞吐量,因此我们可以将这种内存分配方式称
      之为快速分配策略。
    • 据我所知所有OpenJDK衍生出来的JVM都提供了TLAB的设计。

TLAB分配过程:

11.堆空间常用的VM参数

  • -XX: +PrintFlagsInitial :查看所有的参数的默认初始值

  • -XX:+PrintFlagsFinal : 查看所有的参数的最终值(可能会存在修改,
    不再是初始值)

  • -Xms:初始堆空间内存 (默认为物理内存的1/64)

  • -Xmx:最大堆空间内存(默认为物理内存的1 /4)

  • Xmn: 设置新生代的大小。(初始值及最大值)

  • XX: +DoEscapeAnalysis ; 开启逃逸分析

  • XX:NewRatio:配置新生代与老年代在堆结构的占比

  • -XX:SurvivorRatio:设置新生代中Eden和SO/S1空间的比例

  • -XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄

  • -XX: +PrintGCDetails:输出详细的GC处理日志

  • -XX:HandL ePromotionFailure:是否设置空间分配担保

  • -XX:+EliminateAllocations: 开启标量替换

12.通过逃逸分析看堆空间的对象分配策略

1.堆是分配对象存储的唯一选择吗?

  • 在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述:
    随着JIT编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导
    致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。
  • 在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一一
    种特殊情况,那就是如果经过逃逸分析(Escape Analysis) 后发现,一个对象并没有
    逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无须
    进行垃圾回收了。这也是最常见的堆外存储技术。
  • 此外,前面提到的基于openJDK深度定制的TaoBaoVM,其中创新的GCIH (GC
    invisible heap) 技术实现off -heap,将生命周期较长的Java对象从heap中移至
    heap外,并且GC不能管理GCIH内部的Java对象,以此达到降低GC的回收频率和提升
    GC的回收效率的目的。

2.逃逸分析概述

  • 如何将堆上的对象分配到栈,需要使用逃逸分析手段。
    这是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数
    全局数据流分析算法。
  • 通过逃逸分析,JavaHotspot编译器能够分析出一个新的对象的引用的
    使用范围从而决定是否要将这个对象分配到堆上。
  • 当能够明确对象不会发生逃逸时,就可以对这个对象做一个优化,不将其分配到堆上,而是直接分配到栈上,这样在方法结束时,这个对象就会随着方法的出栈而销毁,这样就可以减少垃圾回收的压力。
  • 逃逸分析的基本行为就是分析对象动态作用域:
    • 当一个对象在方法中被定义后,对象只在方法内部使用,则认为没有
      发生逃逸。
    • 当一个对象在方法中被定义后,它被外部方法所引用,则认为发生逃
      逸。例如作为调用参数传递到其他地方中。
/***  逃逸分析**  如何快速的判断是否发生了逃逸分析,大家就看new的对象实体是否有可能在方法外被调用。*/
public class EscapeAnalysis {public EscapeAnalysis obj;/*方法返回EscapeAnalysis对象,发生逃逸*/public EscapeAnalysis getInstance(){return obj == null? new EscapeAnalysis() : obj;}/*为成员属性赋值,发生逃逸*/public void setObj(){this.obj = new EscapeAnalysis();}//思考:如果当前的obj引用声明为static的?仍然会发生逃逸。/*对象的作用域仅在当前方法中有效,没有发生逃逸*/public void useEscapeAnalysis(){EscapeAnalysis e = new EscapeAnalysis();}/*引用成员变量的值,发生逃逸*/public void useEscapeAnalysis1(){EscapeAnalysis e = getInstance();//getInstance().xxx()同样会发生逃逸}
}

3.逃逸分析:代码优化

使用逃逸分析,编译器可以对代码做如下优化:

一、栈上分配

将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配。

二、同步省略:

如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。

三、分离对象或标量替换:

有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。

4.逃逸分析的缺点

  • 关于逃逸分析的论文在1999年就已经发表了,但直到JDK 1.6才有实现,而且这项技
    术到如今也并不是十分成熟的。
  • 其根本原因就是无法保证逃逸分析的性能消耗一定能高于他的消耗。虽然经过逃逸分
    析可以做标量替换、栈上分配、和锁消除。但是逃逸分析自身也是需要进行一系列复
    杂的分析的,这其实也是一个相对耗时的过程。
  • 一个极端的例子,就是经过逃逸分析之后,发现没有一个对象是不逃逸的。那这个逃
    逸分析的过程就白白浪费掉了。
  • 虽然这项技术并不十分成熟,但是它也是即时编译器优化技术中一个十分重要的手段。
    注意到有一些观点,认为通过逃逸分析,JVM会 在栈.上分配那些不会逃逸的对象,这
    在理论上是可行的,但是取决于JVM设计者的选择。据我所知,Oracle Hotspot
    JVM中并未这么做,这一点在逃逸分析相关的文档里已经说明,所以可以明确所有的
    对象实例都是创建在堆上。
  • 目前很多书籍还是基于JDK 7以前的版本,JDK已经发生了很大变化,intern字符串.
    的缓存和静态变量曾经都被分配在永久代上,而永久代已经被元数据区取代。但是,
    intern字符串缓存和静态变量并不是被转移到元数据区,而是直接在堆上分配,所以
    这一点同样符合前面一点的结论:对象实例都是分配在堆上。

Java JVM堆空间的概述相关推荐

  1. java虚拟机堆空间

    堆是一个进程唯一的,是内存管理的核心区域 jvm启动时 堆 就会被创建,大小也就确定了,是jvm中管理的最大的一块内存,堆的大小是可以调节的 <java虚拟机规范>规定,堆可以处于物理上不 ...

  2. jvm堆空间的常用参数设置

  3. java堆空间(内存)

    当Java程序开始运行时,JVM会从操作系统获取一些内存.JVM使用这些内存,这些内存的一部分就是堆内存.堆内存通常在存储地址的底层,向上排列.当一个对象通过new关键字或通过其他方式创建后,对象从堆 ...

  4. Java #JVM(HotSpot) 运行时数据区 #程序计数器(PC寄存器)#虚拟机栈(栈帧:局部变量表、操作数栈……)#堆……

    目录 JVM中线程的说明 程序计数器(PC寄存器) 虚拟机栈 · 栈帧 ·· 局部变量表 ·· 操作数栈 ·· 动态链接 ·· 方法返回地址 ·· 本地方法栈 堆 · 查看堆的大小 · 堆的默认大小 ...

  5. java中的堆空间增加_Java堆内存的10个要点

    当我开始学习Java编程时,我不知道什么是堆内存或堆空间,我甚至不知道当对象创建时,它们被放在了哪里.当我开始正式写一些程序后,我会经常遇到java.lang.outOfMemoryError的报错, ...

  6. 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://sina.lt/gqaM 最近网上出现一个美团 ...

  7. 美团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    作者:gosaintmrc 来源:http://sina.lt/gqaM 最近网上出现一个美团面试题:"一个线程OOM后,其他线程还能运行吗?" 我看网上出现了很多不靠谱的答案.这 ...

  8. 美团面试:JVM 堆内存溢出后,其他线程是否可继续工作?

    来源 | http://x7j.net/b8c06 最近网上出现一个美团面试题:"一个线程OOM后,其他线程还能运行吗?" 我看网上出现了很多不靠谱的答案.这道题其实很有难度,涉及 ...

  9. JVM 堆内存溢出后,其他线程是否可继续工作?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 来源:http://sina.lt/gqaM 最近网上出现 ...

最新文章

  1. OzymanDNS 使用——perl 5.22没有成功。。。
  2. Android短消息备份闪退,Android Socket发送信息时闪退
  3. 环境变量和用户变量有什么区别?
  4. 微信小程序小模块界面,边框带阴影
  5. 如何用keras实现deepFM
  6. Python 数据科学入门
  7. 【渝粤题库】国家开放大学2021春1542投资学题目
  8. Android 内存泄漏分析(完)
  9. vue.js 模板语法
  10. Xshel和Xftp免费版
  11. 吉林大学超星MOOC学习通高级语言程序设计 C++ 实验01 顺序程序设计(2021级)
  12. 数字图像处理学习笔记(一)——数字图像处理概述
  13. 【报告分享】连锁经营行业全面费用管理数字化白皮书-亿欧汇联易(附下载)
  14. 变速恒频风电机组的优缺点_变速恒频双馈风力发电机的主要优点和基本原理
  15. 千千音乐付费音乐爬取--json数据的处理
  16. 微信小程序弹窗有输入框且可以使用名文和密文输入
  17. C# + OpenXML 生成 Word 文档(VS2015)
  18. WiFi无线网卡属性设置——英特尔无线适配器高级设置
  19. 《深入理解计算机系统》之浅析程序性能优化
  20. 电子信息(非全)考研分析——大连理工VS哈工程

热门文章

  1. UINO优诺:数字孪生可视化管理GIV,打造统览全局大视野
  2. archlinux下网易云音乐netease-cloud-music部分问题
  3. nodejs镜像问题如何设置镜像
  4. 西电计算机组织与体系结构实验,《计算机组织与体系结构》实验.doc
  5. 【论文投稿】Hindawi旗下4区Mobile Information Systems(misy)投稿详细步骤
  6. Egret(白鹭引擎)——Egret+fairyGui 实战项目入门
  7. [经验教程]2022京东618红包活动时间是什么时候开始什么时候结束及怎么领取京东618红包?
  8. 英语名篇——关于《论学习》的读后感
  9. 【electron】 打包应用修改图标和进程名字
  10. Drawing Rectangles(绘制矩形)