• jvm读书记录1-Java虚拟机运行时数据区域


    Java虚拟机运行时的内存数据区域可分为:

    1. 方法区
    2. 虚拟机栈
    3. 本地方法栈
    4. 程序计数器

    其中堆和方法区由线程共享;虚拟机栈、本地方法区、程序计数器线程隔离的,即每个线程都有。

    下面简单描述下上述的各个分区的职责和功能

    一、程序计数器

    程序计数器是一块较小的内存空间,在java虚拟机的概念模型里面,字节码解释器工作时,通过改变这个计数器来选去下一个要执行的字节码指令,他是程序控制流的指示器;包括:分支、循环、异常处理、线程恢复。

    java虚拟机的多线程时通过线程轮流切换、分配处理器执行时间的方式来实现的。因此,为了线程切断后能恢复到正确的执行位置,每天线程都需要一个独立的程序计数器。

    二、Java虚拟机栈

    Java虚拟机栈时线程私有的,他的生命周期与线程相同。

    虚拟机栈描述的是java方法执行的线程内存模型:

    每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中从入栈道出栈的过程。

    局部变量表

    局部变量表存放了编译器可知的各种java虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,他并不等同于对象本身,可能是一个指向对象其实地址的引用指针,也可能是指向一个代表对象的句柄会在与此对象相关的位置)。

    这些数据类型在局部变量表中的存储空间以局部变量槽来表示,局部变量表在内存空间编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的空间时完全确定的,在方法运行期间不会改变大小。这里的大小指的是变量槽的数据,实际大小和虚拟机真正使用多大的空间有关系;例如一个变量槽占用多少bit。

    在这个内存区域有两类异常

    • StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度
    • outofmemoryerror:java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存

    HotSpot虚拟机的栈容量时不可扩展的,classic可以。所以在hotspot虚拟机上时不会出现oom异常的,只要线程申请栈空间成功就不会oom(会StackOverflowError),如果申请失败则会时oom;

    三、本地方法栈

    本地方法栈和虚拟机栈发挥的作用非常相似,区别就是虚拟机栈位虚拟机执行java方法服务,而本地方法方法栈则为虚拟机使用到的本地方法服务。本地方法栈也会抛出StackOverflowError和oom异常。

    四、Java 堆

    Java堆事所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java世界里面“几乎”所有的对象实例都在这里分配内存。

    Java堆事垃圾收集器管理的内存区域,从内存回收的角度看,现代垃圾收集器大部分都是基于分代收集理论设计的(例如:新生代、老年代;eden空间、from survivor空间、tosurvivor空间),但是也有不分代设计的垃圾收集器。

    如果从分配内存的角度看,所有的线程共享的java堆中可以划分出多个线程私有的分配缓冲区(TLAB),以提升对象分配时的效率。

    五、方法区

    方法区与堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

    方法区与永久代

    在hotspot虚拟机上,有的人把方法区称呼为永久代。这个其实是因为当时hotspot虚拟机当时选择把收集器的分代设计扩展至方法区,好省掉为方法区单独编写垃圾收集的工作。到了jdk 7 的hotspot已经把原本放在永久代的字符串常量池、静态变量移出,到了jdk8 已经完全废弃了永久代。

    方法区的垃圾收集目标主要是针对常量池的回收和类型的卸载,方法区也会出现oom的异常。

    六、直接内存(堆外内存)

    直接内存并不是虚拟机运行时数据区的一部分。这部分内存的使用例子可以参考spark的内存管理里面的对外堆外内存。

    在使用jvm堆内内存的时候,虽然spark做了逻辑上的内存管理《统一内存管理模型》,但是在标记对象释放,其实还是依赖的jvm,jvm如果释放不及时的话,就可能出现oom。同时可以避免频繁的GC,减少了不必要的内存开销。

    为了更好的管理内存,spark增加了对堆外内存的设置,由spark自己管理,提升了处理性能。

    参考:

    《深入理解Java虚拟机》周志明

    https://blog.csdn.net/pre_tender/article/details/101517789

  • 相关阅读:
    TinyOS在ubuntu 14.04下安装教程
    C++ STL标准入门
    C++ 模板
    多态
    C++继承
    C++类型转换 -- 由其他类型转换到自定义类型
    运算符重载
    友元
    typedef用法
    c++细节--section1
  • 原文地址:https://www.cnblogs.com/ldsggv/p/15487003.html
Copyright © 2020-2023  润新知