空空叶博客 学习与开发博客

内存模型

2017-05-05

内存模型

JVM规定的数据区域(类型)

1. pc寄存器(pc register)

每个线程都有一个pc寄存器

任何时候,每个线程都在执行一个方法,叫做当前方法,如果此方法非native,则pc寄存器会保存当前执行的地址;如果此方法是native的,则pc寄存器的值是undefined

2. java虚拟机栈

每个线程都有个私有的虚拟机栈,在线程建立时建立.

因为只会进行出栈与入栈frame操作,因此内存区域不需要是连续的

大小可以是固定或可变的,如果是固定的,则虚拟机栈建立时可以自行决定大小

如果某个线程内的某个计算需要的虚拟机栈大小超过上限,则会抛出StackOverflowError

当虚拟机栈可扩展,但扩展时内存不足或新建线程时内存不足,则会抛出OutOfMemoryError

3. 堆(heap)

所有线程共享heap

虚拟机启动时建立heap

其中的对象会被GC检测回收

内存区域不需要是连续的

大小可以是固定或可变的

如果某个计算需要的heap内存超过上限,则会抛出OutOfMemoryError

4. 方法区

逻辑上包含在heap内

所有线程共享方法区

虚拟机启动时建立方法区

内存区域不需要是连续的

大小可以是固定或可变的

存储每个类的结构,包括常量池与field与method数据与代码

可能抛出OutOfMemoryError

5. 运行时常量池

逻辑上包含在方法区内

是属于每个类或接口的

当类或接口建立时,运行时常量池也建立

可能抛出OutOfMemoryError

6. 本地方法栈

虚拟机可以不支持本地方法

本地方法: 指用非java语言编写的方法

属于线程,线程建立时建立

大小可以是固定或可变的

如果需要某个线程的计算需要的本地方法栈超出上限,则抛出StackOverflowError

当本地方法栈可扩展,但扩展时内存不足或新建线程时内存不足,则会抛出OutOfMemoryError

内存池(位置)

Metaspace

默认最大容量没有限制,即只受系统限制(如32位或64位及是否使用虚拟内存)

MaxMetaspaceSize: 用来限制Metaspace最大容量的参数

什么时候GC? 当大小达到MaxMetaspaceSize时进行GC,会对dead classes and classloaders进行处理

说明 从1.7的PermGen到1.8的Metaspace,但内存泄露仍然存在(通常由应用动态重新部署引起的)

Code Cache

JVM生成的Native Code会保存在Code Cache中,一般使用Code Cache的大户是JIT

启动参数

大小:

参数名 默认值 描述
InitialCodeCacheSize 160K (varies) 初始大小
ReservedCodeCacheSize 32M/48M 保留(最大)大小
CodeCacheExpansionSize 32K/64K 扩张大小

Flush:

| 参数名| 默认值| 描述| | :——– | ——–:| :——: | | ExitOnFullCodeCache|false|Code Cache满时退出JVM| | UseCodeCacheFlushing|false|是否在关闭编译器(compiler)前尝试清扫(sweep)code cache| | MinCodeCacheFlushingInterval|30|两次清扫(sweep)最小间隔(单位秒)| | CodeCacheMinimumFreeSpace|500K|当剩余空间不足此大小时,停止编译(此空间保留给非编译方法,如native adapters)| 注:

  • 什么时候关闭编译器?当Code Cache满时
  • CodeCacheMinimumFreeSpace一般至少分配100K,否则JVM可能抛出VirtualMachineError 错误,甚至少数情况下还会崩溃

编译Policy:

参数名 默认值 描述
CompileThreshold 1000 or 1500/10000 在(重新)编译前最大解释执行的方法调用次数
OnStackReplacePercentage 140 to 933 NON_TIERED number of method invocations/branches (expressed as a percentage of CompileThreshold) before (re-)compiling OSR code

编译限制:

参数名 默认值 描述
MaxInlineLevel 9 max nested calls that are inlined
MaxInlineSize 35 Max bytecode size of a method to be inlined
MinInliningThreshold 250 Min invocation count a method needs to have to be inlined
InlineSynchronizedMethods true Inline synchronized methods

诊断选项:

参数名 默认值 描述
PrintFlagsFinal false Print all JVM options after argument and ergonomic processing
PrintCodeCache false 退出时打印code cache内存使用
PrintCodeCacheOnCompilation false 每次方法编译时打印code cache内存使用

compressed class space

参数:

参数名 默认值 描述
CompressedClassSpaceSize 1G 最大compressed class space的空间

heap

通常是占用空间最大的

maximum: 硬性的最大限制,超过则会抛出OutOfMemory错误 committed: 实际分配的内存,只要成功committed的内存都是可以使用的 used: 实际存储使用的内存

used的内存大小接近committed的内存大小时JVM会做什么? 一般会进行GC或请求分配更多内存(加大committed的内存)

什么情况下无法committed更多的内存? 当虚拟内存不够时.

committed的内存超过物理内存时,程序效率会下降吗? 是的,这种情况下,部分会被转换为分页文件,导致GC时很缓慢,此时减少heap大小可提高效率.

通俗的描述: 比如限制程序最大heap(maximum heap)为1G,开始程序申请了100M内存(committed heap),然后实际使用了60M(used heap)存储数据,当使用的内存接近100M时,GC后发现可用内存还是很少,JVM就去再申请更多的内存(committed heap)供使用.


上一篇 一种缓存架构

下一篇 内存泄露

目录