【JVM】运行时内存分配(jvm内存分配的两种方式)

  本篇文章为你整理了【JVM】运行时内存分配(jvm内存分配的两种方式)的详细内容,包含有jvm运行时内存分区 jvm内存分配的两种方式 jvm如何管理内存,内存区域划分和动态分配原理 jvm内存划分哪些区域 【JVM】运行时内存分配,希望能帮助你了解 【JVM】运行时内存分配。

  程序计数器

  用于标识线程执行到了字节码文件(class文件)的哪一行,当执行native方法时,值为undefined,各个线程私有

  Java虚拟机栈

  每个线程独有,每个方法执行时会创建一个栈帧,用于存储局部变量表等方法信息,即方法的执行会伴随着一个栈帧的入栈出栈。

  栈帧的组成

  

  

  如果线程请求的栈深度大于虚拟机允许的最大深度,将抛出StackoverflowError异常

  栈最大深度由栈内存大小和局部变量表大小确定,即栈大小固定,局部变量表越大,栈深度越小,栈大小可通过-Xss参数设置,默认为1m

  如果栈动态扩展失败,会抛出OutOfMemoryError异常,不过hotspot虚拟机不支持栈动态扩展,申请时失败了,会抛出OOM异常

  本地方法栈

  虚拟机执行native方法时使用,与Java虚拟机栈类似,hotspot将二者合在一起

  Java堆

  用于存储Java实例对象,垃圾收集器管理的内存区域,也称为GC堆(Garbage Collected Heap)。垃圾收集就发生在该区域,一般分为eden,servivor1,servivor2,old。

  另外在Java8之前还有一个永久代,不过永久代实际上不属于堆内存,属于虚拟机内存,同时受垃圾收集器管理(fullgc时触发垃圾回收)。Java8之后删除了永久代,将方法区移动至元空间(Metaspace),使用native内存,移除虚拟机,防止OOM异常,元空间大小可以通过-XX:MaxMetaspaceSize参数控制,fullgc时会对元空间进行垃圾回收;将字符串常量(JDK 7)迁移到Java堆中。

  Java堆所有线程共享,不过可以通过设置TLAB(ThreadLocalAllocationBuffer)给各线程预留内存,提高内存分配时的效率。

  Java堆可以通过-Xms和-Xmx设置初始大小和最大大小(虽然现在的项目一般将两个值设为相同以减少GC次数),当动态申请内存不足时,会抛出OOM异常。

  用于存储已经被Java虚拟机加载的类型信息,常量,静态变量和即时编译器编译后的代码缓存等数据。Java8之前通过永久代实现,Java8之后通过元空间实现,实际为一个逻辑内存区域,多线程共享。Java的元空间会在fullgc时进行垃圾回收,主要进行类的卸载时方法区的垃圾回收。当内存分配出现不足时,会抛出OOM异常。

  运行时常量池

  属于方法区的一部分,用于存储类的版本,方法,字段,接口等描述信息,同时接受新的常量,例如String.intern()方法将字符串放入常量池中,实际将char[]存储到堆中的字符串常量池中,将引用存储到运行时常量池中。当内存不足时,抛出OOM异常。

  注意,运行时常量池不等于字符串常量池,上面说了,字符传常量池在(JDK 7后移入)堆(老年代)中,而运行时常量池实际存储在元空间中

  直接内存不属于JVM虚机内存的一部分,属于native内存,JDK1.4后推出的NIO即可以直接操作Native内存,通过在Java堆中创建DirectByteBuffer对象控制Native内存。

  以上就是【JVM】运行时内存分配(jvm内存分配的两种方式)的详细内容,想要了解更多 【JVM】运行时内存分配的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: