Java虚拟机及运行时数据区
1、Java虚拟机的定义
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 VM(服务端、桌面、嵌入式 通用)
当运行一个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规范定义了若干种程序运行时使用到的运行时数据区
- 有一些是 随虚拟机的启动而创建,随虚拟机的退出而销毁
- 第二种则是与线程一一对应,随线程的开始和结束而创建和销毁
java虚拟机所管理的内存将会包括以下几个运行时数据区域:
3.1、程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器。
每一条JVM线程都有自己的PC寄存器
在任意时刻,一条JVM线程只会执行一个方法的代码。该方法称为该线程的当前方法(Current Method)
如果该方法是java方法,那PC寄存器保存JVM正在执行的字节码指令的地址
如果该方法是native,那PC寄存器的值是undefined。
此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
3.2、Java虚拟机栈
即线程运行栈,与PC寄存器一样,java虚拟机栈(Java Virtual Machine Stack)也是线程私有的。每一个JVM线程都有自己的java虚拟机栈,这个栈与线程同时创建,它的生命周期与线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
JVM stack 可以被实现成固定大小,也可以根据计算动态扩展。
如果采用固定大小的JVM stack设计,那么每一条线程的JVM Stack容量应该在线程创建时独立地选定。JVM实现应该提供调节JVM Stack初始容量的手段。
如果采用动态扩展和收缩的JVM Stack方式,应该提供调节最大、最小容量的手段。
JVM Stack 异常情况:
StackOverflowError:当线程请求分配的栈容量超过JVM允许的最大容量时抛出
OutOfMemoryError:如果JVM Stack可以动态扩展,但是在尝试扩展时无法申请到足够的内存去完成扩展,或者在建立新的线程时没有足够的内存去创建对应的虚拟机栈时抛出。
3.3、本地方法栈
Java虚拟机可能会使用到传统的栈来支持native方法(使用Java语言以外的其它语言编写的方法)的执行,这个栈就是本地方法栈(Native Method Stack)
如果JVM不支持native方法,也不依赖与传统方法栈的话,可以无需支持本地方法栈。
如果支持本地方法栈,则这个栈一般会在线程创建的时候按线程分配。
异常情况:
StackOverflowError:如果线程请求分配的栈容量超过本地方法栈允许的最大容量时抛出
OutOfMemoryError:如果本地方法栈可以动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或者在建立新的线程时没有足够的内存去创建对应的本地方法栈,那Java虚拟机将会抛出一个OutOfMemoryError异常。
3.4、方法区
方法区(Method Area)是可供各条线程共享的运行时内存区域。存储了每一个类的结构信息,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法
方法区在虚拟机启动的时候创建。
方法区的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。
方法区在实际内存空间中可以是不连续的。
Java虚拟机实现应当提供给程序员或者最终用户调节方法区初始容量的手段,对于可以动态扩展和收缩方法区来说,则应当提供调节其最大、最小容量的手段。
Java 方法区异常:
OutOfMemoryError: 如果方法区的内存空间不能满足内存分配请求,那Java虚拟机将抛出一个OutOfMemoryError异常。
注:
方法区常被称为持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大。(“持久代”概念针对HotSpot虚拟机而言,BEA JRockit、IBM J9等不存在此概念,且在HotSpot中将逐渐放弃永久代并改为采用Native Memory来实现方法区。JDK1.7开始逐步“去永久代”)
运行时常量池
运行时常量池(Runtime Constant Pool)是每一个类或接口的常量池(Constant_Pool)的运行时表现形式,它包括了若干种常量:编译器可知的数值字面量到必须运行期解析后才能获得的方法或字段的引用。
运行时常量池是方法区的一部分。每一个运行时常量池都分配在JVM的方法区中,在类和接口被加载到JVM后,对应的运行时常量池就被创建。
在创建类和接口的运行时常量池时,可能会遇到的异常:
OutOfMemoryError:当创建类和接口时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大内存空间后就会抛出OutOfMemoryError
3.5、Java堆
在JVM中,堆(heap)是可供各条线程共享的运行时内存区域,也是供所有类实例和数据对象分配内存的区域。
Java堆载虚拟机启动的时候就被创建,堆中储存了各种对象,这些对象被自动管理内存系统(Automatic Storage Management System,也即是常说的“Garbage Collector(垃圾回收器)”)所管理。这些对象无需、也无法显示地被销毁。
Java堆的容量可以是固定大小,也可以随着需求动态扩展,并在不需要过多空间时自动收缩。
Java堆所使用的内存不需要保证是物理连续的,只要逻辑上是连续的即可。
JVM实现应当提供给程序员调节Java 堆初始容量的手段,对于可动态扩展和收缩的堆来说,则应当提供调节其最大和最小容量的手段。
Java 堆异常:
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起,采用元空间代替永久代。元空间与永久代的区别是,元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。
4、参考资料
[1]http://chenzhou123520.iteye.com/blog/1585224,(其即参考自《深入理解Java虚拟机——JVM高级特性与最佳实践》)
Java虚拟机及运行时数据区的更多相关文章
- Java虚拟机一 运行时数据区(栈、堆、方法区等)
Java虚拟机的内存管理主要分两点:内存分配以及内存回收.· 一.内存分配图: 注: 所占区域的大小与实际的内存大小比例并无直接关系. 解读: 1.如图,分成两种颜色的内存区域,其中蓝色的是线程隔离的 ...
- 【Java虚拟机】运行时数据区
Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随 ...
- 深入理解Java虚拟机(一) 运行时数据区划分
前言:从我学Java的第一天开始,我的大学老师就告诉我 Java语言相比C.C++的语言有一个非常强大的功能,那就是自动内存管理:我们用Java编码时不需要申请或释放内存等,这些工作全部交由我们的Ja ...
- java虚拟机规范-运行时数据区
前言 java虚拟机是java跨平台的基石,本文的描述以jdk7.0为准,其他版本可能会有一些微调. 引用 java虚拟机规范 数据类型 java总共有两种数据类型:基本类型和引用类型.java虚拟机 ...
- Java虚拟机_运行时数据区
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途.各自的创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程启动 ...
- java内存区域----运行时数据区
Java虚拟机的内存区域也叫做java运行时数据区,共分为五个部分:程序计数器,方法区,本地方法栈,虚拟机栈和堆.方法区和堆是线程之间所共有的,程序计数器,本地方法栈,虚拟机栈是线程私有的.其中虚拟机 ...
- 深入理解Java虚拟机-JVM运行时数据区域
一.运行时数据区域 1.程序计数器 程序计数器( Program Counter Register) 是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器. Java虚拟机的多线程是 ...
- 【JVM】虚拟机初见-运行时数据区图解
本文是听咕泡XX公开课视频整理的笔记,较书本更为总结,感谢. 计算机模型(汇编知识):数据集(数据).指令集(操作指令,+-等).控制集(分支循环) JVM运行时的数据区: 程序计数器(每个线程都有) ...
- java虚拟机规范-运行时栈帧
前言 java虚拟机是java跨平台的基石,本文的描述以jdk7.0为准,其他版本可能会有一些微调. 引用 java虚拟机规范 java虚拟机规范-运行时数据区 java内存运行时的栈帧结构 java ...
随机推荐
- android基于口令加密快速搞懂(一)
import java.util.Random; import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypt ...
- SQL基础教程--实现增删查改功能(W3School)
1.SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法.但是 SQL 语言也包含用于更新 ...
- 管理者与下属谈话的技巧及注意点[持续更新ing]
1.谈话之前要明确谈话的内容.原则和目的(为什么谈,谈什么,要解决什么事) 2.谈话时间不宜过长,尽量控制在半小时以内,最好在每一个阶段或一个节点的时间上去谈 3.谈话单次内容不能过多,但要捉住重点, ...
- 突然想到一个问题:有关 cqrs 分离
大部分的系统,都是查询多,c少,那为什么我们不把q放在内存里面,而c直接操作数据库呢? 就如enode,c在内存,而q在数据库,当然q也很容易扩展到内存缓存上.二个enode案例demo,都可以让c的 ...
- Quartz2.0以上版本的单机和集群
(一)Quartz单机 1.Quartz简介 Quartz是一个完全由java编写的开源作业调度框架,能实现业务的定时调度.Quartz主要有三个核心调度器.任务和触发器: ①任务-JobDetail ...
- Eclipse使用Maven创建web3.0项目
安装Maven插件 这一步不细说了,自己下载的Eclipse-JAVA EE 版已自带 Maven插件 开始创建 文本1New一个 Maven Web App项目:File-->New--> ...
- java 后台开发关键词解释
bean类:是一些实体类,包括viewbean,databean等等.action类:可作为接收显示层的数据,连接显示层和业务逻辑实现层的控制层.model类:MVC中model层就是到层.在java ...
- 烂泥:ubuntu 14.04搭建OpenVPN服务器
本文由秀依林枫提供友情赞助,首发于烂泥行天下 公司分部需要连接公司内部的服务器,但是该服务器只允许公司内部的网络访问. 为了解决这个问题,打算使用VPN.对于VPN以前使用最多的是PPTP这个解决方案 ...
- Java并发基础总结
并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可 交互性将大大改善.现代的PC都有多个CPU或一个CPU中有多 ...
- windows系统下fis3安装教程
注意:在安装fis3前必须安装node和npm,详情请见官网http://nodejs.org node版本要求 0.8.x,0.10.x, 0.12.x,4.x,6.x,不在此列表中的版本不予支持. ...