jvm内存空间 可以划分为方法区,堆,本地方法,pc寄存器,以及jvm方法栈 如下图
下面分别介绍这几块内容:
一 jvm方法区
方法区中存放了要加载的类的信息 包括类的名称修饰符等,类中的静态变量、类中定义为final类型的常量,类中的field信息,类中的方法信息 当程序调用getName isInterface方法获取信息时这些属于都是源自于该方法区。方法区域也是全局共享的,在一定条件下会被gc 当该方法区超过运行的大小时会抛出OutOfMemory的错误信息。
在sun的jdk中该区对应的permanet generation 又称为持久代 默认最小为16mb 最大为64mb 可以通过 -XX:permSize以及-XX:MaxPerSize 来指定最小值和最大值
二 jvm 堆
堆是用来存储对象实例和数组值,可以认为是java中所有通过new创建的对象的内存都在此分配 heap中对象所占用的内存由gc回收 在32位操作系统上最大为2G 64位上则没有限制。其大小可以通过-Xms和-Xmx来控制。 当默认堆内存空间小于40%时,jvm会增大堆内存到-xmx的大小,通过指定 -xx:minHeapFreeRatio可以来自己设定比例,当空余堆大于70%
时jvm会减小堆的大小到-xms指定的大小,可以通过-xx:MaxHeapFreeRatio来指定这个比例。对于系统运行而言,为了避免在运行过程中频繁调整heap的大小,通常将-Xms和zxmx的值设置为一样。
为了提高内存管理 jvm内存堆又进行了分代管理
分为:1 新生代 2 旧生代
1 新生代 大多是情况下java中程序新建对象都是从新生代中分配内存,新生代是有eden space和两块大小相同的survivor space s0 和s1 可以通过-xmn参数来指定新生代的大小。
可以通过-xx:survivorratio 来调整eden space和surviror space的大小,不同的gc 的分配方式不同,也有些gc会动态调整eden space和s0 s1的大小。
2 旧生代
用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建对象也有可能在旧生代中直接分配内存,主要情况有两种:
一种是大对象,可以再启动参数上设子-xx:pretenureSizeThreshold=1024(单位是字节)来代表当前对象超过多大时就直接在旧生代直接分配内存,此参数在新生代采用paralel scavenge gc时无效,parallel scavenge gc 会根据运行状况来决定什么对象直接在旧生代上分配内存
另外一种是数组对象 且数组中无引用外部对象
三 本地方法栈
本地方法栈用于支持native运行,存储了每个navigate方法的调用状态,在sun jdk的视线中本地房发展和jvm方法栈是同一个栈区。
四 pc寄存器和jvm方法栈
每个线程中均会创建pc寄存器和jvm方法栈 pc寄存器占用的可能是cpu寄存器或操作系统内存,jvm方法栈占用的是操作系统内存,jvm方法栈为线程私有,其在内存分配上非常高效
当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。 当jvm方法栈空间不足时会抛出StackOverflowError错误,在sun的jdk中可以通过-xss来指定其大小