在接下来的几天想总结下,JVM相关的一些内容,好比下面的这三个内容算是比较核心知识点了java
1.运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量(栈)等。算法
2.垃圾回收机制: java 语言的优点之一就是它的自动内存管理,主要回收运行时数据区域的堆内存里的数据数组
3.类加载机制: 虚拟机首先须要把编译完成的字节码文件经过类加载器来加载到运行时数据区域服务器
一个段Java代码的生命周期都会少不了上图这几个步骤,也就是Java代码首先会被编译成字节码文件,以后被类加载器加载到运行时数据区域,以及运行,垃圾收集器回收对象等等。数据结构
但今天我想介绍第一个知识点《运行时数据区域》函数
Java虚拟机定义了一系列逻辑数据区域,有些是随着虚拟机的启动而建立,虚拟机的关闭而销毁。还有一部分是随着线程生命周期建立销毁的。性能
咱们有必要深刻了解这块的内容,由于它将决定服务器性能,首先咱们须要对整个运行时区域由总体的认识而且了解了每一个区域的生命周期以及做用以后才能经过相应的调参来提高系统性能。除此以外还有助于快速定位虚拟机的相关Error.this
逻辑上能够划出一下6个区域分别是 线程
全名叫作 Program Counter Register 既然是叫作寄存器了那么确定是须要存东西,那到底存的是什呢?
因为JVM同时能够处理多个线程因此就涉及到一些线程调度,当cpu暂停运行线程A把时间片让给线程B的时候咱们须要保存线程A被暂停执行前的一些现场状态,须要记录当前执行到那一行字节码了,因此具有保存现场的功能。cdn
每条线程都有本身的pc寄存器,在任意时刻虚拟机只会执行一个方法
若是执行的是方法不是native方法 pc寄存器则保存指向当前执行字节码的指令地址
若是执行的是native方法 pc寄存器会保存undefined
虚拟机栈也是每条线程私有的区域,里头存储栈帧(Frame),后面会重点介绍栈帧算是重点内容。方法的调用与返回基于栈帧来实现的。
在Java虚拟机中堆是全部线程均可以共享的内存区域,是存放全部类实例和数组对象的地方。在虚拟机启动就根据相关堆参数,建立堆,他也是垃圾收集器工做的主要区域。 堆内存里的对象不会被显式的回收,而是由垃圾回收器回收
为了配合垃圾收集器的特性咱们能够把堆分为年轻代和老年代
年轻代又分了Eden和survivor区,主要是为了配合垃圾回收算法而这么搞得。
在Java虚拟机中 方法区是可提供各个线程共享的运行时内存区域,它存储了每个类的结构信息,例如运行时常量池,字段和方法数据,构造函数和普通函数的字节码内容,一句话总结就是存储元数据地方
运行时常量池是class文件中每一个类或接口常量池表的表示形式。它包括了若干不一样的常量,好比 从编译期可知的数值字面量到运行时才能解析得到的方法或字段引用等等。
建立时机 每一个运行时常量池都在Java虚拟机的方法区中分配,在加载类和接口到虚拟机以后建立对应的运行时常量池
若是咱们想再Java底层里调用别的语言代码的话就须要用到别的方法栈了,好比Java虚拟机的实现会用到传统的栈(C stack)来调用native方法,这个就是本地方法栈的应用,固然这个不是必须实现的,彻底取决于虚拟机的实现。
首先看下栈帧在虚拟机内存中在什么位置,
栈帧是用来存储数据和部分过程结果的数据结构,同时也用来处理动态连接,方法返回,异常分派等工做。栈帧的生命周期是跟方法一致的,随着方法的调用而建立,方法的结束或者异常而销毁。 每一个栈帧都由局部变量表,操做数栈,动态连接组成的
每一个栈帧内部都包含一组称为局部变量表的列表,变量表的长度在编译期决定。 一个局部变量能够存储一个基本数据类型或一个对象引用(referance),returnAddress的数据。存储long或double须要两个局部变量才能存储。
当虚拟机要使用局部变量表里的数据时经过索引来定位,默认从0开始,因为long和double占用两个局部变量因此它的索引较特殊,取决于最小的那个值,好比某个long类型数据在索引n和n+1里存储了,那么它对应的索引值就是n. 虚拟机经过局部变量表来完成方法调用时的参数传递。若是是类方法,它的参数依次从0开始的位置传递到局部变量表,若是是实例方法则第0位置存储所在对象的引用(this),从1开始传递参数。
操做数栈是属于栈帧中的栈,其实它的全名叫作当前栈帧的初操做数栈。栈,栈帧,操做数栈的关系须要梳理清楚:
动态连接是用来完成运行时绑定操做的。在栈帧中有一个指向常量池的当前类的一个引用。在class文件里一个方法要是调用其余方法或者方法其余成员变量,则须要经过符号引用来表示。