JVM之【运行时数据区2】

news2024/12/23 10:37:07

三、堆(Heap)

在这里插入图片描述

1、什么是堆

  • 在Java虚拟机(JVM)中,堆(Heap)是用于动态分配内存的区域。在Java程序运行时,所有对象和数组都是在堆中分配内存的。堆是Java内存模型的重要组成部分,允许程序在运行时动态地分配和释放内存。
  • 一个JVM实例通常只有一个堆区域,整个应用程序中的所有线程共享这个堆。这个堆是由JVM在启动时根据配置参数(如-Xms-Xmx)来初始化和管理的。
  • 堆的大小JVM启动时就确定,并且创建了。

2、堆的分代策略

JVM将堆内存分为三代:年轻代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation,Java 8之后称为元空间(Metaspace))。

(1)年轻代(Young Generation)

年轻代主要存放新创建的对象,大部分对象在这里很快变得不可达。年轻代又细分为三个区域:

  • Eden区: 大部分新对象在这里分配。
  • 两个Survivor区(S0和S1): 在Eden区进行垃圾回收时,存活的对象会被移到Survivor区。这两个Survivor区会轮流使用,一个用作复制的目标,另一个空闲。

(2)老年代(Old Generation)

生命周期较长的对象会从年轻代晋升到老年代。老年代存放的对象相对稳定,垃圾回收频率较低,但回收时通常会进行全堆扫描,代价较高。

(3)永久代(Permanent Generation)/元空间(Metaspace)

永久代用于存储类的元数据(如类信息、方法信息等)。在Java 8及之后,永久代被元空间取代,元空间在本地内存中分配,而不再是堆的一部分。

Java虚拟机(JVM)中的分代垃圾回收策略是为了提高内存管理的效率和性能。通过将堆内存划分为不同的区域,并根据对象的生命周期对其进行管理,分代策略优化了垃圾回收的频率和速度。

3、堆的内存分配策略

在Java堆内存管理中,有两种主要的内存分配策略:指针碰撞(Bump-the-pointer)和空闲列表(Free List)。这两种策略用于不同的垃圾回收器和内存布局方式。下面将详细解释这两种策略,以及它们的优缺点和相关配置。

(1)指针碰撞(Bump-the-pointer)

指针碰撞是一种非常高效的内存分配方式,适用于内存连续分配的情形。堆内存被划分为两部分:已使用的部分和未使用的部分。JVM维护一个指针,该指针指向当前未使用部分的开始位置。当需要分配内存时,只需将指针向前移动所需的大小,分配过程非常简单高效。

工作原理
  1. 初始化: 在堆的开始位置设置一个指针,指向可用内存的起始位置。
  2. 分配内存: 当需要分配对象时,将指针向前移动对象大小的距离,并返回原指针位置作为分配地址。
  3. 回收内存: 垃圾回收时,通过压缩和整理,使存活对象连续存放在堆的一端,然后重置指针到存活对象的末尾。
优点
  • 分配速度快: 内存分配只需移动指针,时间复杂度为O(1)。
  • 低碎片: 通过压缩整理,可以减少内存碎片。
缺点
  • 适用范围有限: 适用于对象存活时间较短、需要频繁分配和回收的情况(如年轻代)。
  • 整理开销: 垃圾回收时需要对存活对象进行整理,开销较大。
相关配置参数

指针碰撞通常用于垃圾回收器G1和Parallel Scavenge的年轻代。具体配置参数取决于使用的垃圾回收器。例如:

  • -XX:+UseG1GC:启用G1垃圾回收器。
  • -XX:+UseParallelGC:启用Parallel垃圾回收器。

(2)空闲列表(Free List)

空闲列表是一种较为灵活的内存分配方式,适用于内存块大小不固定的情形。JVM维护一个已回收内存块的列表,每次分配内存时,从空闲列表中找到适当大小的内存块进行分配。

工作原理
  1. 初始化: 创建一个空闲列表,记录所有可用的内存块。
  2. 分配内存: 当需要分配对象时,从空闲列表中找到适当大小的内存块,并将其从列表中移除。
  3. 回收内存: 垃圾回收时,将回收的内存块加入空闲列表。
优点
  • 灵活性高: 可以处理不同大小的内存分配请求,适用于对象大小和生命周期不确定的情况(如老年代)。
  • 无须整理: 不需要像指针碰撞那样频繁整理内存。
缺点
  • 分配速度慢: 分配内存时需要遍历空闲列表找到适当的内存块,时间复杂度为O(n)。
  • 内存碎片: 回收和分配过程中可能产生内存碎片,降低内存利用率。
相关配置参数

空闲列表通常用于垃圾回收器CMS(Concurrent Mark-Sweep)和老年代。具体配置参数包括:

  • -XX:+UseConcMarkSweepGC:启用CMS垃圾回收器。
  • -XX:+UseParallelOldGC:启用Parallel Old垃圾回收器(老年代使用空闲列表)。

总结对比

特性指针碰撞(Bump-the-pointer)空闲列表(Free List)
分配速度快(O(1))慢(O(n))
内存碎片少,通过整理减少多,需管理和合并碎片
适用场景年轻代,短生命周期对象老年代,大小不定的对象
整理开销高,需要压缩和整理无需整理,但需管理空闲块
相关垃圾回收器G1, Parallel ScavengeCMS, Parallel Old

4、对象在各个代之间的转移过程

一个对象从Eden区创建开始,到老年代,最后涉及元空间的过程如下:

  1. 对象在Eden区创建:

    • 当使用new关键字或其他方式创建对象时,首先在Eden区分配内存。
    • 大对象会直接进入老年代(如超过了新生代大小的对象)
  2. Minor GC(小型垃圾回收):

    • 当Eden区满时,会触发Minor GC。
    • 在Minor GC期间,Eden区的存活对象会被复制到一个空闲的Survivor区(S0或S1)。
    • Eden区的内存会被清空。
  3. Survivor区的对象晋升:

    • 存活下来的对象继续留在Survivor区,如果在多次Minor GC后仍存活(达到一定的年龄阈值,一般为15),对象会从Survivor区晋升到老年代。
    • 大对象会直接进入老年代(如超过了新生代大小的对象)
  4. 老年代的对象:

    • 在老年代的对象生命周期较长,通常只有在Major GC(也称为Full GC)时才会被回收。
    • 当老年代的内存使用达到一定阈值时,会触发Major GC,清理老年代中的不可达对象。
  5. 永久代/元空间:

    • 类的元数据、方法元数据等会存放在永久代(Java 7及以前)或元空间(Java 8及以后)。
    • 元空间在本地内存中分配,不属于堆的一部分。
    • 类加载器加载类时,类的元数据会存放到元空间中,这部分数据在类卸载时会被回收。

示例:对象从Eden到老年代的转移过程

假设我们创建一个新的对象:

public class Test {
    public static void main(String[] args) {
        Object obj = new Object(); // 对象在Eden区分配
    }
}
  1. 创建对象:

    • new Object()会在Eden区分配内存,创建obj对象。
  2. Eden区满时触发Minor GC:

    • 如果Eden区满了,会触发Minor GC。
    • 存活的obj对象会被复制到一个Survivor区(假设是S0)。
  3. 对象在Survivor区之间复制:

    • 如果obj在下一次Minor GC时仍然存活,会从S0复制到S1。
    • 每次Minor GC,存活对象在S0和S1之间复制。
  4. 对象晋升到老年代:

    • obj对象达到晋升年龄(如15次Minor GC),它会被移动到老年代。
    • 大对象会直接进入老年代(如超过了新生代大小的对象)
  5. Major GC回收老年代对象:

    • 当老年代内存不足时,会触发Major GC,清理不可达的老年代对象。

总结

通过分代策略,JVM能够高效地管理内存,减少垃圾回收的开销。年轻代频繁进行Minor GC,快速回收短生命周期对象,而老年代的Major GC则更少进行,但处理存活时间长的对象。元空间管理类元数据,独立于堆内存。通过这些机制,JVM能够在性能和内存管理之间取得平衡。

5、Minor GC、Major GC、Full GC

在Java虚拟机(JVM)中,垃圾回收(Garbage Collection, GC)是管理内存的关键机制。垃圾回收器通过自动回收不再使用的对象来释放内存,避免内存泄漏和内存溢出。JVM中的垃圾回收可以分为三种主要类型:Minor GC、Major GC 和 Full GC。
在这里插入图片描述

(1)Minor GC

作用

Minor GC专门用于清理年轻代(Young Generation)的垃圾对象。年轻代中的对象生命周期通常较短,频繁创建和销毁,因此Minor GC发生频率较高。

触发条件

当Eden区满时,JVM会触发Minor GC。这种情况通常发生在新对象被频繁创建的情况下。

过程
  1. 复制存活对象: 在Minor GC期间,Eden区中的存活对象会被复制到一个空闲的Survivor区(S0或S1,这俩会交替空)。
  2. 清空Eden区: Eden区的所有内存会被清空,所有不可达的对象都会被回收。
  3. Survivor区轮换: 存活的对象在两个Survivor区之间轮换,最后达到一定年龄的对象会被晋升到老年代。

(2) Major GC

作用

Major GC,也称为Old GC,主要用于清理老年代(Old Generation)的垃圾对象。老年代存放生命周期较长的对象,Major GC的发生频率较低,但回收过程较慢。所需时间一般为Minor GC的十倍以上

触发条件

当老年代的内存使用达到一定的阈值时,JVM会触发Major GC。这通常发生在老年代中的对象越来越多,导致内存不足的情况下。

过程
  1. 标记存活对象: Major GC会首先标记所有存活的对象。
  2. 清理垃圾对象: 清理不可达的对象,释放老年代中的内存。
  3. 整理内存: 一些垃圾收集器(如CMS)可能会对内存进行压缩和整理,以减少内存碎片。

(3)Full GC

作用

Full GC是一次全面的垃圾回收操作,包括清理年轻代、老年代和永久代/元空间中的所有垃圾对象。Full GC的开销最大,因为它需要暂停所有应用线程(Stop-the-World,STW)进行全堆扫描和回收。

触发条件

Full GC可以由多种情况触发,包括:

  1. System.gc() 调用: 显式调用System.gc()会建议JVM执行Full GC。
  2. 老年代或永久代/元空间内存不足: 当老年代或元空间的内存不足时,可能会触发Full GC。
  3. JVM自适应调整: 某些情况下,JVM的自适应调整策略可能会触发Full GC。
过程
  1. 标记所有存活对象: Full GC会标记整个堆中的所有存活对象,包括年轻代、老年代和永久代/元空间。
  2. 清理垃圾对象: 回收所有不可达的对象,释放内存。
  3. 整理内存: 对内存进行压缩和整理,减少内存碎片。

垃圾回收器的种类

JVM提供了多种垃圾回收器,每种回收器在处理Minor GC、Major GC和Full GC时有不同的策略。常见的垃圾回收器包括:

  1. Serial GC: 单线程垃圾回收器,适用于单处理器机器。
  2. Parallel GC: 多线程垃圾回收器,适用于多处理器机器。
  3. CMS(Concurrent Mark-Sweep) GC: 低暂停时间的垃圾回收器,适用于需要响应时间的应用。
  4. G1(Garbage-First) GC: 适用于大堆内存和低暂停时间要求的应用,结合了并行和并发回收技术。

总结

  • Minor GC: 清理年轻代的垃圾对象,触发频率高,回收速度快。
  • Major GC: 清理老年代的垃圾对象,触发频率低,回收速度慢。
  • Full GC: 全堆垃圾回收,包括年轻代、老年代和永久代/元空间,触发代价最高,通常是最后的手段。

6、TLAB-本地线程分配缓冲(Thread Local Allocation Buffer)

为什么

  • 堆区是线程共享区域,任何线程都可以访问到堆区中的共享数据由于对象实例的创建在JVM中非常频繁,因此在并发环境下从堆区中划分内存空间是线程不安全的
  • 为避免多个线程操作同一地址,需要使用加锁等机制,进而影响分配速度
  • 因为堆是线程共享的,那就会出现正在给A分配内存,还没有完成,B又来使用原先的内存状态分配内存的情况。

是什么

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

再说明

  • 尽管不是所有的对象实例都能够在TLAB中成功分配内存,但JVM确实是将TLAB作为内存分配的首选。
  • 在程序中,开发人员可以通过选项“-XX:UseTLAB”设置是否开启TLAB空间。默认情况下,TLAB空间的内存非常小,仅占有整个Eden空间的1%,当然我们可以通过选项“-XX:TLABwasteTargetPercent”设置TLAB空间所占用Eden空间的百分比大小。
  • 一旦对象在TLAB空间分配内存失败时,JVM就会尝试着通过使用加锁机制确保数据操作的原子性,从而直接在Eden空间中分配内存。

在这里插入图片描述

7、对象在堆里的创建过程

(1)前提条件:类加载

类加载

  • 当JVM遇到一个类的首次使用(通常是通过new关键字),会触发类加载过程。
  • 类加载分为加载(Loading)、连接(Linking)和初始化(Initialization)三个阶段。
  • 加载阶段:JVM通过类加载器(ClassLoader)读取类的字节码。
  • 连接阶段:包括验证(Verification)、准备(Preparation)和解析(Resolution)。
    • 验证:确保字节码符合JVM规范。
    • 准备:为类的静态变量分配内存并设置初始值。
    • 解析:将符号引用转换为直接引用。
  • 初始化阶段:执行类的静态初始化块和静态变量的赋值。
    对象初始化是对象在堆内存中创建的关键步骤,包括内存清零、对象头填充、字段初始化和构造方法调用等过程。对齐填充则是为了优化内存访问效率,对对象的大小进行调整。下面详细描述对象初始化的过程和对齐填充。

(2)初始化

  1. 内存分配

    • 在JVM的堆内存中为对象分配一个连续的内存块,这个内存块的大小由对象的类定义,包括对象头和实例数据。
    • 内存分配可能采用指针碰撞或空闲列表的方式,具体取决于垃圾收集器的实现。
  2. 内存清零

    • 分配的内存块通常会被清零(非必须但常见),以确保对象的默认值是零值。
    • 清零的目的是防止使用未初始化的内存,减少潜在的错误。
  3. 对象头填充

    • 将对象头的内容填充到内存块的前几字节,具体包括:
      • Mark Word:初始化对象的哈希码(通常为空),GC状态和锁状态等。
      • 类型指针(Klass Pointer):指向对象所属的类元数据,JVM通过这个指针知道对象的类信息。
      • 数组长度(如果是数组对象):存储数组的长度。
  4. 字段初始化

    • JVM将对象的字段按照类定义进行初始化,基本类型字段初始化为默认值(例如int为0,float为0.0,boolean为false等),引用类型字段初始化为null。
    • 如果类有显示的字段初始值(例如private int age = 25;),JVM会在这一步将这些字段初始化为指定的值。
  5. 调用构造方法

    • JVM调用类的构造方法(<init>),执行用户定义的初始化逻辑。
    • 构造方法可能调用父类的构造方法(通过super),确保整个类继承链上的初始化顺序正确。
    • 构造方法中可以进一步修改字段的初始值,设置对象的初始状态。

(3)对齐填充(Padding)

对齐填充的目的是优化内存访问效率,确保对象在内存中的对齐符合硬件要求。对齐填充通常发生在以下几个方面:

  1. 对象大小对齐

    • JVM要求对象的大小是特定字节数的倍数(通常是8字节)。如果对象的实际大小不是8字节的倍数,JVM会在对象末尾添加填充字节,以满足对齐要求。
    • 例如,一个对象实际大小是14字节,那么JVM会添加2字节的填充,使对象大小达到16字节。
  2. 字段对齐

    • JVM可能会调整对象内部字段的排列顺序,以确保每个字段都对齐到其自然边界(例如,4字节的int字段对齐到4字节边界)。
    • 字段对齐可以提高内存访问速度,因为硬件在读取或写入未对齐的数据时可能需要额外的操作。

(4)示例分析

假设有一个简单的Java类:

public class Person {
    private int age;
    private boolean isEmployed;
}

当创建一个Person对象时:

Person person = new Person();
内存布局分析
  1. 内存分配

    • JVM为Person对象分配一个内存块,包括对象头和实例数据。
  2. 内存清零

    • 内存块被清零,确保初始值为0。
  3. 对象头填充

    • 对象头(12字节,假设为32位系统):包含Mark Word(8字节)和类型指针(4字节)。
  4. 字段初始化

    • age(4字节,初始值为0)
    • isEmployed(1字节,初始值为false)
  5. 对齐填充

    • 为了对齐对象大小到8字节,可能会在isEmployed后面添加3字节的填充,使对象大小达到16字节。
对象的内存布局示例(32位系统)
| 对象头 (Mark Word, 8字节) |
| 对象头 (类型指针, 4字节) |
| int age (4字节)          |
| boolean isEmployed (1字节)|
| 填充 (3字节)             |

在64位系统中,对象头可能是16字节,因此需要调整相应的对齐填充:

| 对象头 (Mark Word, 8字节)   |
| 对象头 (类型指针, 8字节)    |
| int age (4字节)             |
| boolean isEmployed (1字节)  |
| 填充 (3字节)               |

四、方法区

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

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

相关文章

常见SSL证书品牌关系图

常见SSL证书品牌关系图 在SSL证书市场上&#xff0c;有几个主要的品牌和他们之间的复杂关系。以下是一些主要的SSL证书提供商及其关系的简要概述&#xff1a; DigiCert&#xff1a; DigiCert 是最大的SSL证书颁发机构之一。它收购了Symantec的SSL和PKI业务&#xff0c;其中包括…

Linux系统硬盘分区

文章目录 一、硬盘和分区1.1 硬盘的概念1.2 硬盘分区的类别1.3 硬盘分区的方式1.3.1 MBR分区1.3.2 GPT分区 1.4 硬盘分区的意义1.4.1 分区的作用1.4.2 分区的缺点 二、如何建立分区2.1 分区命令2.1.1 fdisk命令2.1.2 gdisk命令 2.2 建立分区2.2.1 建立MBR分区建立主分区建立扩展…

leetCode.82. 删除排序链表中的重复元素 II

leetCode.82. 删除排序链表中的重复元素 II 题目思路&#xff1a; 代码 class Solution { public:ListNode* deleteDuplicates(ListNode* head) {auto dummy new ListNode(-1);dummy->next head;auto p dummy;while(p->next){auto q p->next->next;while(q …

洛谷 P1346电车

题目来源于&#xff1a;洛谷 解题思路&#xff1a; 可以把一个路口看作一张图中的一个点&#xff0c;轨道是图中的边&#xff08;注意&#xff1a;这是有向图&#xff09;&#xff0c;每一条边的权值就是这个边所联通的点是否需要按按钮&#xff08;需要按按钮就是1&#xff0…

Ubuntu24.04安装tabby-terminal-1.0.207并处理依赖

1 下载 tabby-terminal-1.0.207 地址&#xff1a; https://github.com/Eugeny/tabby/releases 点击show all 36 assets 选择 tabby-1.0.207-linux-x64.deb 并下载。 2 依赖下载 gconf2_3.2.6-3ubuntu6_amd64.deb gconf2-common_3.2.6-3ubuntu6_all.deb gconf-service_3.2.6-…

如何实现倾斜摄影三维模型OSGB格式轻量化

如何实现倾斜摄影三维模型OSGB格式轻量化 倾斜摄影三维模型以其高精度和真实感受在城市规划、建筑设计和虚拟漫游等领域发挥着重要作用。然而&#xff0c;由于其庞大的数据量和复杂的几何结构&#xff0c;给数据存储、传输和可视化带来了挑战。为了解决这个问题&#xff0c;倾斜…

机器学习实验----逻辑回归实现二分类

目录 一、介绍 二、sigmoid函数 &#xff08;1&#xff09;公式&#xff1a; &#xff08;2&#xff09;sigmoid函数的输入 预测函数&#xff1a; 以下是sigmoid函数代码&#xff1a; 三、梯度上升 &#xff08;1&#xff09;似然函数 公式&#xff1a; 概念&#xff…

Android存储系统成长记

用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章 本文概要 您一定使用过Context的getFileStreamPath方法或者Environment的getExternalStoragePublicDirectory方法&#xff0c;甚至还有别的方法把数据存储到文件中&#xff0c;这些都是存储系统提供的服务&#x…

【代码随想录——回溯算法——三周目】

1. 子集2 这题需要先进行排序&#xff0c;和候选人那题类似。防止出现重复的子集。 func subsetsWithDup(nums []int) [][]int {path : make([]int, 0)res : make([][]int, 0)sort.Ints(nums)var dfs func(nums []int, start int)dfs func(nums []int, start int) {res app…

08Django项目--用户管理系统--查(前后端)

对应视频链接点击直达 TOC 一些朋友加我Q反馈&#xff0c;希望有每个阶段的完整项目代码&#xff0c;那从今天开始&#xff0c;我会上传完整的项目代码。 用户管理&#xff0c;简而言之就是用户的增删改查。 08项目点击下载&#xff0c;可直接运行&#xff08;含数据库&…

1967python多媒体素材管理系统mysql数据库Django结构layUI布局计算机软件工程网页

一、源码特点 python Django多媒体素材管理系统是一套完善的web设计系统mysql数据库 &#xff0c;对理解python编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 开发环境pycharm mysql 5.0 到5.5 依赖包 Dj…

推荐丨 IP地址如何申请SSL证书实现https

为IP地址申请SSL证书可以让用户通过HTTPS协议安全地访问直接绑定到IP地址的网站或服务。以下是申请IP地址SSL证书的一般步骤&#xff1a; 1 选择支持IP证书的CA&#xff1a;直接为IP地址颁发SSL/TLS证书并不常见&#xff0c;国内厂商JoySSL有提供IP证书&#xff0c;登录其官网…

东莞MES管理系统在电子工厂的益处

东莞MES管理系统对东莞电子企业带来了许多好处&#xff0c;包括但不限于以下几点&#xff1a; 提高生产效率&#xff1a;MES系统可以优化生产计划、监控生产过程&#xff0c;提高生产效率&#xff0c;减少生产中的浪费和停机时间&#xff0c;提高产能利用率。 优化库存管理&a…

R可视化:另类的柱状图

介绍 方格状态的柱状图 加载R包 knitr::opts_chunk$set(echo TRUE, message FALSE, warning FALSE) library(patternplot) library(png) library(ggplot2) library(gridExtra)rm(list ls()) options(stringsAsFactors F)导入数据 data <- read.csv(system.file(&qu…

M00238-固定翼无人机集群飞行仿真平台MATLAB完整代码含效果

一个小型无人机集群仿真演示平台&#xff0c;使用matlab和simulink搭建。 给出的例子是5架的&#xff0c;当然如果你愿意花时间&#xff0c;也可以把它扩展到10架&#xff0c;20架甚至更多。 输入&#xff1a;5架飞机的规划路径 输出&#xff1a;每架无人机每个时刻的13个状态量…

如何将天猫内容保存为PDF格式?详细步骤与实战解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;保存天猫内容的重要性 二、环境准备与工具安装 1. 安装必要的Python包…

2024年电工杯高校数学建模竞赛(B题) 建模解析| 大学生平衡膳食食谱的优化设计

问题重述及方法概述 问题1&#xff1a;膳食食谱的营养分析评价及调整 数学方法&#xff1a;线性规划模型、营养素评价模型、比较分析 可视化数据图&#xff1a;营养素含量表、营养素摄入量对比图、营养素缺乏情况图 问题2&#xff1a;基于附件3的日平衡膳食食谱的优化设计 数…

idea 中配置 Java 注释模板

引言&#xff1a; 在软件工程中&#xff0c;良好的代码注释习惯对于项目的可维护性和可读性至关重要。IntelliJ IDEA&#xff0c;作为一款强大的Java开发IDE&#xff0c;提供了灵活的注释模板配置功能&#xff0c;帮助开发者快速生成规范的代码注释。本文将详细介绍如何在Inte…

2024年上半年信息系统项目管理师下午真题及答案(第二批)

试题一 某项目计划工期为10个月&#xff0c;预算210万元&#xff0c;第7个月结束时&#xff0c;项目经理进行了绩效评估&#xff0c;发现实际完成了总计划进度的70%。项目的实际数据如表所示&#xff1a; 单击下面头像图片领取更多软考独家资料

【Ambari】Docker 安装Ambari 大数据单机版本

目录 一、前期准备 1.1 部署 docker 1.2 部署 docker-compose 1.3 版本说明 二 、镜像构建启动 2.1 系统镜像构建 2.2 安装包源镜像构建 2.3 kdc镜像构建 2.4 集群安装 2.5 容器导出为镜像 三、Ubuntu环境安装测试 3.1 环境准备 3.2 集群容器启动 一、前期准备 1.…