JVM 内存结构
前面介绍了内存的不同形态:物理内存和虚拟内存。介绍了内存的使用形式:内核空
间和用户空间。接着又介绍了Java 有哪些组件需要使用内存。下面着重介绍在JVM 中是
如何使用内存的。
JVM 是按照运行时数据的存储结构来划分内存结构的,JVM 在运行Java 程序时,将
它们划分成几种不同格式的数据,分别存储在不同的区域,这些数据统一称为运行时数据
(Runtime Data)。运行时数据包括Java 程序本身的数据信息和JVM 运行Java 程序需要的
额外数据信息,如要记录当前程序指令执行的指针(又称为PC 指针)等。
在 Java 虚拟机规范中将Java 运行时数据划分为6 种,分别为:
◎ PC 寄存器数据;
Java 栈;
◎ 堆;
◎ 方法区;
◎ 本地方法区;
◎ 运行时常量池。
PC 寄存器
PC 寄存器严格来说是一个数据结构,它用于保存当前正常执行的程序的内存地址。
同时Java 程序是多线程执行的,所以不可能一直都按照线性执行下去,当有多个线程交
叉执行时,被中断线程的程序当前执行到哪条的内存地址必然要保存下来,以便于它被恢
复执行时再按照被中断时的指令地址继续执行下去。这很好理解,它就像一个记事员一样
记录下哪个线程当前执行到哪条指令了。
但是 JVM 规范只定义了Java 方法需要记录指针信息,而对于Native 方法,并没有要
求记录执行的指针地址。
Java 栈
Java 栈总是和线程关联在一起,每当创建一个线程时,JVM 就会为这个线程创建一个
对应的Java 栈,在这个Java 栈中又会含有多个栈帧(Frames),这些栈帧是与每个方法关
联起来的,每运行一个方法就创建一个栈帧,每个栈帧会含有一些内部变量(在方法内定
义的变量)、操作栈和方法返回值等信息。
每当一个方法执行完成时,这个栈帧就会弹出栈帧的元素作为这个方法的返回值,并
清除这个栈帧,Java 栈的栈顶的栈帧就是当前正在执行的活动栈,也就是当前正在执行的
方法,PC 寄存器也会指向这个地址。只有这个活动的栈帧的本地变量可以被操作栈使用,
当在这个栈帧中调用另外一个方法时,与之对应的一个新的栈帧又被创建,这个新创建的
栈帧又被放到Java 栈的顶部,变为当前的活动栈帧。同样现在只有这个栈帧的本地变量
才能被使用,当在这个栈帧中所有指令执行完成时这个栈帧移出Java 栈,刚才的那个栈
帧又变为活动栈帧,前面的栈帧的返回值又变为这个栈帧的操作栈中的一个操作数。如果
前面的栈帧没有返回值,那么当前的栈帧的操作栈的操作数没有变化。
由于 Java 栈是与Java 线程对应起来的,这个数据不是线程共享的,所以我们不用关
心它的数据一致性问题,也不会存在同步锁的问题。
堆
堆是存储 Java 对象的地方,它是JVM 管理Java 对象的核心存储区域,堆是Java 程
序员最应该关心的,因为它是我们的应用程序与内存关系最密切的存储区域。
每一个存储在堆中的Java 对象都会是这个对象的类的一个副本,它会复制包括继承
自它父类的所有非静态属性。
堆是被所有Java 线程所共享的,所以对它的访问需要注意同步问题,方法和对应的
属性都需要保证一致性。
方法区
JVM 方法区是用于存储类结构信息的地方,如在第7 章介绍的将一个class 文件解析
成JVM 能识别的几个部分,这些不同的部分在这个class 被加载到JVM 时,会被存储在
不同的数据结构中,其中的常量池、域、方法数据、方法体、构造函数,包括类中的专用
方法、实例初始化、接口初始化都存储在这个区域。
方法区这个存储区域也属于后面介绍的Java 堆中的一部分,也就是我们通常所说的
Java 堆中的永久区。这个区域可以被所有的线程共享,并且它的大小可以通过参数来设置。
这个方法区存储区域的大小一般在程序启动后的一段时间内就是固定的了,JVM 运行
一段时间后,需要加载的类通常都已经加载到JVM 中了。但是有一种情况是需要注意的,
那就是在项目中如果存在对类的动态编译,而且是同样一个类的多次编译,那么需要观察
方法区的大小是否能满足类存储。
方法区这个区域有点特殊,由于它不像其他Java 堆一样会频繁地被GC 回收器回收,
它存储的信息相对比较稳定,但是它仍然占用了Java 堆的空间,所以仍然会被JVM 的GC
回收器来管理。在一些特殊的场合下,有时通常需要缓存一块内容,这个内容也很少变动,
但是如果把它置于Java 堆中它会不停地被GC 回收器扫描,直到经过很长的时间后会进入
Old 区。在这种情况下,通常是能控制这个缓存区域中数据的生命周期的,我们不希望它
被JVM 内存管理,但是又希望它在内存中。面对这种情况,淘宝正在开发一种技术用于
在JVM 中分配另外一个内存存储区域,它不需要GC 回收器来回收,但是可以和其他内
存中对象一样来使用。
运行时常量池
在 JVM 规范中是这样定义运行时常量池这个数据结构的:Runtime Constant Pool 代表运
行时每个class 文件中的常量表。它包括几种常量:编译期的数字常量、方法或者域的引用
(在运行时解析)。Runtime Constant Pool 的功能类似于传统编程语言的符号表,尽管它包含
的数据比典型的符号表要丰富得多。每个Runtime Constant pool 都是在JVM 的Method area
中分配的,每个Class 或者Interface 的Constant Pool 都是在JVM 创建class 或接口时创建的。
上面的描述可能使你有点迷惑,这个常量池与前面方法区的常量池是否是一回事?答
案是肯定的。它是方法区的一部分,所以它的存储也受方法区的规范约束,如果常量池无
法分配,同样会抛出OutOfMemoryError。
本地方法栈
本地方法栈是为JVM 运行Native 方法准备的空间,它和前面介绍的Java 栈的作用是
类似的,由于很多Native 方法都是用C 语言实现的,所以它通常又叫C 栈,除了在我们
的代码中包含的常规的Native 方法会使用这个存储空间,在JVM 利用JIT 技术时会将一
些Java 方法重新编译为Native Code 代码,这些编译后的本地代码通常也是利用这个栈来
跟踪方法的执行状态的。
在 JVM 规范中没有对这个区域的严格限制,它可以由不同的JVM 实现者自由实现,
但是它和其他存储区一样也会抛出OutOfMemoryError 和StackOverflowError。
相关推荐
1. **JVM内存结构** JVM内存主要分为以下几个区域: - **方法区(Method Area)**:这是所有线程共享的区域,存储类信息、常量、静态变量、即时编译后的代码等。在Java 8以前,这部分也被称为永久代(Permanent ...
### JVM内存结构详解 #### 一、概述 Java虚拟机(JVM)作为Java程序的运行环境,其核心组件之一便是内存管理系统。理解JVM的内存布局对于开发高性能的应用程序至关重要。本文将详细介绍JVM内存结构及其各个组成部分...
JVM 内存结构和 6 大区域 JVM 是 Java虚拟机,它是 Java 语言的核心组件之一,为 Java 程序提供了运行环境。JVM 的内存结构是 Java 程序的基础,它的设计和实现对 Java 程序的性能和可靠性产生了深远的影响。 JVM ...
"Jvm性能优化-JVM内存结构原理分析03" Jvm性能优化是Java虚拟机(JVM)中非常重要的一部分,它对Jvm的性能产生了很大的影响。本文将从Jvm内存结构的角度来分析Jvm性能优化的原理。 Jvm内存结构主要分为五部分:堆...
JVM内存结构的理解对于优化Java程序性能、避免内存溢出等问题至关重要。以下是对JVM内存结构的详细阐述: 1. **堆内存(Heap)** 堆内存是Java程序中最大的一块内存区域,用于存储对象实例。所有通过`new`关键字...
总之,深入理解JVM内存结构及其管理机制,有助于我们编写更高效、更稳定的Java程序,并能有效地处理内存相关问题。这份"JVM内存结构笔记"将详细阐述这些内容,是学习和研究JVM内存管理的重要参考资料。
JVM内存结构的理解对于优化Java程序的性能至关重要。JVM内存主要分为以下几个区域: 1. **程序计数器(Program Counter Register)**:每个线程都有一个独立的程序计数器,用于存储当前线程正在执行的字节码指令...
总结来说,Linux和JVM内存结构分析是提升系统效率和稳定性的重要手段。通过阅读和分析上述文件,我们可以深入了解系统资源的使用情况,进而进行针对性的调优。对于IT专业人士而言,掌握这些知识不仅能提升工作效率,...
了解JVM内存结构对于优化代码性能、防止内存泄漏以及理解程序运行时的行为至关重要。本文将深入探讨JVM内存的各个区域,帮助你全面掌握JVM的工作原理。 首先,JVM内存主要分为以下几个部分: 1. **程序计数器...
JVM内存结构-JVM体系结构 程序计数器 虚拟机栈 本地方法栈 堆 方法区
2019最新深入理解JVM内存结构及运行原理(JVM调优)高级核心课程视频教程下载。JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java程序员深入Java技术领域的重要因素。本课程试图通过简单易懂的方式,系统...
Java虚拟机(JVM)内存结构是理解Java...总之,JVM内存结构是Java平台的核心特性,它为程序提供了动态的内存分配和管理,确保了程序的稳定性和效率。深入理解这一结构,有助于开发者写出更高效、更健壮的Java应用程序。
Java内存模型(JMM)与JVM内存结构不同,它是针对多线程环境下内存访问的抽象模型。JMM确保在多线程环境下,共享变量的读写操作具有正确的顺序和可见性,通过volatile、synchronized等关键字来实现这一目标。JMM关注...
java jvm内存结构 调优
理解JVM内存结构和垃圾回收机制对于Java开发者至关重要,它可以帮助我们更好地优化程序性能,避免内存溢出等问题。通过调整JVM参数,如堆大小、新生代与老年代的比例、垃圾收集器的选择等,我们可以根据应用的需求...
了解JVM内存结构及其功能对于优化Java应用程序的性能和排查内存问题至关重要。 首先,我们来详细探讨JVM的内存结构。在Java中,内存主要分为以下几个区域: 1. **程序计数器(Program Counter Register)**:每个...
在JDK8中,JVM内存结构发生了显著变化,尤其是元空间(MetaSpace)替代了永久代(Permanent Generation)作为方法区的一部分。这种方法区的调整是由于永久代存在的一些问题,比如大小设定困难,容易引发溢出,以及给...
2019最新深入理解JVM内存结构及运行原理(JVM调优)高级核心课程视频教程下载。JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java程序员深入Java技术领域的重要因素。本课程试图通过简单易懂的方式,系统...
jvm内存结构-栈的变化,机器指令的格式/执行模式文章中的demo代码。