1、JVM定义

Java虚拟机(Java Virtual Machine),简称JVM。当我们说起Java虚拟机时,可能指的是如下三种不同的东西:

  • 抽象的虚拟机规范
  • 规范的具体实现
  • 一个运行中的虚拟机实例

Java虚拟机抽象规范仅仅是一个概念,在《The Java Virtual Machine Specification》中有详细的描述。

该规范的实现,可能来自多个提供商,并存在于多个平台上,它或者是全部由软件实现,或者是以硬件和软件相结合的方式来实现。JVM的实现有很多,广为使用的主要有三个(由于Sun和BEA被Oracle收购,故HotSpot、JRockit已都为Oracle所有):

  • Sun HotSpot(服务端、桌面、嵌入式 通用)
  • BEA JRockit(专注于服务端)
  • IBM J9(服务端、桌面、嵌入式 通用)

当运行一个Java程序的时候,也就在运行一个Java虚拟机实例。注意,我们所说的Java平台无关性是指class文件的平台无关性,JVM是和平台相关的,不同操作系统对应不同的JVM。

2、JVM架构

HotSpot虚拟机是官方的、最常用的JVM规范实现,这里以HotSpot虚拟机为例。

2.1、HotSpot JVM架构

如图,JVM可以分为三部分:类加载子系统、运行时数据区、执行引擎。

(图片来源:Java Garbage Collection Introduction)

更详细的结构:

(图片来源:The JVM Architecture Explained)

2.2、HotSpot JVM在Java SE中的位置

(图片来源:Jave SE Platform at a Glance)

3、JVM运行时数据区

JVM规范定义了若干种程序运行时使用到的运行时数据区:

分为两种,一种随虚拟机的启动和退出而创建和销毁(方法区、堆),一种随线程的开始和结束而创建和销毁(虚拟机栈、本地方法栈、程序计数器):

  • 方法区:类信息(版本、字段、方法、接口等描述信息,类的Class对象也存在此)、常量、静态变量、即时编译后的代码、运行时常量池(存放编译器生成的字面量和符号引用)等。(OutOfMemoryError异常)
  • 堆:实例对象(及数组)。注意不是所有对象,如上面所说类的Class对象存放在方法区。(OutOfMemoryError异常)
  • 栈(HotSpot对虚拟机栈和本地方法栈不加以分区,二者合二为一)::存放线程执行产生的栈帧信息(OutOfMemoryError异常、StackOverFlow异常)
    • 虚拟机栈(线程栈): 局部变量表(编译期可知的基本数据类型、引用类型、returnAddress)、操作数栈、动态链接、方法出口信息等
    • 本地方法栈:与虚拟机栈类似
  • 程序计数器:所属线程下一条要执行的指令的地址。(没有规定异常)

方法区、堆区、栈区 均可实现成固定大小容量或实现成可动态扩展容量的。

3.1、程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做是当前线程所执行的字节码的信号指示器。若线程正在执行的是一个Java方法,则程序计数器保存的是当前所在线程下一条要执行的字节码指令的地址;若正在执行的是Native方法,则计数器值为空(undefined)。

线程私有,每个JVM线程都有自己的程序寄存器。

此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

3.2、Java虚拟机栈

Java虚拟机栈(Java Virtual Machine Stack)即线程运行栈,描述的是Java方法执行的内存模型:每个方法被执行时会同时创建一个栈帧(Stack Frame)用于局部变量表(存编译期可知的基本数据类型、引用类型、returnAddress)、操作数栈、动态链表、方法出口信息等。每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

线程私有,每一个JVM线程都有自己的java虚拟机栈,这个栈与线程同时创建,它的生命周期与线程相同

JVM stack 可以实现成固定大小,也可以实现成可动态扩展的。若实现成固定大小,则每一条线程的JVM Stack容量应该在线程创建时就指定了大小,JVM实现应该提供调节JVM Stack初始容量的手段;若实现成可动态扩展的方式,则应该提供调节最大、最小容量的手段。

能创建的栈的数量(即线程的数量)受所在机器物理内存的限制,但实际上OS对一个进程能使用的内存大小(Windows 2GB)是有限制的,故能创建栈的数量受OS的这个限制。换句话说,JVM并没有支持调节各栈能用的总内存而是只提供了对一个栈大小的调节。

异常(两者实际上有重叠):

StackOverflowError:纵向无法分配即无法分配新的栈帧时 抛出此异常。

OutOfMemoryError:横线无法分配即无法建立新的线程(在创建新线程时没有足够内存来创建对应的虚拟机栈时 或者 JVM Stack可以动态扩展但在尝试扩展时无法申请到足够的内存来完成扩展,也就是超过了OS对一个进程能创建的线程数的限制时)时 抛出此异常。

3.3、本地方法栈

Java虚拟机可能会使用到传统的栈来支持native方法(使用Java语言以外的其它语言编写的方法)的执行,这个栈就是本地方法栈(Native Method Stack)。

线程私有。

本地方法栈发挥的作用域Java虚拟机栈相似。有的虚拟机(如HotSpot)不对两者加以区分,合二为一。

3.4、方法区

方法区(Method Area)用于存储已被虚拟机加载的类信息(版本、字段、方法、接口等描述信息)、常量、静态变量、即时编译后的代码、运行时常量池等。

各线程共享。

方法区的容量可以实现成固定大小的,也可以实现成可动态扩展的,并在不需要过多空间时候自动收缩。

方法区可以处于物理上不连续的内存空间中,只要逻辑连续即可。

OutOfMemoryError异常: 方法区的内存空间不能满足内存分配请求,且无法扩展时抛出此异常。

运行时常量池:存放编译器生成的各种字面量和符号引用

是方法区的一部分。Class文件编译后生成的各种字面量和符号引用放在文件的常量池中,这部分内容在类加载后进入方法区的运行时常量池。

与Class文件常量池相比,运行时常量池具备动态性:不要求常量只有在编译期才能产生,即并非预置入Class文件中常量池的内容才能进入运行时常量池,运行期间也可将新常量放入运行时常量池,如String的intern()方法(见Java小记-MarchOn)。

OutOfMemoryError异常:当创建类和接口时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大内存空间后就会抛出此异常。

注:方法区/永久代/元空间:

方法区常又被称为永久代(PermGen space)、元空间(Metaspace),它们并不等价,区别是:方法区为JVM的规范,永久代、元空间分别是方法区在HotSpot中的一种实现;对于其他类型的虚拟机实现,如 JRockit(BEA)、J9(IBM),其并没有永久代、元空间这些概念,其只要不触碰到进程可用内存上限即可。

  • 从JDK1.7开始,逐渐开始去永久代工作:JDK1.7中,存储在永久代的部分数据就已经转移到了Java Heap或者是 Native Heap。(如符号引用(Symbols)转移到了native heap;字面量(interned strings)、类的静态变量(class statics)转移到了java heap);
  • 从JDK1.8起,改用本地内存实现方法区,称为元空间。元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

3.5、Java堆

Java堆是几乎所有对象(有例外,如类的Class对象置于方法区)实例分配内存的区域。堆在虚拟机启动的时候被创建,堆中储存了各种对象,这些对象被自动内存管理系统(Automatic Storage Management System,也即是常说的“Garbage Collector(垃圾回收器)”)所管理。这些对象无需、也无法显示地被销毁。

各线程共享。

堆的容量可以实现成固定大小的,也可以实现成可动态扩展的,并在不需要过多空间时候自动收缩。

Java堆可以处于物理上不连续的内存空间中,只要逻辑连续即可。

Java 堆异常(OutOfMemoryError):若在堆中没有足够内存完成实例分配,并且也无法扩展时,抛出此异常。

3.6、本地直接内存(不是运行时数据区)

本地直接内存(Direct Memory)不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范定义的内存区域。但也可被使用,而且也可能出现OutOfMemoryError异常。其不受堆大小的限制,但受到本机进程可用内存的限制。

4、JVM各区域内存分配参数设置

上述各区域内存大小的配置可参看 HotSpot JVM各区域内存分配参数设置-MarchOn

Java虚拟机及运行时数据区相关推荐

  1. 【Java虚拟机】运行时数据区

    Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随 ...

  2. java虚拟机笔记—运行时数据区域

    程序计数器 1.程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器. 2.是唯一一个在java虚拟机规范中没有规定任何outOfMemoryError情况区域. 3.线程私 ...

  3. 20张图助你了解JVM运行时数据区,你还觉得枯燥吗?

    我们的JVM系列已经断更好几天了,小伙伴们在后台疯狂私信阿Q,想看后续内容,今天它来了.相信大家在上篇文章中已经对类加载子系统有了清晰的认识,接下来就让我们来揭开"运行时数据区"的 ...

  4. Java 虚拟机学习笔记 | 运行时数据区总结

    前言 要想学习好 Java,Java虚拟(JVM)的学习是绕不开的.学习 Java虚拟(JVM)首先就要先了解的就是Java虚拟(JVM)运行时数据区. 在Java语言和虚拟机规范中对运行时数据区进行 ...

  5. Java虚拟机2:Java 运行时数据区

    前言快速到底 如果有人问你 java 的内存区域分为哪些,可能很多人会说:堆.栈.方法区--.我个人理解从开发者的角度 Java 能够涉及到"内存区域"的大致有两处:第一,java ...

  6. 《深入理解Java虚拟机》笔记01 -- 运行时数据区

    运行时数据区示意图 1. 程序计数器 占用一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.主要用来记录线程执行到哪条语句了,分支.循环.跳转.异常处理.线程恢复等功能都需要依赖这个 ...

  7. 1、虚拟机内存管理、运行时数据区、线程共享区、Java堆、新生代、老年代、Eden区域分配、方法区、线程独占区、虚拟机栈

    1.Java虚拟机内存管理 1.1.运行时数据区[Runtime Data Area] 1.1.1.线程共享区 1.1.1.1.Java堆[heap] 1.1.1.1.1.新生代.老年代.Eden区域 ...

  8. 《深入理解Java虚拟机》(二)Java虚拟机运行时数据区

    Java虚拟机运行时数据区 详解 2.1 概述 本文参考的是周志明的 <深入理解Java虚拟机>第二章 ,为了整理思路,简单记录一下,方便后期查阅. 2.2 运行时数据区域 Java虚拟机 ...

  9. 笔记:Java虚拟机运行时数据区

    Java虚拟机在执行Java程序的过程中会把它管的内存划分为以下若干个不同的区域: 1.程序计数器 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器:由于Java虚拟机的 ...

  10. Java虚拟机运行时数据区

    将从<深入理解Java虚拟机:JVM高级特性与最佳实践>和 The Java® Virtual Machine Specification 中对于Java运行时数据区的描述整理记录一下 从 ...

最新文章

  1. linux 安装安装rz/sz 和 ssh
  2. 调包侠福音!机器学习经典算法开源教程(附参数详解及代码实现)
  3. php和python写爬虫-一个简单的Python写的XML爬虫
  4. 30秒清除你电脑中的垃圾(使你电脑急速如飞)
  5. 从JDK9的Flow接口说起
  6. KandQ:那年,那树,那些知识点
  7. 一个简单的MVP模式案例
  8. Goland显示“Cannot resolve symbol XXX“ 进行更新IDE的索引库
  9. 为什么说项目管理是每个人必备的底层能力?
  10. 信息发布服务器hp3000,HPCS-3000型DCS系统维护说明….doc
  11. 数据库工作笔记016---Redis、Memcache和MongoDB的区别
  12. h5 做app时和原生交互的小常识。
  13. Linux基础知识点
  14. java -super关键字
  15. Windows和Linux DNS Cache清理
  16. 顺序结构程序设计总结
  17. Android报错:The processing instruction target matching [xX][mM][lL] is not allowed.
  18. 超详细的元器件分类大全—电阻、电容、电感
  19. 以衍复为例,聊聊当下的沪深300指数增强
  20. 互联网时代如何快速提升宣传效果?

热门文章

  1. Postgresql - cursor介绍
  2. python如何筛选excel重复_老板让我从上千个Excel中筛选数据,利用Python分分钟解决!...
  3. 互联网+房地产最后拼什么?除了技术还是技术
  4. windows安装时提醒“缺少所需要的CD/DVD驱动器设备驱动程序”的解决办法
  5. stm32—火焰传感器的初步使用
  6. 股债轮动Python实现
  7. vs code的php格式化
  8. SVG_37_六一儿童节快乐-路径移动-火焰文字
  9. 对于百度统计热力点击图的研究
  10. SpringSecurity实现登陆认证并返回token