深入Java虚拟机(一):Java内存区域

本文深入解析Java内存区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池及直接内存。涵盖各区域特性、作用、异常情况及JDK1.8的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java内存区域:

      程序计数器(Program Counter Register)

      (1)线程私有

      (2)当线程在执行一个Java方法时,该计数器记录的是正在执行的虚拟机字节码指令的地址;

         当线程在执行的是Native方法(调用本地操作系统方法)时,该计数器的值为空。

      (3)唯一一个在Java虚拟机规范中么有规定任何OOM(内存溢出:OutOfMemoryError)情况的区域。

 

      Java虚拟机栈(Java Virtual Machine Stacks)

       (1)线程私有的,生命周期与线程相同。

       (2)虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,栈帧用于存储局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息。在编译程序代码时,栈帧中需要多大的局部变量表、多深的操作数栈都已经完全确定了,并且写入了方法表的Code属性之中。因此,一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

        (3)在Java虚拟机规范中,对这个区域规定了两种异常情况:

                  a)  如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。

                  b)  如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

       本地方法栈(Native Method Stacks)

        (1)线程私有

        (2) 该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为使用到的本地操作系统(Native)方法服务。与虚拟机栈一样,本地方法栈也会抛出StackOverflowError异常和OutOfMemoryError异常。

 

       Java堆(Java Heap)

     (1)线程共享,没有空间时将抛出OutOfMemoryError异常。

     (2)所有的对象实例以及数组都要在堆上分配(例外:逃逸分析技术比如栈上分配)

     (3)细分:

         Young Generation(年轻代)、Old Generation(年老代)以及Perm Generation(永久代)。其中的Young Generation(年轻代),又分为Eden、From和To,其中From和To又统称为Survivor Spaces(幸存区)。

 

       方法区(Method Area)

           (1)线程共享

           (2)它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区域又被称为“永久代”,但这仅仅对于Sun HotSpot来讲,JRockit和IBM J9虚拟机中并不存在永久代的概念。垃圾回收行为在这个区域是比较少见的。

          (3)根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。


       运行时常量池 (Ruentime Constnat Pool)

           (1)属于方法区的一部分。

          (2)用于Class文件的各种字面量和符号引用。

          (3)运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,Java语言并不要求常量一定只能在编译期产生,运行期间也可能将新的常量放入池中,如String类的intern()方法。

       直接内存(Direct Memory)

             直接内存并不是Java虚拟机中的内存区域,它直接从操作系统中分配,可以利用DirectByteBuffer实现Netty的零拷贝。

jdk1.8变化

JDK 1.6下,会出现“PermGen Space”的内存溢出,而在 JDK 1.7和 JDK 1.8 中,会出现堆内存溢出,并且 JDK 1.8中 PermSize 和 MaxPermGen 已经无效。因此,可以大致验证 JDK 1.7 和 1.8 将字符串常量由永久代转移到堆中,并且 JDK 1.8 中已经不存在永久代的结论。

  元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

  -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

 除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值