🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。
✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!
🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客
🔥温馨提示:划到文末发现专栏彩蛋 点击这里直接传送
🔥本篇概览:详细讲解了运行时数据区的堆——设置堆的大小与查看堆详细的信息。🌈⭕🔥
【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】
🌈章节引出:
前一篇章:《剑指JVM》——第7章——堆的核心概念——堆1——运行时数据区篇13-CSDN博客
🌈章节速览:
7.2.1 设置堆内存大小
1.默认的内存参数配置原则
Java堆区用于存储Java对象实例,堆的大小在JVM启动时就已经设定好了,可以通JVM 参数“-Xms”和“-Xmx”来进行设置。所示:
“-Xms”用于表示堆区的起始内存,等价于-XX:InitialHeapSize。
“-Xmx”用于表示堆区的最大内存,等价于-XX:MaxHeapSize。
一旦堆区中的内存大小超过“-Xmx”所指定的最大内存,将会抛出内存溢出异常OutOfMemoryError, OOM)。
通常会将“-Xms”和“-Xmx”两个参数配置相同的值。否则,服务器在运行过程中,堆空间会不断地扩容与回缩,势必形成不必要的系统压力。
所以在线上生产环境中,JVM的Xms 和 Xmx 设置成同样大小,避免在 GC后调整堆大小时带来的额外压力。初始内存大小占据物理内存大小的 1/64,最大内存大小占据物理内存大小的 1/4。
下面我们通过代码演示查看堆区的默认配置大小,如代码清单7-4所示。
/**
* 1.设置堆空间大小的参数
* -Xms 用来设置堆空间(新生代+老年代)的初始内存大小
* -X 是 JVM 的运行参数
* ms 是 memory start
* -Xmx 用来设置堆空间(新生代+老年代)的最大内存大小
*
* 2.默认堆空间的大小
* 初始内存大小: 物理电脑内存大小的 1/64
* 最大内存大小: 物理电脑内存大小的 1/4
*
* 3.手动设置: -Xms600m -Xmx600m
* 开发中建议将初始堆内存和最大的堆内存设置成相同的值
*
* 4.查看设置的参数:
* 方式一: jps/jstat -gc 进程id
* 方式二: -XX:+PrintGCDetails
*
* @author atguigu
*/
public class HeapSpaceInitial {
public static void main(String[] args) {
// 返回 JVM 中的堆内存总量
long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
// 返回 JVM 试图使用的最大堆内存量
long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
System.out.println("-Xms(JVM 中的堆内存初始化量): " + initialMemory + "M");
System.out.println("-Xmx(JVM 试图使用的最大堆内存量): " + maxMemory + "M");
System.out.println("系统内存大小为(利用堆的初始内存大小: 物理电脑内存大小的 1/64): " + initialMemory * 64.0 / 1024 + "G");
System.out.println("系统内存大小为(利用堆的最大内存大小: 物理电脑内存大小的 1/4): " + maxMemory * 4.0 / 1024 + "G");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
接下来在命令行中输入如下信息,即可查看本机内存为大致16G。得出的一致。
systeminfo | findstr "物理内存总量"
由图7-8可知,最终计算系统内存大小不到15GB,这是因为内存的制造厂商会有不同的进制计算方式,比如现实是以 1000进制计算 GB,而计算机中是以1024进制计算,这样会出现一定的误差。
2.两种方式查看手动设置的JVM的参数
上面案例讲解了默认的内存参数配置原则,那么通过-Xms 和-Xmx 手动配置了参数之后,程序运行起来后如何查看设置的参数呢?这里设置为
-Xms600M -Xmx600M。
继续以代码清单7-4为例,解开sleep 相关代码的注释,运行代码,然后通过以下两种方式查看设置的参数明细。
(1)JPS+讲解jstat栏目
按 Windows+R键打开命令行,输入“jps”查看进程id,再输入“istat -gc进程 id”命令查看参数配置,如图7-9所示。
通过图7-9我们可以看到isat-gs命令下的结果有很多参数选项,下面我们解释其中参数的含义:
讲解jstat的栏目
S0C S1C S0U S1U EC EU OC OU MC MU CCSC
CCSU YGC YGCT FGC FGCT GCT
这些是与 Java 虚拟机(JVM)的垃圾回收(GC)和内存管理相关的一些指标和参数:
- s0c:年轻代中第一个 survivor(幸存区)的容量(单位:kb)。
- s1c:年轻代中第二个 survivor(幸存区)的容量(单位:kb)。
- s0u:年轻代中第一个 survivor(幸存区)目前已使用空间(单位:kb)。
- s1u:年轻代中第二个 survivor(幸存区)目前已使用空间(单位:kb)。
- ec:年轻代中 eden(伊甸园)的容量(单位:kb)。
- eu:年轻代中 eden(伊甸园)目前已使用空间(单位:kb)。
- oc:old 代(老年代)的容量(单位:kb)。
- ou:old 代目前已使用空间(单位:kb)。
- mc:元数据区(metaspace)已经 committed 的内存空间。
- mu:元数据区的使用量。
- ccsc:压缩 class(compressed class space)committed 的内存空间。
- ccsu:压缩 class 已使用的内存空间。
- ygc:从应用程序启动到采样时年轻代中垃圾回收(GC)的次数。
- ygct:从应用程序启动到采样时年轻代中垃圾回收所用的时间(单位:s)。
- fgc:从应用程序启动到采样时 old 代(全 GC)垃圾回收的次数。
- fgct:从应用程序启动到采样时 old 代垃圾回收所用的时间(单位:s)。
- gct:从应用程序启动到采样时垃圾回收用的总时间(单位:s)。
通过计算可以得到堆内存中的大小,S0C加上S1C、EC、OC的大小,正好就是600MB。
详细讲解CCSC、CCSU
在 64 位平台上,HotSpot 使用了两项压缩优化技术,分别是compressed object pointers
(“compressed oops”)和compressed class pointers
。
compressed class pointers
指的是,每个 Java 对象的头部有一个引用指向元空间(metaspace)中的klass
结构。当使用了compressed class pointers
时,这个引用是 32 位的值。为了找到真正的 64 位地址,需要加上一个基准值(base 值)。
然而,这项技术对klass
的分配带来了问题:由于 32 位地址只能访问到 4GB 的空间,所以最大只允许 4GB 的klass
地址。这意味着 JVM 需要向元空间分配一个连续的地址空间。但当通过调用系统接口malloc(3)
或mmap(3)
从系统申请内存时,操作系统可能返回任意一个地址值,它并不能保证在 4GB 的范围内。
因此,只能用一个mmap()
来申请一个区域单独用来存放klass
对象。由于需要提前知道这个区域的大小,而且不能超过 4GB,这种方式是不能扩展的,因为这个地址后面的内存可能是被占用的。
只有klass
结构有这个限制,对于其他的类元数据(class metadata)则没有必要,因为只有klass
实例是通过 Java 对象头部中的压缩指针访问的,其他的元数据都是通过 64 位的地址进行访问,所以它们可以被放到任意的地址上。
基于此,将元空间分为了两个区域:
non-class part
:包含其他所有的元数据;class part
:存放klass
对象,需要一个连续的不超过 4GB 的内存,这个区域被称作compressed class space
。
compressed class space
空间的大小可以通过-XX:CompressedClassSpaceSize
指定,其默认值是 1GB。需要注意的是,这里的 1GB 并不是真正使用了操作系统的 1GB 物理内存,而是虚拟地址映射。
另外,有两个相关的开关:
-XX:+UseCompressedOops
:允许对象指针压缩;-XX:+UseCompressedClassPointers
:允许类指针压缩。
它们默认都是开启的,也可以手动关闭。如果不允许类指针压缩,那么将没有compressed class space
这个空间,并且-XX:CompressedClassSpaceSize
这个参数无效。
同时,-XX:-UseCompressedClassPointers
需要搭配-XX:+UseCompressedOops
,但反过来则不是必须的。也就是说,可以只压缩对象指针,而不压缩类指针。这可能是因为从直觉上来说,压缩对象指针能获得较大的收益,相对更为重要。
此外,对象指针压缩要求堆小于 32GB,如果堆大于等于 32GB,那么对象指针压缩和类指针压缩都会被关闭。
在使用jstat
命令查看 Java 虚拟机的统计信息时,ccsc
(Compressed Class Space Committed)表示压缩类空间(compressed class space)已提交的内存空间大小。它反映了当前实际为compressed class space
分配的内存量。通过观察ccsc
的值,可以了解到compressed class space
的使用情况,以便进行内存管理和优化。如果发现ccsc
的值接近或达到了设置的上限,可能需要考虑调整相关的内存参数,或者优化类的数量和大小等,以避免出现内存不足的情况。
(2)设置 VM options 为“-XX:+PrintGCDetails”
在IDEA中进行设置 VM options 为“-XX:+PrintGCDetails”,参数配置如图1.
所示。
打印下来的信息如图:
补一嘴,说到上面的CPU啥的,下面是自己的电脑配置:
技术面要广系列——自己电脑的配置-CSDN博客
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
热门专栏推荐
🌈🌈计算机科学入门系列 关注走一波💕💕
🌈🌈CSAPP深入理解计算机原理 关注走一波💕💕
🌈🌈微服务项目之黑马头条 关注走一波💕💕
🌈🌈redis深度项目之黑马点评 关注走一波💕💕
🌈🌈JAVA面试八股文系列专栏 关注走一波💕💕
🌈🌈JAVA基础试题集精讲 关注走一波💕💕
🌈🌈代码随想录精讲200题 关注走一波💕💕
总栏
🌈🌈JAVA基础要夯牢 关注走一波💕💕
🌈🌈JAVA后端技术栈 关注走一波💕💕
🌈🌈JAVA面试八股文 关注走一波💕💕
🌈🌈JAVA项目(含源码深度剖析) 关注走一波💕💕
🌈🌈计算机四件套 关注走一波💕💕
🌈🌈数据结构与算法 关注走一波💕💕
🌈🌈必知必会工具集 关注走一波💕💕
🌈🌈书籍网课笔记汇总 关注走一波💕💕
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!