在接下来的几天想总结下,JVM相关的一些内容,比如下面的这三个内容算是比较核心知识点了

1.运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量(栈)等。

2.垃圾回收机制: java 语言的优势之一就是它的自动内存管理,主要回收运行时数据区域的堆内存里的数据

3.类加载机制: 虚拟机首先需要把编译完成的字节码文件通过类加载器来加载到运行时数据区域

一个段Java代码的生命周期都会少不了上图这几个步骤,也就是Java代码首先会被编译成字节码文件,之后被类加载器加载到运行时数据区域,以及运行,垃圾收集器回收对象等等。

但今天我想介绍第一个知识点《运行时数据区域》

1 运行时数据区

Java虚拟机定义了一系列逻辑数据区域,有些是随着虚拟机的启动而创建,虚拟机的关闭而销毁。还有一部分是随着线程生命周期创建销毁的。

我们有必要深入了解这块的内容,因为它将决定服务器性能,首先我们需要对整个运行时区域由整体的认识并且了解了每个区域的生命周期以及作用之后才能通过相应的调参来提升系统性能。除此之外还有助于快速定位虚拟机的相关Error.

逻辑上可以划出一下6个区域分别是

1.1 PC寄存器

全名叫做 Program Counter Register 既然是叫做寄存器了那么肯定是需要存东西,那到底存的是什呢?
由于JVM同时可以处理多个线程所以就涉及到一些线程调度,当cpu暂停运行线程A把时间片让给线程B的时候我们需要保存线程A被暂停执行前的一些现场状态,需要记录当前执行到那一行字节码了,所以具备保存现场的功能。

每条线程都有自己的pc寄存器,在任意时刻虚拟机只会执行一个方法

如果执行的是方法不是native方法 pc寄存器则保存指向当前执行字节码的指令地址

如果执行的是native方法 pc寄存器会保存undefined

1.2 java虚拟机栈

虚拟机栈也是每条线程私有的区域,里头存储栈帧(Frame),后面会重点介绍栈帧算是重点内容。方法的调用与返回基于栈帧来实现的。

1.3 虚拟机堆

在Java虚拟机中堆是所有线程都可以共享的内存区域,是存放所有类实例和数组对象的地方。在虚拟机启动就根据相关堆参数,创建堆,他也是垃圾收集器工作的主要区域。
堆内存里的对象不会被显式的回收,而是由垃圾回收器回收

为了配合垃圾收集器的特性我们可以把堆分为年轻代和老年代

年轻代又分了Eden和survivor区,主要是为了配合垃圾回收算法而这么搞得。

1.4 方法区和运行时常量池

在Java虚拟机中 方法区是可提供各个线程共享的运行时内存区域,它存储了每一个类的结构信息,例如运行时常量池,字段和方法数据,构造函数和普通函数的字节码内容,一句话总结就是存储元数据地方

运行时常量池是class文件中每个类或接口常量池表的表示形式。它包括了若干不同的常量,比如 从编译期可知的数值字面量到运行时才能解析获得的方法或字段引用等等。

创建时机
每个运行时常量池都在Java虚拟机的方法区中分配,在加载类和接口到虚拟机之后创建对应的运行时常量池

1.5 本地方法栈

如果我们想再Java底层里调用别的语言代码的话就需要用到别的方法栈了,比如Java虚拟机的实现会用到传统的栈(C stack)来调用native方法,这个就是本地方法栈的应用,当然这个不是必须实现的,完全取决于虚拟机的实现。

2 栈帧:

首先看下栈帧在虚拟机内存中在什么位置,

栈帧是用来存储数据和部分过程结果的数据结构,同时也用来处理动态链接,方法返回,异常分派等工作。栈帧的生命周期是跟方法一致的,随着方法的调用而创建,方法的结束或者异常而销毁。
每个栈帧都由局部变量表,操作数栈,动态链接组成的

2.1 局部变量表 (Local variable)

每个栈帧内部都包含一组称为局部变量表的列表,变量表的长度在编译期决定。
一个局部变量可以存储一个基本数据类型或一个对象引用(referance),returnAddress的数据。存储long或double需要两个局部变量才能存储。

当虚拟机要使用局部变量表里的数据时通过索引来定位,默认从0开始,由于long和double占用两个局部变量所以它的索引较特殊,取决于最小的那个值,比如某个long类型数据在索引n和n+1里存储了,那么它对应的索引值就是n.
虚拟机通过局部变量表来完成方法调用时的参数传递。如果是类方法,它的参数依次从0开始的位置传递到局部变量表,如果是实例方法则第0位置存储所在对象的引用(this),从1开始传递参数。

2.2 操作数栈 (Operating Stack)

操作数栈是属于栈帧中的栈,其实它的全名叫做当前栈帧的初操作数栈。栈,栈帧,操作数栈的关系需要梳理清楚:

  • 栈:是虚拟机运行时数据区的一个逻辑区域,里面存储了一个个栈帧。
  • 栈帧:栈帧代表一个方法的整个生命周期,里头存储了局部变量表,操作数栈,动态链接
  • 操作数栈: 刚刚创建时操作数栈是空的。虚拟机提供一些指令从局部变量表把一些常量或者变量值加载到操作数栈,也提供了从操作数栈取走数据的指令。
    调用方法时操作数栈用来准备调用方法参数以及接受方法的返回结果。

2.3 动态链接 (Dynamic Linking)。

动态链接是用来完成运行时绑定操作的。在栈帧中有一个指向常量池的当前类的一个引用。在class文件里一个方法要是调用其他方法或者方法其他成员变量,则需要通过符号引用来表示。

  • 动态链接的作用就是将符号引用转换为直接引用。
  • 类加载的过程中将要解析尚未被解析的符号引用,并且把对变量的访问转换为正确的偏移量。

JVM三部曲之运行时数据区 (第一部)的更多相关文章

  1. JVM学习笔记-运行时数据区

    不同于C,C++程序,Java程序的内存管理工作由Java虚拟机(JVM)接管,这减低了java程序员的负担,但如果出现内存泄露与溢出问题如报OutOfMemory,StackOverFlow异常错误 ...

  2. 1、JVM 内存模型+运行时数据区+JVM参数

    JMM(内存模型)  1.’主内存+每个线程有自己的内存 JVM运行时数据区 包含:1.程序计算器(每个线程自带):2.JAVA-STACK(每个线程自带):3.本地方法stack:4.堆:5.方法区 ...

  3. jvm内存模型(运行时数据区)

    运行时数据区(runtime data area) jvm定义了几个运行时数据区,这些运行时数据区存储的数据,供开发者的应用或者jvm本身使用.按线程共享与否可以分为线程间共享和线程间独立. 线程间独 ...

  4. JVM内存结构——运行时数据区

    在Java虚拟机规范中将Java运行时数据划分为6种,分别为: PC寄存器(程序计数器) Java栈 堆 方法区 运行时常量池 本地方法栈 一.PC寄存器(程序计数器) PC寄存器(Program C ...

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

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

  6. JVM之Java运行时数据区(线程共享区)

    JVM运行时区域各线程共享的区域包括堆区和方法区. 堆区 堆区最最主要的功能是存储对象实例[上篇也提到过],因此Java垃圾回收的主要战场就是在堆区,因此也有称为GC堆区.如果堆区的内存不够会出现Ou ...

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

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

  8. JVM入门——运行时数据区

    这张图我相信基本上对JVM有点接触的都应该很熟悉,可以说这是JVM入门的第一课.其中的“堆”和“虚拟机栈(栈)”更是耳熟能详.下面将围绕这张图对JVM的运行时数据区做一个简单介绍. 程序计数器(Pro ...

  9. 深入理解JVM(2)——运行时数据区

    1.运行时数据区 1.1.程序计数器 记录当前线程正在执行的字节码指令的地址,如果正在执行的是 Native 方法,这个计数器值则为空. 1.2.虚拟机栈 每个 Java 方法在执行的同时会创建一个栈 ...

随机推荐

  1. Mycat 关键特性

    关键特性 支持SQL92标准 支持MySQL.Oracle.DB2.SQL Server.PostgreSQL等DB的常见SQL语法 遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理. ...

  2. SpringBootSecurity学习(13)前后端分离版之JWT

    JWT 使用 前面简单介绍了把默认的页面登录改为前后端分离的接口异步登录的方法,可以帮我们实现基本的前后端分离登录功能.但是这种基本的登录和前面的页面登录还有一个一样的地方,就是使用session和c ...

  3. mysql操作遇到的坑(第二版)

    1.通过条件查询出上一条与下一条 sql说明:本表关联本表,然后通过其中一个表,查询出对应的条件,再用另外一个表求出上一条与下一条的数据,求出来的数据是多条的 SELECT ua.id, ua.wx_ ...

  4. mysql操作遇到的坑(第一版)

    1.当我们要统计数据表数量时,如果遇到多表查询,会出现一个主表对应多个子表的维度,我们会用到group by,但是不要再用统计函数去操作数据,因为统计还是会统计原数据 案例 SELECT sum(`o ...

  5. Python 正则re匹配中文、英式数字

    #coding:utf-8 import re s = u''' 或多或少的好好读书电锯惊魂20202 和水电费后是否会时候1212没收到风10.12海大富的是粉红色的和办法的1244525.000 ...

  6. ieTESTER浏览器使用ie6崩溃问题

    打开浏览器在选项--internet属性--连接--局域网设置--将自动检测设置的对勾勾掉就可以  重启下浏览器

  7. LitePal的基本用法

    快速配置   1. 引入Jar包或源码 首先我们需要将LitePal的jar包引入到项目当中,可以点击这里查看LitePal的最新版本,选择你需要的下载即可.下载好了jar包之后,把它复制到项目的li ...

  8. asp.net 开源工作流-ccflow关于 “ 是否自动计算未来的处理人”的功能变更

    关键字:流程未来节点处理人  工作流快速开发平台  工作流流设计  业务流程管理   asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向.对于另 ...

  9. ASRWGAN: Wasserstein Generative Adversarial Network for Audio Super Resolution

    ASEGAN:WGAN音频超分辨率 这篇文章并不具有权威性,因为没有发表,说不定是外国的某个大学的毕业设计,或者课程结束后的作业.或者实验报告. CS230: Deep Learning, Sprin ...

  10. 关于Git的使用方法

    1.查看Git的使用方法 : git 2.把当前文件夹变为一个git仓库 创建git仓库:git init 3.查看当前仓库文件变化情况:git status 4.添加修改:git add (可使用g ...