`

JVM 运行时数据区简介及堆与栈的区别

    博客分类:
  • JVM
 
阅读更多

1、JVM运行时数据区分类

  • 程序计数器 (Program Counter (PC) Register)

  • JVM栈 (Java Virtual Machine Stacks)

  • 堆内存 (Heap Memory)

  • 方法区 (Method Area)

  • 运行时常量池 (Run-time Constant Pool)

  • 本地方法栈 (Native Method Stacks)

 

2、看图说话

 

3、按线程持有划分

查看上面的图,可以得知以上六个数据区可以分为线程私有还是共享,总体分为如下两种。

 

3.1 单个线程私有(Managed Per-Thread) 

属于这一种的数据区包含 程序计数器, JVM栈还有本地方法栈。 每个线程都私有这三个数据区,这些数据区在其所属的线程创建时初始化,并随着所属线程结束被销毁。

 

3.1.1 程序计数器

在通用的计算机体系中,程序计数器用来记录当前正在执行的指令,在JVM中也是如此。程序计数器是线程私有,所以当一个新的线程创建时,程序计数器也会创建。由于Java是支持多线程,Java中的程序计数器用来记录当前线程中正在执行的指令。如果当前正在执行的方法是本地方法,那么此刻程序计数器的值为undefined。注意这个区域是唯一一个不抛出OutOfMemoryError的运行时数据区。

 

3.1.2 JVM栈

在介绍JVM栈之前,简单介绍一个概念,栈帧

栈帧:一个栈帧随着一个方法的调用开始而创建,这个方法调用完成而销毁。栈帧内存放者方法中的局部变量,操作数栈等数据。

JVM栈只对栈帧进行存储,压栈和出栈操作。栈内存的大小可以有两种设置,固定值和根据线程需要动态增长。在JVM栈这个数据区可能会发生抛出两种错误。

  • StackOverflowError 出现在栈内存设置成固定值的时候,当程序执行需要的栈内存超过设定的固定值会抛出这个错误。

  • OutOfMemoryError 出现在栈内存设置成动态增长的时候,当JVM尝试申请的内存大小超过了其可用内存时会抛出这个错误。

 

3.1.3 本地方法栈

一个支持native方法调用的JVM实现,需要有这样一个数据区,就是本地方法栈,Java官方对于本地方法的定义为methods written in a language other than the Java programming language,就是使用非Java语言实现的方法,但是通常我们指的一般为C或者C++,因此这个栈也有着C栈这一称号。一个不支持本地方法执行的JVM没有必要实现这个数据区域。本地方法栈基本和JVM栈一样,其大小也是可以设置为固定值或者动态增加,因此也会对应抛出StackOverflowError和OutOfMemoryError错误。

 

3.2 多个线程共享 

属于这一种的数据区包含 堆内存,方法区和运行时常量池。这些数据区可以被每一个线程访问,他们随着JVM启动而初始化,同时伴随JVM关闭而销毁。

 

3.2.1 堆数据区

堆数据区是用来存放对象和数组(特殊的对象)。堆内存由多个线程共享。堆内存随着JVM启动而创建。众所周知,Java中有一个很好的特性就是自动垃圾回收。垃圾回收就操作这个数据区来回收对象进而释放内存。如果堆内存剩余的内存不足以满足于对象创建,JVM会抛出OutOfMemoryError错误。

 

3.2.2 方法区

在JVM规范中,方法区被视为堆内存的一个逻辑部分。这一点可能由于具体的JVM实现而不同,甚至在方法区不实现垃圾回收处理也是可以的。方法区和堆内存一样被多个线程访问,方法区中存放类的信息,比如类加载器引用,属性,方法代码和构造方法和常量等。当方法区的可用内存无法满足内存分配需求时,JVM会抛出OutOfMemoryError错误。

 

3.2.3 运行时常量池

运行时常量池创建在方法区,当一个类或者一个接口被创建的时候,JVM会创建一个运行时常量池。一个运行时常量池实际上是一个类或者接口的class文件中常量池表(constant_pool table)的运行时展示形式。一个运行时常量池包含了多种类型的常量,从诸如运行时可以确定的数值型字面量到运行时才能决定的方法和属性引用。当运行时常量池无法满足于内存分配需求时,JVM会抛出OutOfMemoryError错误。

 

4、Java 堆和栈的区别

当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先出(Last In First Out)的顺序的数据结构,这就是java.util.Stack。这种情况下,不免让很多人更加费解前面的问题。事实上,堆和栈都是内存中的一部分,有着不同的作用,而且一个程序需要在这片区域上分配内存。众所周知,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然是JVM(虚拟)内存中的堆和栈。

 

4.1 各司其职

最主要的区别就是栈内存用来存储局部变量和方法调用。

而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。

 

4.2 独有还是共享

栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。

而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

 

4.3 异常错误

如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.StackOverFlowError。

而如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。

 

4.4 空间大小

栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生StackOverFlowError问题。

你可以通过-Xss选项设置栈内存的大小。-Xms选项可以设置堆的开始时的大小,-Xmx选项可以设置堆的最大值。

这就是Java中堆和栈的区别。理解好这个问题的话,可以对你解决开发中的问题,分析堆内存和栈内存使用,甚至性能调优都有帮助。

 

4.5 查看默认值(Updated)

查看堆的默认值,使用下面的代码,其中InitialHeapSize为最开始的堆的大小,MaxHeapSize为堆的最大值。

1
2
3
4
5
6
7
8
9
13:17 $ java -XX:+PrintFlagsFinal -version | grep HeapSize
    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 134217728                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 2147483648                          {product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

查看栈的默认值,其中ThreadStackSize为栈内存的大小。

1
2
3
4
5
6
7
13:21 $ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize
     intx CompilerThreadStackSize                   = 0                                   {pd product}
     intx ThreadStackSize                           = 1024                                {pd product}
     intx VMThreadStackSize                         = 1024                                {pd product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
分享到:
评论

相关推荐

    超硬核!!!一篇文章搞定整个JVM运行时数据区

    JVM运行时数据区1 JVM运行时数据区2 解析JVM运行时数据区2.1 方法区(Method Area)2.2 Java堆(Java Heap)2.3 程序计数器(Program Counter Register)2.4 Java虚拟机栈(Java Virtual Machine Stacks)2.5 本地...

    JVM 运行时数据区域,垃圾回收机制,类加载机制三大功能详解.docx

    运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量(栈)等。 垃圾回收机制: java 语言的优势之一就是它的自动内存管理,主要回收运行时数据区域的堆内存里的数据 ...

    jvm原理及调优

    一、JVM概述 二、JVM的体系结构 三、JVM运行时数据区 3.1 PC寄存器 3.2 JVM栈 3.3 堆(Heap) 3.4 方法区域 3.5 运行时常量池 3.6本地方法堆栈 四、Jvm堆 五、Jvm调优

    最新java面试专题01-JVM

    最新jvm面试题合集,涵盖JVM运行时数据区、垃圾回收算法、垃圾回收器、类加载机制、JIT即时编译等核心知识点及常见面试题,一书在手,天下我有。 JVM内存结构:JVM的内存结构主要包括堆内存、方法区、栈(包括Java...

    《JVM从入门到入魔》笔记.pdf

    1:JVM内存模型:类加载机制【转载、验证、准备、解析、初始化】+类装载器【装载器分类、加载原则】+运行时数据区【方法区、堆、虚拟机栈、本地方法栈、程序计数器】。 2:垃圾回收:垃圾确定【引用计数法、可达性分析...

    一篇文章掌握整个JVM,JVM超详细解析!!!

    JVM先想想一些问题1 我们开发人员编写的Java代码是怎么让电脑认识的2 为什么说java是跨平台语言3 Jdk和Jre和JVM的区别4 为什么要学习JVM深入学习JVM1 JVM运行时数据区2 解析JVM运行时数据区2.1 方法区(Method Area...

    Java虚拟机(JVM)面试题(总结最全面的面试题!!!)

    说一下 JVM 运行时数据区详细的介绍下程序计数器?(重点理解)详细介绍下Java虚拟机栈?(重点理解)一个方法调用另一个方法,会创建很多栈帧吗?栈指向堆是什么意思?递归的调用自己会创建很多栈帧吗?你能给我详细...

    深入理解JVM内存结构及运行原理全套视频加资料.txt

    包括JVM执行过程、虚拟机类加载机制、运行时数据区、GC、类加载器、内存分配与回收策略等,全套视频加资料高清无密码  第1讲 说在前面的话 免费 00:05:07  第2讲 整个部分要讲的内容说明 免费 00:06:58  第3讲...

    Java进阶教程解密JVM视频教程

    学习字节码指令的的运行流程,字节码指令与常量池、方法区的关系。掌握条件分支、循环控制、异常处理、构造方法在字节码级别的实现原理,利用HSDB工具理解多态原理。还会涉及从编译期的语法糖处理,到类加载的各个...

    JVM简介以及历史.docx

    (3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。 JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器...

    微服务架构面试专题系列(MySQL,JVM,并发编程,RabbitMQ消息中间件,Spring)

    说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 2. MySQL包括了:索引,锁,事务等常见考点 MySql的主从...

    大白话带你认识JVM.pdf

    堆 主要放了一些存储的数据,比如对象实例,数组···等,它和方法区都同属于 线程共享区域 。也就是说它们都是 线程不安全 的 #④ 栈 栈 这是我们的代码运行空间。我们编写的每一个方法都会放到 栈 里面运行。 ...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    第2章 Java内存区域与内存溢出异常 / 24 2.1 概述 / 24 2.2 运行时数据区域 / 25 2.2.1 程序计数器 / 25 2.2.2 Java虚拟机栈 / 26 2.2.3 本地方法栈 / 27 2.2.4 Java堆 / 27 2.2.5 方法区 / 28 2.2.6 运行...

    java技术栈,包括 java基础,jvm,java集合.zip

    java技术栈,包括 java基础,jvm,java集合,java并发,IO, 设计模式,http,网络,操作系统,mysql,redis,spring,mybatis,数据结构,算法等。持续更新中,欢迎star! 各领域数据集,工具源码,适合毕业设计、...

    JVM历史发展和内存回收笔记.rar

    虚拟机的历史版本和JAVA内存分配,未来的虚拟机技术, 运行时数据区域,方法的出入栈,栈上分配

    JVM内存模型及垃圾回收

    通俗的来讲,jvm主要分为5个部分 程序计数器、虚拟机枝、本地方法枝、 Java 堆、 方法区, 引用大佬总结的概括程序计数器用于存放下一条运行的指令,虚拟机栈和本地方法栈用于存放函数调用堆栈信息, Java 堆用于...

    重磅2023年最新JAVA核心知识整理从基础到精通完整教程-283页全面试题解析学习资料涵项目源码-20231120.pdf

    2.3.JVM运行时内存 2.3.1.新生代 2.3.1.1.Eden区 2.3.1.2.ServivorFrom 2.3.1.3.ServivorTo 2.3.1.4.MinorGC的过程(复制->清空->互换) 1:eden、servicorFrom复制到ServicorTo,年龄+1 2:清空eden、servicorFrom ...

Global site tag (gtag.js) - Google Analytics