• Jvm的运行时数据区


    运行时数据区域

    Java虚拟机在运行过程中会将其所管理的内存区域划分为多个不同区域,便于管理程序运行过程中的对象、方法等的创建执行和销毁。根据《Java虚拟机规范》规定,Java虚拟机的内存分为以下几种运行时区域:

     

    其中方法区、堆区为线程共享的区域,其生命周期与虚拟机相同;虚拟机栈、本地方法栈与程序计数器为线程私有的区域,跟随线程创建、销毁。

     

    程序计数器

    程序计数器是一个较小的内存空间,代表线程当前正在执行的字节码的行号指示器,是虚拟机的概念模型,各虚拟机有自己的实现。字节码解释器工作时通过修改计数器的值找到下一条要执行的指令。

    每个线程都有一个程序计数器,便于线程切换时能恢复正在执行的指令。

    线程执行普通Java方法时,计数器记录的是正在执行的字节码指令地址;执行Native方法时,计数器值为空(Undefined)。

    该区域不会发生OutOfMemoryError

     

    Java虚拟机栈

    虚拟机栈就是我们平常说的“堆”、“栈”中的“栈”,每个线程拥有一个虚拟机栈,用于存储方法的运行信息,程序每执行一个方法就会创建一个栈帧压入虚拟机栈中,栈帧存储局部变量表、操作数栈、动态链接、方法出口等信息。方法执行完就将栈帧弹出栈。

    局部变量表用于存放编译器可知的基本数据类型、对象引用和returnAddress类型。

    虚拟机栈可能出现StackOverflowError和OutOfMemoryError。

     

    本地方法栈

    类似于虚拟机栈,不过本地方法栈用于执行Native方法,Native方法用native关键字标识,没有方法体,使用C编写。

    本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError异常。

     

    Java堆

    堆区主要用于存放对象实例,是Jvm管理的最大的一块内存区域,为线程共享,生命周期于虚拟机相同。堆区是垃圾收起器管理的主要区域,从对象回收角度,堆区被划分为新生代和老年代,新生代又分为Eden区、From Survivor区和To Survivor区。从内存分配角度,堆区可划分出线程私有的分配缓冲区(TLAB)。

    通过 -Xms 和 -Xmx 参数可以设置堆区的初始内存和最大内存大小,会出现OutOfMemoryError异常。

     

    方法区

    线程共享的区域,用于存储虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据(虽然叫方法区,但不是存储方法的区域)。

    方法区无法满足内存分配需求时会出现OutOfMemoryError异常。

    JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8 开始使用元空间(Metaspace),以前永久代所有内容的字符串常量移至堆内存,其他内容移至元空间,元空间直接在本地内存分配。

    运行时常量池

    运行时常量池(runtime constant pool)是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用。jvm在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中。

    一般来说,除了保存 Class 文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。

    运行时常量池相较于Class文件常量池的体征就是动态性,在运行时也可以将新的常量放入池中,如String类的intern()方法。

    会出现OutOfMemoryError异常。

    字面量

    1. 文本字符串
    2. 8种基本类型的值
    3. 被声明为final的常量

    符号引用

    1. 类和方法的权限定名
    2. 字段的名称和描述符
    3. 方法的名称和描述符

     

    直接内存

    直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。

    在 JDK 1.4 中新加入了 NIO,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。

    显然,本机直接内存的分配不会受到 Java 堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括 RAM 以及 SWAP 区或者分页文件)大小以及处理器寻址空间的限制。服务器管理员在配置虚拟机参数时,会根据实际内存设置 -Xmx 等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),从而导致动态扩展时出现 OutOfMemoryError 异常。

  • 相关阅读:
    中国正在消失的老行当
    ie9 scrollbar中hover 高度增高的bug
    (替月光博客备份)百度百科:游荡在中国的窃贼
    严格模式下 W3C Strict 验证的几个注意事项
    [转]滤镜渐变使用 IE浏览器
    1.什么是串口?
    6.串口操作之API篇 GetCommTimeouts SetCommTimeouts
    5.串口操作之API篇 SetupComm GetCommState SetCommState
    TeeChart经验总结 13.Export之2.对象保存
    解决"手机存储暂不能使用""SIM卡存储暂不能使用"
  • 原文地址:https://www.cnblogs.com/liuyiyuan/p/13031823.html
Copyright © 2020-2023  润新知