JVM 堆内存分配过程

news/2024/7/18 17:41:26 标签: jvm

设置堆内存大小和 OOM

Java 堆用于存储 Java 对象实例,那么堆的大小在 JVM 启动的时候就确定了,我们可以通过 -Xmx-Xms 来设定

  • -Xms 用来表示堆的起始内存,等价于 -XX:InitialHeapSize
  • -Xmx 用来表示堆的最大内存,等价于 -XX:MaxHeapSize

如果堆的内存大小超过 -Xmx 设定的最大内存, 就会抛出 OutOfMemoryError 异常。

我们通常会将 -Xmx-Xms 两个参数配置为相同的值,其目的是为了能够在垃圾回收机制清理完堆区后不再需要重新分隔计算堆的大小,从而提高性能。

  • 默认情况下,初始堆内存大小为:电脑内存大小/64

  • 默认情况下,最大堆内存大小为:电脑内存大小/4

可以通过代码获取到我们的设置值,当然也可以模拟 OOM:

public static void main(String[] args) {

  //返回 JVM 堆大小
  long initalMemory = Runtime.getRuntime().totalMemory() / 1024 /1024;
  //返回 JVM 堆的最大内存
  long maxMemory = Runtime.getRuntime().maxMemory() / 1024 /1024;

  System.out.println("-Xms : "+initalMemory + "M");
  System.out.println("-Xmx : "+maxMemory + "M");

  System.out.println("系统内存大小:" + initalMemory * 64 / 1024 + "G");
  System.out.println("系统内存大小:" + maxMemory * 4 / 1024 + "G");
}

 

jvm-堆内存分配">查看 JVM 堆内存分配

  1. 在默认不配置 JVM 堆内存大小的情况下,JVM 根据默认值来配置当前内存大小

  2. 默认情况下新生代和老年代的比例是 1:2,可以通过 –XX:NewRatio 来配置

    新生代中的 Eden:From Survivor:To Survivor 的比例是 8:1:1,可以通过 -XX:SurvivorRatio 来配置
  3. 若在 JDK 7 中开启了 -XX:+UseAdaptiveSizePolicy,JVM 会动态调整 JVM 堆中各个区域的大小以及进入老年代的年龄

    此时 –XX:NewRatio-XX:SurvivorRatio 将会失效,而 JDK 8 是默认开启-XX:+UseAdaptiveSizePolicy

    在 JDK 8中,不要随意关闭-XX:+UseAdaptiveSizePolicy,除非对堆内存的划分有明确的规划

每次 GC 后都会重新计算 Eden、From Survivor、To Survivor 的大小,计算依据是GC过程中统计的GC时间吞吐量内存占用量。

java -XX:+PrintFlagsFinal -version | grep HeapSize
    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 134217728                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 2147483648                          {product}
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)



$ jmap -heap 进程号

 

 

对象在堆中的生命周期

  1. 在 JVM 内存模型的堆中,堆被划分为新生代和老年代
    • 新生代又被进一步划分为 Eden区Survivor区,Survivor 区由 From SurvivorTo Survivor 组成
  2. 当创建一个对象时,对象会被优先分配到新生代的 Eden 区
    • 此时 JVM 会给对象定义一个对象年轻计数器-XX:MaxTenuringThreshold
  3. 当 Eden 空间不足时,JVM 将执行新生代的垃圾回收(Minor GC)
    • JVM 会把存活的对象转移到 Survivor 中,并且对象年龄 +1
    • 对象在 Survivor 中同样也会经历 Minor GC,每经历一次 Minor GC,对象年龄都会+1
  4. 如果分配的对象超过了-XX:PetenureSizeThreshold,对象会直接被分配到老年代

 

对象的分配过程

为对象分配内存是一件非常严谨和复杂的任务,JVM 的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法和内存回收算法密切相关,所以还需要考虑 GC 执行完内存回收后是否会在内存空间中产生内存碎片。

  1. new 的对象先放在伊甸园区,此区有大小限制
  2. 当伊甸园的空间填满时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区,然后将伊甸园中的剩余对象移动到幸存者 0 区
  3. 如果再次触发垃圾回收,此时上次幸存下来的放到幸存者 0 区,如果没有回收,就会放到幸存者 1 区
  4. 如果再次经历垃圾回收,此时会重新放回幸存者 0 区,接着再去幸存者 1 区
  5. 什么时候才会去养老区呢? 默认是 15 次回收标记
  6. 在养老区,相对悠闲。当养老区内存不足时,再次触发 Major GC,进行养老区的内存清理
  7. 若养老区执行了 Major GC 之后发现依然无法进行对象的保存,就会产生 OOM 异常

 

 

GC 垃圾回收简介  Minor GC、Major GC、Full GC

JVM 在进行 GC 时,并非每次都对堆内存(新生代、老年代;方法区)区域一起回收的,大部分时候回收的都是指新生代。

针对 HotSpot VM 的实现,它里面的 GC 按照回收区域又分为两大类:部分收集(Partial GC),整堆收集(Full GC)

  • 部分收集:不是完整收集整个 Java 堆的垃圾收集。其中又分为:
    • 新生代收集(Minor GC/Young GC):只是新生代的垃圾收集
    • 老年代收集(Major GC/Old GC):只是老年代的垃圾收集
      • 目前,只有 CMS GC 会有单独收集老年代的行为
      • 很多时候 Major GC 会和 Full GC 混合使用,需要具体分辨是老年代回收还是整堆回收
    • 混合收集(Mixed GC):收集整个新生代以及部分老年代的垃圾收集
      • 目前只有 G1 GC 会有这种行为
  • 整堆收集(Full GC):收集整个 Java 堆和方法区的垃圾

http://www.niftyadmin.cn/n/5544329.html

相关文章

智慧消防视频监控烟火识别方案,筑牢安全防线

一、方案背景 在现代化城市中,各类小型场所(简称“九小场所”)如小餐馆、小商店、小网吧等遍布大街小巷,为市民生活提供了极大的便利。然而,由于这些场所往往规模较小、人员流动性大、消防安全意识相对薄弱&#xff0…

前端技术(三)—— javasctipt 介绍:jQuery方法和点击事件介绍(补充)

6. 常用方法 ● addClass() 为jQuery对象添加一个或多个class <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&…

windows中配置python3.11环境安装教程

在Windows中配置Python 3.11环境的详细安装教程如下&#xff1a; ### 步骤1&#xff1a;下载Python 3.11 1. 打开浏览器&#xff0c;访问[Python官方下载页面](https://www.python.org/downloads/). 2. 找到并点击Python 3.11的下载链接。 3. 下载适用于Windows的安装包&…

RedHat运维-LinuxSELinux基础4-端口绑定SELinux上下文

1. SELinux将一个_________与一个SELinux上下文相连接&#xff1b; 2. SSH协议将22/tcp端口与__________SELinux上下文相联系&#xff1b; 3. HTTP协议将80/tcp、443/tcp端口与____________SELinux上下文相联系&#xff1b; 4. 列出所有端口的SELinux上下文信息的方法是_______…

【Linux】网络新手村

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 引言 今天&#xff0c;我们就开始学习Linux网络相关的内容。这篇博客作为Linux网络板块的第一篇博客看&#xff0c;我们首先要带着大家明白Linux网络的一些名词的概念&#xff0c;为之后的学习扫清障碍。然后我…

【大数据面试题】36 你平时优化代码有什么方法,思路?

一步一个脚印&#xff0c;一天一道大数据面试题 博主希望能够得到大家的点赞收藏支持&#xff01;非常感谢 点赞&#xff0c;收藏是情分&#xff0c;不点是本分。祝你身体健康&#xff0c;事事顺心&#xff01; 上次梳理了 Spark 优化&#xff0c;最近想了想通用的优化方法。就…

RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化

接前一篇:RAG实践:ES混合搜索BM25+kNN(cosine) https://blog.csdn.net/Xin_101/article/details/140230948 本文主要讲解混合搜索相关理论以及计算推导过程, 包括BM25、kNN以及ES中使用混合搜索分数计算过程。 详细讲解: (1)ES中如何通过BM25计算关键词搜索分数; (2)…

RT-Thread中rt_kprintf函数无法输出浮点数问题

RT-Thread中rt_kprintf函数无法输出浮点数和HAL_Snprintf无法格式化%f的问题 解决 直接粗暴把rt_kprintf函数调用的rt_vsnprintf直接改为vsnprintf&#xff0c;加入头文件#include <stdio.h>。浮点功能恢复正常。 同样&#xff0c;rt_sprintf也直接替换成sprintf可以将浮…