前情回想

在本专栏的前12篇博客中。 我们主要大致介绍了什么是JVM, 而且具体介绍了class文件的格式。 对于深入理解Java, 或者深入理解运行于JVM上的其它语言, 深入理解class文件格式都是必须的。 假设读者对class文件的格式不是非常熟悉, 在阅读本博客以下的文章之前。 建议先读一下前面的12篇博客。 或者參考其它资料, 熟悉class文件的格式。 

深入理解Java虚拟机究竟是什么 这篇博客中, 我们有提到过, JVM就是一个特殊的进程, 我们运行的java程序。 都运行在一个JVM进程中, 这个进程的作用就是载入class文件, 而且运行class文件里的代码。 当然。 从一个class文件的载入。
到准备好可运行之前。 另一段非常长的路要走, 以后的文章会具体介绍这个过程。 既然虚拟机作为一个虚拟的计算机, 来运行我们的程序, 那么在运行的过程中。 必定要有地方存放我们的代码(class文件)。 在运行的过程中, 总会创建非常多对象, 必须有地方存放这些对象; 在运行的过程中, 还须要保存一些运行的状态。 比方, 将要运行哪个方法, 当前方法运行完毕之后, 要返回到哪个方法等信息。 所以, 必须有一个地方来保持运行的状态。

上面的描写叙述中, “地方”指的当然就是内存区域, 程序运行起来之后。 就是一个动态的过程,
必须合理的划分内存区域。 来存放各种数据。 所以。 在本文中, 将会具体介绍JVM的运行时数据区。

 

JVM体系结构和运行时数据区概述

要理解JVM的运行时数据区。 必须先要理解JVM的体系结构, 由于虚拟机的体系结构基本上解释了“为什么会有这些运行时数据区” 。 在深入理解Java虚拟机究竟是什么 这篇文章中也简单的提到过JVM的体系机构, 这里再具体的解说一下。 JVM的体系结构例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmdqZ19ibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

由此可见, 运行时数据区的划分。 是和JVM的体系结构相关的。 本文主要介绍运行时数据区的划分, 对体系结构不做深入的解说。 简单概括一下, 类载入器子系统用于将class文件载入到虚拟机的运行时数据区中(准确的说应该是方法区) 。 能够觉得运行引擎是字节码的运行机制, 一个线程能够看做是一个运行引擎的实例。 以下介绍运行时数据区:

JVM运行时数据区

方法区

在字面意思上。 “方法区”这个词会让人产生误解。由于方法区存放的不仅仅是方法, 它存放的是类型信息。我们在敲代码的时候, 差点儿总是在和类。 对象打交道, 我们知道依据一个类能够创建对象。 一般来说。 我们操纵的是对象。 訪问对象的属性。 调用对象的方法等, 可是我们要思考这样一个问题, 虚拟机依据什么信息知道怎样创建对象的呢? 当然是依据这个对象的类型信息, 可是这个类型信息在哪里呢?如今我们知道是在方法区中。 那么类型信息是被谁载入到方法区中的呢?由上面的体系结构图,
我们能够知道是类载入器子系统?那么所谓的类型信息, 都包括什么信息呢?这些信息又是怎样存放的呢?这里的类型信息, 能够笼统的觉得就是我们前面解说过的一个class文件,类载入器子系统将会提取class文件里面的类型信息,并将这些类型信息存放到方法区中。

 至于方法区中怎样存放一个类型数据, 是和JVM的具体实现相关的。 可是无论怎样实现, 一个类的类型信息总是会包括例如以下信息:

类的全限定名
当前类的直接父类的全限定名
这个类是接口类型, 类类型。 还是枚举类型
类的訪问修饰符信息
当前类型的超接口的全限定名
当前类型的常量池
字段信息
方法信息

假设对class文件格式比較熟悉的话。 能够看出, 这些信息都是在class文件里描写叙述过的。 由于我们无法看到类型信息具体是怎样存储的。 可是大致能够将类型信息看做一个class文件, 这有助于我们的理解。

以下再次列出class文件结构的表格。读者能够对照class文件里的内容到类型数据上。 该表中的各种数据已经在前面的博客中具体解说过:

 类型数据中。除了这些基本信息外, 类型信息还包括以下两个方面:

一个到类的ClassLoader对象的引用
一个到表示该类的Class实例对象的引用

静态变量存储区

由于之前的博客中具体介绍过class文件的格式, 对上面的一些基本信息我们可能比較熟悉。 可是对这两种信息就比較陌生了。

事实上说来也简单,每一个class都是被一个类载入器载入到方法区的, 类型信息中的到类的ClassLoader对象的引用, 表明了当前的类是被哪个类载入器载入的, 这个信息同一时候也标示了当前的类型的名称空间。 

每当一个class文件被成功的载入到方法区中, JVM总会创建一个Class对象, 来唯一标示这个类。

这个Class对象能够看做是类载入过程的产物。 由于它描写叙述了整个类型信息。 而Java中的反射也是针对的类型信息。 所以这个Class对象是反射的基石。 大多数反射API都是依据Class对象来实现的。  

而静态变量也是存在于类型信息中, 能够这么说, 类型信息中, 会有专门的区域存放类的静态变量。 与存在于对象中的实例变量不同, 静态变量存在于类型数据中, 每一个类型仅仅有一份。所以也叫类变量。 

方法区是一个相对来说比較固定的内存区, 由于它存放的是类型信息, 而类型信息在被载入到方法区中之后, 除了必要的连接和初始化。 一般不会有较大修改。普通情况下, JVM也不会卸载类型信息。 所以方法区也能够称为JVM的静态区。 一个类型的生命周期一般就是整个程序的生命周期。 这也是为什么要慎用静态变量的原因所在, 由于静态变量随类型信息存放在方法区中。 生命周期非常长, 假设使用不当。 非常easy造成内存泄露。

一个JVM实例中仅仅存在一个方法区, 方法区中的全部类型数据被全部线程共享。

方法区是存放类型数据的, 而堆则是存放运行时产生的对象的。 和C++不同的是。 Java仅仅能在堆中存放对象。 而不能在栈上分配对象, 全部运行时产生的对象全部都存放于堆中, 包括数组。

我们知道, 在Java中, 数组也是对象。一个JVM实例中仅仅有一个堆, 全部线程共享堆中的数据(对象) 。 

Java虚拟机支持几种不同的创建对象的指令, 如new 。 anewarray等。 这些指令运行的结果就是在堆中分配内存。 并创建对象。 可是Java虚拟机的指令集中并不包括不论什么释放内存的指令, 因而我们也就不能手动释放内存。 全部被创建的对象都会被一个叫做垃圾收集器(GC)的模块自己主动回收。 垃圾收集器有不同的实现方式, 他们以 特定的方式推断对象是否过期, 并以特定的方式对对象进行回收, 关于垃圾收集的话题不是本文的重点, 这里就不多说了。
我们仅仅要知道:全部创建的对象都存在堆中。 而垃圾收集器会自己主动回收过期的对象。 所以,JVM的堆区是垃圾收集器的“重点管理区” 。

Java栈

Java栈是一个线程的运行区域, 它保存着一个线程中的方法的调用状态, 也能够说, 一个Java线程的运行状态。 都由一个Java栈来保存。 在这个栈中, 每一方法相应一个栈帧, 请注意区分栈帧和栈这两个概念。

栈指的是整个线程的运行栈, 栈帧是栈中的一个单位, 每一个方法相应一个栈帧。 JVM会对Java栈运行两种操作: 压栈和出栈。 这两种操作在运行时都是以帧(栈帧)为单位的。 当调用了一个新的方法, 就会压入一个栈帧, 当一个方法调用完毕,
就会弹出这种方法的栈帧, 回到调用者的栈帧。 

举例来说。 假设方法a调用了方法b, 而方法b中调用了方法c。 这个过程中的方法调用和返回的装状态是这种(当中图中两条虚线之间表示Java栈,每一个方块表示一个特定方法的栈帧)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmdqZ19ibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

Java栈上的全部数据都是线程私有的, 也就是说, 每一个线程都会有自己的Java栈, 不会相互訪问其它Java栈中的数据。 

PC寄存器

pc寄存器用于存放一条指令的地址, 这条指令就是虚拟机要运行的下一条指令。pc寄存器和线程相关联, 每一个线程都有一个PC寄存器。

本地方法栈

我们知道Java能够和C/C++互调。假设当前线程运行的代码是C/C++写的本地代码。 那么这些方法就在本地方法栈中运行。而不会在Java栈中运行, Java栈中仅仅运行Java方法。

深入理解Java执行时数据区的更多相关文章

  1. 《Java虚拟机原理图解》3、JVM执行时数据区

    [last updated :2014/11/7]     JVM执行时数据区(JVM Runtime Area)事实上就是指JVM在执行期间,其对计算机内存空间的划分和分配.本文将通过下面几个话题来 ...

  2. Jvm基础(1)-Java运行时数据区

    最近在看<深入理解Java虚拟机>,里面讲到了Java运行时数据区,这是Jvm基本知识,把读书笔记记录在此.这些知识属于常识,都能查到的,如果我有理解不对的地方,还请指出. 首先把图贴上来 ...

  3. 读书笔记-浅析Java运行时数据区

    作为一个 Java 为主语言的程序员,我偶尔也需要 用 C/C++ 写程序,在使用时让我很烦恼的一件事情就是需要对 new 出来的对象进行 delete/free 操作,我老是担心忘了这件事情,从而导 ...

  4. 【转】Java运行时数据区简介及堆与栈的区别

    理解JVM运行时的数据区是Java编程中的进阶部分.我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机 ...

  5. 一个“Hello World”理解JVM运行时数据区

    先上一张JVM体系结构图: 1)运行时数据区:经过编译生成的字节码文件(class文件),由class loader(类加载子系统)加载后交给执行引擎执行.在执行引擎执行的过程中产生的数据会存储在一块 ...

  6. Java 运行时数据区

    写在前面 本文描述的有关于 JVM 的运行时数据区是基于 HotSpot 虚拟机. 概述 JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以 ...

  7. Java 运行时数据区和内存模型

    运行时数据区是指对 JVM 运行过程中涉及到的内存根据功能.目的进行的划分,而内存模型可以理解为对内存进行存取操作的过程定义.总是有人望文生义的将前者描述为 "Java 内存模型" ...

  8. Java运行时数据区

    目录 1. 概述 2. Java内存结构 3. 程序计数器 4. Java虚拟机栈 5. 本地方法栈 6. 堆 7. 方法区 8. 运行时常量池 9. 直接内存 10. 总结 1. 概述 作为日常的J ...

  9. JVM之Java运行时数据区(线程隔离区)

    来源 JVM会在会在执行Java程序过程中把所管理的内存划分为若干区域,主要包括程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native ...

随机推荐

  1. PS学习笔记(01)

    [1]PS,文件-脚本-删除所有的空图层.   [2]设计师与美工的区别? 设计在于有思路了再去找素材, 美工在于有素材后再去设计 (思路是在大量的设计上,才累计出来的.)   [3]如何知道一张图片 ...

  2. Python Tornado简单的http request

    这是关于chunk encoding传输以前相关传输编码的处理.没有做压缩解码的处理. import tornado.ioloop import tornado.iostream import soc ...

  3. 大数据学习——mapreduce倒排索引

    数据 a.txt hello jerry hello tom b.txt allen tom allen jerry allen hello c.txt hello jerry hello tom 1 ...

  4. google的三篇论文

    文章:MapReduce/GFS/BigTable三大技术资料 文章:Google File System(中文翻译) 文章:MapReduce:超大机群上的简单数据处理 文章:Google's Bi ...

  5. CodeForces - 592D Super M 题解

    题目大意: 一棵树 n个点 有m个点被标记 求经过所有被标记的点的最短路径的长度以及起点(如有多条输出编号最小的起点). 思路: 1.当且仅当一个点本身或其子树中有点被标记时该点在最短的路径上因此,可 ...

  6. 【枚举】Southwestern Europe Regional Contest H - Sheldon Numbers

    https://vjudge.net/contest/174235#problem/H [题意] 求[x,y]之间有多少个Sheldon Number Sheldon Number是二进制满足以下条件 ...

  7. 洛谷P3406 海底高铁

    题目背景 大东亚海底隧道连接着厦门.新北.博艾.那霸.鹿儿岛等城市,横穿东海,耗资1000亿博艾元,历时15年,于公元2058年建成.凭借该隧道,从厦门可以乘坐火车直达台湾.博艾和日本,全程只需要4个 ...

  8. python之-- 异常

    异常处理: 语法:try: codeexcept (KeyError..可以写多个) as e: error为抓取的多个错误提示,e为错误信息 print(e) # 打印错误信息except (Ind ...

  9. JVM内存区域(运行时数据区)划分

    前言: 我们每天都在编写Java代码,编译,执行.很多人已经知道Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文 ...

  10. 学习日常笔记<day15>mysql基础

    1.数据库入门 1.1数据库软件 数据库:俗称数据的仓库,方便管理数据的软件(或程序) 1.2市面上数据库软件 Oracle,甲骨文公司的产品. 当前最流行应用最广泛的数据库软件.和java语言兼容非 ...