读书笔记——深入理解Java虚拟机之Java 运行时数据区域

  • 谈谈对 Java 运行时数据区域 有何理解
    • 概述:
      • JVM在执行 Java 时会将其所管理的内存划分为若干个不同的数据区域。各区域有各自的用途,创建和销毁的时间,有的随着jvm的启动而存在,有的根据用户线程的启停而创建或销毁。
    • 划分:
      • 程序计数器-Program Counter Register

        • 概念:当前线程所执行的字节码的行号指示器。线程私有。
        • 作用:字节码解释器工作时通过改变该计数器的值来选取下一条需执行的字节码指令,分支,循环,跳转或异常处理,线程恢复都需依赖该计数器。
        • 题外话:
          • Java 多线程通过线程轮流切换并分配处理器执行时间来实现,任一时刻,一个处理器都只执行一个线程中的指令。为了线程切换后可恢复到正确的执行位置,每一线程都需要独立的程序计数器,线程之间互不影响。
          • Java方法而言,计数器记录的时正在执行的字节码指令的地址;Native方法而言,计数器值为Undefined。
          • 此内存区域是jvm规范中唯一没有规定OutOfMemoryError的区域。
      • Java虚拟机栈

        • 概念:描述的是Java方法执行的内存模型,方法执行时创建的栈帧 存储 局域变量表,操作数栈, 动态链接,方法出口等,方法的调用到执行完成对应着栈帧在jvm中的入栈和出栈。线程私有。
        • 作用:相当于我们所说的栈内存Stack,存放指向原始对象起始位置的引用指针,句柄。
        • 异常情况:
          • 线程请求的栈深度大于jvm允许的深度时,抛出StackOverFlowError;但若对应的虚拟机栈可动态扩展并且扩展时无法申请到足够的内存,则会OutOfMemoryError。
      • 本地方法栈

        • 概念:描述的是Java Native方法的内存模型,类似于Java虚拟机栈,也会抛出上述的两个Error。
      • Java 堆

        • 概念:垃圾收集器管理的主要区域,称为GC堆,占内存最大的一块,线程共享。可细分为新生代和老年代,再细分为Eden、From Survivor、To Survivor空间等。为了更好更快速地分配内存,Java堆中还划分出了多个线程私有的分配缓冲区-Thread Local Allocation Buffer。
        • 作用:在堆上分在jvm启动时创建,用以存放对象实例,所有的对象实例和数组都配,但随着JIT编译器的发展和逃逸分析技术的成熟,栈上分配和标量替换优化技术也导致一些变化,所有的对象都在堆上分配也不那么绝对了。【reference link】https://blog.csdn.net/w372426096/article/details/80333657
        • 题外话:java堆可以物理上不连续但逻辑上必须连续,类似磁盘空间一样。当前主流的jvm都是按照可扩展来实现的—— -Xmx和 -Xms的控制。但当在堆中没有多余的内存完成实例分配并且堆也无法扩展时——OutOfMemoryError。
      • 方法区

        • 概念:线程共享,别名为Non-Heap(非堆)。
        • 作用:存储被jvm加载过的类信息,常量,静态变量以及JIT编译后的代码。
        • 题外话:
          • 《Java虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。在不同的 JVM 上方法区的实现有差异。同时大多数用的JVM都是Sun公司的HotSpot。在HotSpot上把GC分代收集扩展至方法区,或者说使用永久代来实现方法区。永久代是HotSpot的概念,方法区是Java虚拟机规范中的定义,是一种规范,而永久代是一种实现,一个是标准一个是实现。其他的虚拟机实现并没有永久带这一说法。在1.7之前,HotSpot 使用永久代实现方法区,HotSpot 使用 GC分代来实现方法区内存回收。
          • 永久代的概念在jdk1.8后被元空间一词取代。
      • 运行时常量池

        • 概念:方法区的一部分。
        • 作用:在Class文件常量池中存放编译期产生的字面量(String a = “a”,"a"就是字面量)和符号引用,在类加载后进入方法区的运行时常量池。
        • 题外话:
          • 运行时常量池相对于Class文件常量池有一个特征:动态性。
          • Java不要常量只在编译器产生,也就是:并非只有预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行时也会有新的常量进入运行时常量池中,e.g:String.intern()方法。
      • 直接内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值