我开始怀疑堆栈内存(与JVM堆不同)似乎是预先提交的,而没有驻留,并且随着时间的流逝,驻留内存仅达到实际堆栈使用率的最高水位。
是的,除非另有说明,至少在Linux上,mmap是懒惰的。页面仅在写入后才由物理内存支持(由于零页面优化,因此读取不足)
GC堆内存有效地被复制收集器或预调零(
-XX:+AlwaysPreTouch)所触及,因此它将始终处于驻留状态。线程堆栈otoh不受此影响。
为了进一步确认,您可以使用
pmap -x <java pid>各种地址范围的RSS并将其与NMT虚拟内存映射的输出交叉引用。
保留的内存已与映射
PROT_NONE。这意味着虚拟地址空间范围在内核的vma结构中具有条目,因此不会被其他mmap /
malloc调用使用。但是它们仍然会导致页面错误以SIGSEGV的形式转发到进程,即访问它们是一个错误。
这对于使连续的地址范围可供将来使用很重要,这反过来又简化了指针运算。
例如,已提交但未由存储支持的内存已映射-
PROT_READ |PROT_WRITE但访问它仍会导致页面错误。但是,该页面错误由内核静默处理,方法是将其与实际内存一起备份,并像没有任何反应一样返回执行。
也就是说,这是一个实现细节/优化,流程本身不会注意到。
细分概念:
Used Heap :根据最后一个GC,活动对象占用的内存量
提交 :已使用除PROT_NONE之外的其他内容映射的地址范围。由于延迟分配和分页,它们可能会或可能不会由物理或交换支持。
保留 :已
mmap为特定内存池预先映射的总地址范围。
该 预留-致力于 差由
PROT_NONE映射,这是保证不被物理存储器被备份
常驻
:当前处于物理内存中的页面。这意味着代码,堆栈,已提交的内存池的一部分,以及最近已被访问的mmaped文件的一部分,以及JVM控制范围之外的分配。
虚拟
:所有虚拟地址映射的总和。涵盖已提交,保留的内存池,还包括映射文件或共享内存。这个数字很少提供信息,因为JVM可以提前保留很大的地址范围或mmap大文件。



