JVM的结构介绍

一、前言

为什么要学习了解Java虚拟机

1.我们需要更加清楚的了解Java底层是如何运作的,有利于我们更深刻的学习好Java。
  2.对我们调试错误提供很宝贵的经验。
  3.这是合格的Java程序必须要了解的内容。

二、Java虚拟机的定义

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

1.抽象规范。
2.一个具体的实现。
3.一个运行中的虚拟机实例。

Java虚拟机抽象规范仅仅是一个概念,在《The Java Virtual Machine Specification》(java虚拟机规范)中有详细的描述。该规范的实现,可能来自多个提供商,并存在于多个平台上,它或者是全部由软件实现,或者是以硬件和软件相结合的方式来实现。当运行一个Java程序的时候,也就在运行一个Java虚拟机实例。注意,我们所说的Java平台无关性是指class文件的平台无关性,JVM是和平台相关的,不同操作系统对应不同的JVM。

三、Java虚拟机的总体框架图

下图是整个Java虚拟机的总体框架图,之后我们会经常涉及到。

四、Java虚拟机的体系结构

下图表示了Java虚拟机的结构框图,主要描述了JVM子系统和内存区。

五、Java虚拟机各组成部分

5.1 类装载子系统

类装载子系统负责查找并装载类型,Java虚拟机由两种类装载器:启动类装载器(Java虚拟机实现的一部分)和用户自定义类装载器(Java程序的一部分)。类装载子系统负责定位和导入二进制class文件,并且保证导入类的正确性,为类变量分配并初始化内存,以及帮助解析符号引用。类装载器必须严格按照如下顺序进行类的装载。

1) 装载 -- 查找并装载类型的二进制数据
2) 连接 -- 执行验证,准备,以及解析(可选),连接分为如下三个步骤

验证 -- 确保被导入类型的正确性
    准备 -- 为类变量分配内存,并将其初始化为默认值
    解析 -- 把类型中的符号引用转换为直接引用

3) 初始化 -- 把类变量初始化为正确初始值

启动类装载器 -- Java虚拟机必须有一个启动类装载器,用于装载受信任的类,如Java API的class文件。
  用户自定义类装载器 -- 继承自ClassLoader类,ClassLoader的如下四个方法,是通往Java虚拟机的通道。
    1. protected final Class defineClass(String name, byte data[], int offset, int length);
    2. protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain);
    3. protected final Class findSystemClass(String name);
    4. protected final void resolveClass(Class c);
  这四个方法涉及到了装载和连接两个阶段,defineClass方法data参数为二进制Java Class文件格式,表示一个新的可用类型,之后把这个类型导入到方法区中。findSystemClass的参数为全限定名,通过类装载器进行装载。resolveClass参数为Class实例,完成连接初始化操作。

5.2 方法区

方法区是线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError(内存溢出)。
  类信息包括

1.类型全限定名。
2.类型的直接超类的全限定名(除非这个类型是java.lang.Object,它没有超类)。
3.类型是类类型还是接口类型。
4.类型的访问修饰符(public、abstract、final的某个子集)。
5.任何直接超接口的全限定名的有序列表。
6.类型的常量池。
7.字段信息。
8.方法信息。
9.除了常量以外的所有类(静态)变量。
10.一个到类ClassLoader的引用。
11.一个到Class类的引用。

着重介绍常量池 -- 虚拟机必须要为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量和对其他类型、字段和方法的符号引用。它在Java程序的动态连接中起着核心作用。

5.3 堆

一个虚拟机实例只对应一个堆空间,堆是线程共享的。堆空间是存放对象实例的地方,几乎所有对象实例都在这里分配。堆也是垃圾收集器管理的主要区域。堆可以处于物理上不连续的内存空间中,只要逻辑上相连就行,当堆中没有足够的内存进行对象实例分配时,并且堆也无法扩展时,会抛出OutOfMemoryError异常。

5.4 程序计数器

每个线程拥有自己的程序计数器,线程之间的程序计数器互不影响。PC寄存器的内容总是下一条将被执行指令的"地址",这里的"地址"可以是一个本地指针,也可以是在方法字节码中相对于该方法起始指令的偏移量。如果该线程正在执行一个本地方法,则程序计数器内容为undefined,此区域在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

5.5 Java栈

Java栈也是线程私有的,虚拟机只会对栈进行两种操作,以帧为单位的入栈和出栈。每个方法在执行时都会创建一个帧,并入栈,成为当前帧。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。
  局部变量区被组织为一个以字长为单位、从0开始计数的数组。字节码指令通过从0开始的索引来使用其中的数据。类型为int、float、reference和return Address的值在数组中只占据一项,而类型为byte、short和char的值存入时都会转化为int类型,也占一项,而long、double则连续占据两项。
  关于局部变量区给出如下一个例子。
View Code
  
  可以看到类方法的首项中没有隐含的this指针,而对象方法则会隐含this指针。并且byte,char,short,boolean类型存入局部变量区的时候都会被转化成int类型值,当被存回堆或者方法区时,才会转化回原来的类型。
  操作数栈被组织成一个以字长为单位的数组,它是通过标准的栈操作-入栈和出栈来进行访问,而不是通过索引访问。入栈和出栈也会存在类型的转化。
  栈数据区存放一些用于支持常量池解析、正常方法返回以及异常派发机制的信息。即将常量池的符号引用转化为直接地址引用、恢复发起调用的方法的帧进行正常返回,发生异常时转交异常表进行处理。

5.6 本地方法栈

访问本地方式时使用到的栈,为本地方法服务,本地方法区域也会抛出StackOverflowError(栈溢出)和OutOfMemoryError(内存溢出)异常。

5.7 执行引擎

用户所编写的程序如何表现正确的行为需要执行引擎的支持,执行引擎执行字节码指令,完成程序的功能。后面会详细介绍。

5.8 本地方法接口

本地方法接口称为JNI,是为可移植性准备的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • JAVA虚拟机的生命周期 一个运行时的Java虚拟机实例的天职是:负责运行一个java程序。当启动一个Java程序...
    Solang阅读 1,173评论 0 19
  • JVM内存模型Java虚拟机(Java Virtual Machine=JVM)的内存空间分为五个部分,分别是: ...
    光剑书架上的书阅读 2,499评论 2 26
  • 一、 陈光走出塑料布搭的炒饭摊子时,一连下了好几天的雨还在下着,雨滴砸在塑料棚顶上啪嗒啪嗒的声音像砸在头皮上。他把...
    春尽阅读 448评论 2 0
  • 十月秋雨 情 作者:屿上日光 风飞扬孤叶飘零, 哪方是浪子归宿? 秋风萧萧云翻卷, 雨落秋凉君何处? 丝丝水滴...
    屿上日光阅读 262评论 1 1
  • 中秋,中国一个最最传统的节日,寄托着无数远方游子那颗思乡的心,尽管我已在离家乡不远的城市里安家落户,有了新的...
    游仔阅读 232评论 0 0