当Java虚拟机在执行Java程序语言时会把分配给虚拟机的内存划分为以下几个区域:
堆(Heap)
方法区(Method Area)
虚拟机栈(VM Stack)
本地方法栈(Native Method Stack)
程序计数器(Program Counter Register)
五部分,其中堆和方法区是供所有线程共享的数据区,另外三部分是独立与线程相互隔离的数据区。
程序计数器(Program Counter Register):见名知意,计数器,针对程序的计数器,即当前线程在执行代码(字节码)时的行号指示器,字节码解释器负责调度当前线程的下一条所需要执行的字节码位置,如程序中的判断、循环、跳转、异常以及多线程切换睡眠后醒来需要执行的行号。由此可见为了保证多线程之间的有序调度,针对每个线程都分配了有一个独立的线程计数器,这样就能保证线程之间能相互协调工作,像这样的内存区域也就是针对线程独立运行的数据区,他们之间互不影响,就叫做“线程私有”内存。如果线程调度的是Java方法则计数器中记录的是正在执行的虚拟机字节码地址;如果执行的是Native方法此时计数器则为空。通俗的说程序计数器就是告知JVM中正在运行的线程下一步要执行的字节码。PCR是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
虚拟机栈(VM Stack):VM Stack同Program Counter Register一样也是一块线程私有内存区域,线程私有内存有一个共同点就是他们的生命周期是与当前线程同步的,如果当前线程终结那么对应占用的内存空间也就立即释放。VM Stack内存是在Jvm执行Java方法时由不同栈帧(Stack Frame)所占有的,每运行到一个方法时就会分配一个栈帧,在栈帧内存放该方法的局部变量以及和该方法相关的信息,栈有一个特征就是有进有出,当一个方法被调用的时候那么就对应这个方法的栈帧入栈,方法执行完毕,那么该栈帧也就出栈,释放占用的内存资源。在编译期间可知的基本数据类型(boolean、byte、char、short、int、float、long、double)以及一些指向对象的引用就将存放在虚拟机栈中进行调度,这里所说的对象的引用并不是指的对象的本身,它指的是指向对象的一个地址引用指针,或者是指向代表对象的句柄。所以如果当一个线程如果需要申请的栈内存空间超过虚拟机预先设定的栈空间那么就会抛出StackOverflowError异常;还有一种情况是虚拟机栈可以自己根据实际情况动态扩展,如果实际情况需要扩展更大的空间满足线程运行需要,但是此时无法申请到内存空间时就会抛出OutOfMemoryError异常。
本地方法栈(Native Method Stack):它跟VM Stack栈类似,同样也是一块线程私有内存,唯一不同的是他服务的对象不是Java方法,而是Native方法,他也会抛出StackOverflowError和OutOfMemoryError异常。
堆(Heap):这是占用JVM大量内存的一块区域,这块区域不是线程私有内存,而是所有线程共享的,在虚拟机启动时根据事先的虚拟机设定就已经分配了该空间,该区域存放的是大量的实例对象或数组。至于存放该区域的空间对象的生命周期和空间利用都由JVM的垃圾收集器统一管理,如果该区域不能满足新的实例对象所需要的存放空间那么就会抛出OutOfMemoryError异常。
方法区(Method Area):与堆一样也是所有线程可以共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态常量、即时编译器编译后的代码 等数据。当他不能满足新的内存需求分配时他会抛出OutOfMemoryError异常。这里还有一个概念就是运行时常量池(Runtime Constant Pool),他是方法区的一部分,是方法区的一个子集,用于存放编译期生成的各种字面量和符号引用,类一旦被加载后这部分内容就被置入到了常量池中。你会发现也正是类信息、常量、静态常量和各种字面量和符号引用组成了class文件,在运行期间可以通过String类得intern()方法将新的数据置入常量池,所以我们可以理解class文件的所有信息都被放入到了方法区(当然包括常量池),常量池也会受到内存的限制,他不能满足新的内存需求分配时他会抛出OutOfMemoryError异常。
分享到:
相关推荐
### JAVA内存分区与C/C++内存分区的深度解析 #### JAVA内存分区 在JAVA中,JVM(Java虚拟机)的内存主要分为三个区域:堆(heap)、栈(stack)和方法区(method)。每个区域都有其特定的功能和管理机制。 1. **...
Java内存区域和垃圾收集(GC)机制是Java编程中至关重要的一部分,它关乎程序的性能、稳定性和资源管理。本文将深入探讨Java虚拟机(JVM)中的内存划分、垃圾收集的工作原理以及相关工具的使用。 1. **Java内存区域...
本教程将涵盖Java的基础知识,特别是关于内存管理的重要概念——Java内存区域、Out of Memory (OOM)错误以及垃圾回收器和垃圾回收策略。 1. **Java入门**: Java的学习始于基础语法,包括变量、数据类型、运算符、...
Java内存区域是Java虚拟机(JVM)管理内存的核心组成部分,它们主要分为以下几个部分: 1. **程序计数器(ProgramCounterRegister)**:每个线程都有自己的程序计数器,用于存储当前线程正在执行的字节码的行号指示...
java内存区域和内存溢出.xmind
Java内存区域与内存溢出异常.pdf
Java 内存区域, 垃圾收集, 内存分配与回收策略, JVM 调优, 文件结构, 类加载机制, Java 程序 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,意味着可以在不同的操作...
Java虚拟机Java内存区域及对象.doc
深入理解Java虚拟机-Java内存区域透彻分析(序列化、反序列化概念及其使用场景+实现序列化的方式+transient关键字) Java序列化和反序列化是Java虚拟机中的一种重要机制,它们可以将Java对象转换为二进制数据,然后...
1. **Heap(堆)**:这是Java中最主要的内存区域,用于存储所有的类实例和数组。当堆空间不足时,会抛出`java.lang.OutOfMemoryError: Java heap space`异常。为了优化内存管理,Java采用了垃圾回收机制(Garbage ...
Java内存区域的使用详解主要涵盖了五个核心部分:程序计数器、虚拟机栈、本地方法栈、Java堆以及方法区。这些区域各自负责不同的任务,共同确保Java应用程序的正常运行。 1. **程序计数器**:每个线程都有自己的...
这是自己读《深入理解Java虚拟机》时候用XMind建立的思维导图,目的是为了能够帮助自己整理、梳理相关的知识以及方便自己日后的回顾,帮助自己建立起关于JVM的知识体系,里边也有一些对相关内容的补充,通过备注的...
#### 二、Java内存区域概述 Java程序在运行时会根据不同的数据类型和生命周期将其分配到不同的内存区域。这些内存区域主要包括: 1. **寄存器**:用于临时存放CPU计算过程中产生的中间结果,这部分内存不由程序员...
#### 一、Java内存区域划分 Java的内存管理机制将内存分为以下几个区域: 1. **栈(Stack)**: - 存储局部变量(如基本类型的变量和对象的引用)。 - 每个线程拥有一个独立的栈。 - 栈内存中的数据在方法执行...
- **主内存**: 所有线程共享的内存区域,包含堆和方法区,线程间通信的媒介。 - **工作内存**: 每个线程的私有缓存,用于存储从主内存中复制的变量副本,执行计算操作后可能更新回主内存。 2. **内存间交互** - ...
Java内存区域主要分为两部分:主内存(Main Memory)和工作内存(Working Memory)。 - **主内存**:所有线程共享的内存区域,用于存放程序中所有的变量。Java中所有变量都储存在主存中,对于所有线程都是共享的。 - **...
Java虚拟机(JVM)中有三个主要的内存区域:堆内存(Heap)、栈内存(Stack)和方法区(Method Area)。其中,堆内存是Java对象的主要存储场所,栈内存主要存储方法调用时的局部变量,而方法区则存储类的信息,如类...
"浅谈Java内存区域划分和内存分配策略" 本文将详细讲述Java内存区域划分和内存分配策略,涵盖程序计数器、虚拟机栈、本地方法栈、堆、方法区等内存区域的概念和作用,以及对象创建过程和内存分配策略。 程序计数器...
### 如何解决Java内存泄漏 #### 1. 背景 Java凭借其垃圾回收机制大大简化了内存管理,使得开发者无需手动管理内存的释放,从而提升了开发效率。然而,这种自动化管理也可能成为一把双刃剑,特别是当开发人员忽视...
#### 一、Java内存区域划分 Java程序在运行过程中涉及的内存主要分为两大类:栈内存和堆内存。 1. **栈内存**:主要用于存储局部变量,如基本数据类型变量(int、long、char等)以及对象的引用变量。这些变量在...