GC-MetaScace的理解
一些看过Java8以后的垃圾回收日志的一般会对这么一句话感到很困惑:
Metaspace used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
class space used 262K, capacity 386K, committed 512K, reserved 1048576K
第一个问题是,按照一般的理解,metaspace似乎是一个整体,怎么还分成了四个部分?
第二个问题是,怎么metaspace之后,还有一个class space?两者之间的关系是怎样的?
先来看一幅图:

首先可以看到的是,这些used,capacity,committed和reserved并不纯粹是JVM的概念,它和操作系统相关。
先来看committed和reserved。reserved是指,操作系统已经为该进程“保留”的。所谓的保留,更加接近一种记账的概念,就是操作系统承诺说一大块连续的内存已经是你这个进程的了。注意的是,这里强调的是连续的内存,并且强调的是一种名义归属。那么实际上这一大块内存有没有真实对应的物理内存呢?答案是不知道。
那么什么时候才知道呢?等进程committed的时候。当进程真的要用这个连续地址空间的时候,操作系统才会分配真正的内存。所以,这也就是意味着,这个过程会失败。
举个例子来说,就好比张三找李四借钱,张三说借1000,李四在本子上记录了一笔说可以,借给你了,但是暂时不能给你,等你要用的时候再来领。于是过了一天,张三来领了300,这300就是committed的,之前那1000就是reserved的。很显然,如果李四给太多人都记了一笔,说不定等张三去借的时候,就没有了。
因此,这个reserved更加接近记账的概念。
used和capacity就是JVM的概念了。这两个概念非常接近JVM一些集合框架的概念。一些Java集合框架,比如某种List的实现,会有size和capacity的概念。比如说ArrayList的实现里面就有capacity和size的概念。假如说我创建了一个可以存放30个元素的ArrayList,但是我实际上只放了20个元素,那么capacity就是30,而size就是20.这里的size和used就是一个概念。那么“元素”则是一个个内存块"block“。
capacity和committed的关系也可以此类比,只不过capacity反而对应到used,committed对应到capacity,而所谓的”元素“,就是chunk。
至于class space,要记住的是,metaspace并不是全部用来放类对象的。比如说,因为每一个ClassLoader都被分配了一块内存,这块内存可能并没有被用完,于是就会有一些内存碎片;metaspace还需要放所谓静态变量。所以,class space是指实际上被用于放class的那块内存的和。
浙公网安备 33010602011771号