• JVM内存详解


    JVM内存详解

    Java虚拟机的运行时内存空间可以分成五个部分

    • 程序计数器
    • 虚拟机栈
    • 本地方法栈
    • 方法区

    内存划分示意图:

    程序计数器

    作用

    • 当前线程所执行的字节码的行号指示器
    • 通过改变程序计数器的值来选取下一条要执行的字节码指令。
    • 程序的分支,跳转,循环,异常处理,线程恢复依赖于程序计数器完成。

    特性

    • 是线程私有的,记录线程当前执行的位置。
    • 若线程执行的是Java方法,则程序计数器记录的是字节码指令的地址;若执行的是Native方法,则计数器值为空。

    虚拟机栈

    定义

    • 描述方法执行的内存模型。
    • 虚拟机栈中保存着一个个栈帧,一个栈帧对应于一个方法。
    • 一个方法被线程执行,则JVM创建一个栈帧,并将栈帧入栈;若一个方法执行完成,则对应的栈帧从虚拟机栈中出栈
    • 每个栈中包含的内容:
      • 局部变量表
      • 操作数栈
      • 动态链接
      • 方法出口

    特性

    • 虚拟机栈是线程私有的,一个线程拥有一个虚拟机栈。

    局部变量表

    • 局部变量表存放编译时期可知的:
      • 基本数据类型
      • 对象引用
      • returnAddress类型
    • 局部变量表所需的内存空间在编译时期完成分配,完全确定,运行时不改变。
    • 对象引用:(也叫reference类型),本质是一个地址,指向一个对象的起始地址一个代表对象的句柄
    • returnAddress类型:本质是一个地址,指向一条字节码执行。

    可能的异常

    • StackOverFlow异常:请求的栈深度大于允许的最大深度。
    • OutOfMemory异常,内存已用完,且无法扩展栈深度。

    本地方法栈

    • 类似于虚拟机栈,是用来存放Native方法的相关信息。

    定义

    • 用来存放大部分的对象实例数组

    特性

    • 在堆中声明的对象不能直接访问,需通过虚拟机栈中对应的引用变量访问堆中的对象或数组。
    • 所有线程共享的内存区域。
    • 占JVM内存中的最大一部分。
    • 物理上非连续,逻辑上连续。
    • 垃圾回收的主要区域,也称GC堆。

    可能的异常

    • OutOfMemoryError异常:内存用完了。

    方法区

    定义

    • 用来存储已被JVM加载的:
      • 类的信息
      • 常量
      • 静态变量
      • 编译后的代码

    特性

    • 是各个线程共享的内存区域。
    • 物理上不需要连续的内存空间。
    • 大小可以固定,也可扩展。
    • 可以不实现垃圾回收(数据非永久存在,回收主要是常量池的回收和类型的卸载)。

    运行时常量池

    定义 常量池中存放编译时期产生的各种字面量符号引用

    特性

    • 可以在运行时将新的常量放入方法区的运行时常量池中。

    如: String类中的intern方法:若常量池中已包含指定的字符串,则返回常量池中的字符串;否则,将指定的字符串加入常量池中,并返回此字符串对象的引用。

    可能的异常

    • OutOfMemoryError异常:常量池无法申请内存时。

    直接内存

    NIO引入了一种基于通道和缓冲区的IO方式,它可以使用本地函数直接分配堆外内存,然后通过一个存储在堆里的DirectByteBuffer对象作为这块内存的引用来操作堆外内存中的数据。

    直接内存不受Java堆大小的限制,但仍然受本机总内存的限制。

    可能的异常

    • OutOfMemoryError异常

    class son extends father{ // 子类,存放于堆中
        static int var1; // 静态成员变量,存放于方法区
        static father var2; // 静态成员变量,存放于堆中
        final double var3=3.14; // 常量,存放于方法区
        
        void method1(){ // 方法,存放于虚拟机栈中
            int var4; // 局部变量,存放于虚拟机栈的局部变量表中
            father var5 = new father(); // 局部引用变量var5存放于虚拟机栈的局部变量表中,指向的对象存放在堆中
        }
    }
    
    class father{
        static int var1;
        
        void method1(){
            int var2;
        }
    }
    

    JDK8的改动

    • 取消“永久代”,使用“元空间”(metaspace)。
    • 静态成员变量中。
    • 方法区是JVM规范,永久区方法区的具体实现。

    内存的划分:

    • 虚拟机内存:
      • 程序计数器
      • 虚拟机栈
      • 本地方法栈
      • 堆(常量池,静态成员变量,对象,数组
    • 本地内存
      • 元空间

    JDK8内存分配

    参考:

  • 相关阅读:
    057.Python前端Django模型ORM多表查询
    056.Python前端Django模型ORM多表基本操作
    055.Python前端Django模型ORM
    054.Python之Ubuntu安装Pycharm
    053.Python前端Django框架模板层
    052.Python前端Django框架路由层和视图层
    基数排序
    链表k个节点反向
    链表排序
    函数返回局部指针变量是否可行?
  • 原文地址:https://www.cnblogs.com/truestoriesavici01/p/13224704.html
Copyright © 2020-2023  润新知