jvm配置一启动就占用全部资源_JVM运行时占用的内存

一个线上服务内存占用带来的问题

在Oracle官网给出的JVM调优文档中关于堆的调整技巧有以下三个方面:

1.应将堆大小设置为不超过最大可用物理RAM量。如果超过此值,操作系统将开始分页,性能会显着下降。VM总是使用比堆大小更多的内存。除了堆大小设置之外,还分配内部VM功能所需的内存,VM外部的本地类库和永久区(仅适用于Sun虚拟机:存储类和方法所需的内存)。

2.使用分代垃圾收集方案时,年轻代大小不应超过Java堆总大小的一半。通常,堆大小的25%到40%就足够了。

3.在生产环境中,将最小堆大小和最大堆大小设置为相同的值,以防止浪费用于

不断增长和收缩堆的VM资源。

第三点将初始堆大小设置和最大堆大小相同,可以减少JVM重新分配内存,伸缩J堆大小时候的GC压力,在线上实际运行的时候给-Xms和-Xmx参数均设置成2048m,可是使用htop命令查看进程消耗的内存时候,发现只使用了1098m。Xms是设置初始堆和最小堆的大小,难道出问题了么?使用jmap命令输出堆的实际情况,如下:

[root@pc ~]# jmap -heap 15189

Attaching to process ID 15189, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 25.202-b08

using thread-local object allocation.

Parallel GC with 2 thread(s)

Heap Configuration:

MinHeapFreeRatio = 0

MaxHeapFreeRatio = 100

MaxHeapSize = 2147483648 (2048.0MB)

NewSize = 715653120 (682.5MB)

MaxNewSize = 715653120 (682.5MB)

OldSize = 1431830528 (1365.5MB)

NewRatio = 2

SurvivorRatio = 8

MetaspaceSize = 21807104 (20.796875MB)

CompressedClassSpaceSize = 1073741824 (1024.0MB)

MaxMetaspaceSize = 17592186044415 MB

G1HeapRegionSize = 0 (0.0MB)

Heap Usage:

PS Young Generation

Eden Space:

capacity = 677380096 (646.0MB)

used = 359083872 (342.4490661621094MB)

free = 318296224 (303.5509338378906MB)

53.01069135636368% used

From Space:

capacity = 18874368 (18.0MB)

used = 8472112 (8.079635620117188MB)

free = 10402256 (9.920364379882812MB)

44.886864556206596% used

To Space:

capacity = 18350080 (17.5MB)

used = 0 (0.0MB)

free = 18350080 (17.5MB)

0.0% used

PS Old Generation

capacity = 1431830528 (1365.5MB)

used = 45051784 (42.96472930908203MB)

free = 1386778744 (1322.535270690918MB)

3.14644667221399% used

31785 interned Strings occupying 3781800 bytes.

查看以上信息发现,堆分配大小没有问题的呀!这是为什么呢。。查了一会资料,JVM启动的时候,将虚拟地址与本机物理内存地址进行映射,实际运行的时候并没有使用到2048m内存,在堆内存不够用的时候回向操作系统申请物理内存,而操作系统htop命令查看的内存是RES即实际占用的物理内存,刚启动的时候比实际Xms来的小。

这里会带来两个问题:

第1次YGC之前Eden区分配对象的速度较慢;

YGC的时候,Young区的对象要晋升到Old区的时候,这个时候需要操作系统真正分配内存,这样就会加大YGC的停顿时间;

我们可以给JVM添加-XX:+AlwaysPreTouch这个参数优化这个问题,不过这个参数在JDK8下有一个副作用会大大提高启动时间。

在没有配置-XX:+AlwaysPreTouch参数即默认情况下,JVM参数-Xms申明的堆只是在虚拟内存中分配,而不是在物理内存中分配:它被以一种内部数据结构的形式记录,从而避免被其他进程使用这些内存。这些内存页直到被访问时,才会在物理内存中分配。当JVM需要内存的时候,操作系统将根据需要分配内存页。

配置-XX:+AlwaysPreTouch参数后,JVM将-Xms指定的堆内存中每个字节都写入’0’,这样的话,除了在虚拟内存中以内部数据结构保留之外,还会在物理内存中分配。并且由于touch这个行为是单线程的,因此它将会让JVM进程启动变慢。所以,要么选择减少接下来对每个缓存页的第一次访问时间,要么选择减少JVM进程启动时间

不过在JDK9中可以使用并行操作,Parallelize Memory Pretouch。

这里又有疑问了,当JVM内存申请使用完毕后会返还给物理内存吗?

不会,一旦虚拟机申请分配了物理内存,不会返还。

设置了Xmx参数,JVM一定不会超过这个大小么?超过一定会OOM或者SOF吗?

还有堆外内存。。。

JVM内存占用情况

JVM进程主要占用内存的一些地方,其中JDK8之前JMM模型中共享的永久区取消变为元空间(metaspace)依旧存放于堆外内存之中。

由以上可以看出,JVM实际占用的内存实际上包含堆内和堆外的,而虚拟机启动参数Xms和Xmx限制的是堆的大小,实际虚拟机内存可能大得多。

总结

JVM在默认情况下启动的时候,

JVM参数-Xms申明的堆只是在虚拟内存中分配,而不是在物理内存中分配;

-XX:+AlwaysPreTouch参数可以申请提前占用内存,减少GC消耗,但会提高启动时间;

JVM申请的物理内存,一旦申请不会返还,除非重启或者关闭;

JVM实际占用的内存包括堆内和堆外内存,也就是会大于Xmx设置的值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值