Java架构师JVM启动流程和内存结构,程序员必看!

JVM启动流程java

JVM是Java程序运行的环境,同时是一个操做系统的一个应用程序进程,所以它有本身的生命周期,也有本身的代码和数据空间。 JVM工做原理和特色主要是指操做系统装入JVM,是经过jdk中Java.exe来完成,经过下面4步来完成JVM环境。算法

1.建立JVM装载环境和配置 JVM装入环境,JVM提供的方式是操做系统的动态链接文件数组

2.装载JVM.dll 经过第一步已经找到了JVM的路径,Java经过LoadJavaVM来装入JVM.dll文件.装入工做很简单就是调用Windows API函数: LoadLibrary装载JVM.dll动态链接库.而后把JVM.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。JVM.dll的装载工做宣告完成。

3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 这样就能够在Java中调用JVM的函数了.调用InvocationFunctions->CreateJavaVM也就是JVM中JNI_CreateJavaVM方法得到JNIEnv结构的实例.安全

4.调用JNIEnv实例装载并处理class类。markdown

JVM基本结构架构

JVM体系主要是两个JVM的内部体系结构分为三个子系统和两大组件,分别是:类装载器(ClassLoader)子系统、执行引擎子系统和GC子系统,组件是内存运行数据区域和本地接口。函数

· 程序计数器(PC寄存器) PC(Program Couneter)寄存器是每一个线程私有的,Java虚拟机会为每一个线程建立PC寄存器,在任意时刻,一个Java线程老是在执行一个方法,这个方法称为当前方法,若是当前方法不是本地方法,PC寄存器总会执行当前正在被执行的指令,若是是本地方法,则PC寄存器值为Underfined。每执行一条指令 PC 都会自增,所以 PC 存储了指向下一条要被执行的指令地址。JVM 用 PC 来跟踪指令执行的位置,PC 将其实是指向方法区(Method Area)的一个内存地址。

· 方法区(永久代) 方法区存储了每一个类的信息,好比类型的常量池、字段,方法信息、方法字节码。全部线程共享同一个方法区,所以访问方法区数据的和动态连接的进程必须线程安全。若是两个线程试图访问一个还未加载的类的字段或方法,必须只加载一次,并且两个线程必须等它加载完毕才能继续执行。spa

(JDK1.7中,已经把放在永久代的字符串常量池移到堆中。JDK1.8撤销永久代,引入元空间。元空间是直接存在内存中,不在java虚拟机中的,所以元空间依赖于内存大小。固然你也能够自定义元空间大小。) · 方法区不须要连续的内存,能够选择固定大小或者可扩展。而且还能够选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并不是数据进入了方法区就如永久代的名字同样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,通常来讲这个区域的回收“成绩”比较难以使人满意,尤为是类型的卸载,条件至关苛刻,可是这部分区域的回收确实是有必要的。当方法区没法知足内存分配需求时,将抛出OutOfMemoryError异常。操作系统

· 堆(Heap) 应用系统对象都保存在Java堆中,堆被用来在运行时分配类实例、数组。不能在栈上存储数组和对象。由于栈帧被设计为建立之后没法调整大小。栈帧只存储指向堆中对象或数组的引用。与局部变量数组(每一个栈帧中的)中的原始类型和引用类型不一样,对象老是存储在堆上以便在方法结束时不会被移除。对象只能由垃圾回收器移除。全部线程共享Java堆。线程

简述垃圾回收 为了支持分代垃圾回收机制,堆内存能够划分为新生代和老年代两个区域(默认新生代与老年代的空间大小为1:2)。新生代能够再划分为Eden区、From Survivor区和To Survivor区(三者比例为8:1:1)。几乎全部的新对象的建立都是在Eden区进行的。在垃圾回收(GC)过程当中,Eden中的活跃对象会被转移到Survivor区,当再到达必定的年龄(经历过的Minor GC的次数,每通过一次新生代回收,若是对象存活则它的年龄就加1,对象达到必定的年龄后),会被转移到老年代中。

复制算法

· Java栈(Java Stack) Java栈是线程私有的内存区域,其中存储的是栈帧。,每一次方法调用建立一个帧,并压栈,调用完毕出栈。下面是内存的线程公有私有示意图:

若是方法methodOne方法调用了methodTwo,那么methodOne就会先入栈建立一个栈桢,接着methodTwo再入栈成为栈顶(假设没有其余的方法执行),methodTwo执行完先出栈,接着methodOne执行完出栈。

通常由三部分组成:局部变量表、操做数据栈和帧数据区 局部变量表:能够存放的数据有8种基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用和returnAddress类型。其中long和double由于是64位,会占用两个局部变量的空间。

每个块就是一个栈,如图是两个栈 在Java虚拟机规范中,对这个区域规定了两种异常情况:若是线程请求的栈深度大于虚拟机所容许的深度(好比递归调用的y时候),将抛出StackOverflowError异常;若是虚拟机栈能够动态扩展(当前大部分的Java虚拟机均可动态扩展,只不过Java虚拟机规范中也容许固定长度的虚拟机栈),当扩展时没法申请到足够的内存时会抛出OutOfMemoryError异常。

操做数栈:主要保存计算过程的中间结果,同时做为计算过程当中的变量临时的存储空间。  下图是一个两数相加的操做数栈的过程:

帧数据区:除了局部变量表和操做数据栈之外,栈还须要一些数据来支持常量池的解析,这里帧数据区保存着访问常量池的指针,方便计程序访问常量池,另外当函数返回或出现异常时卖虚拟机子必须有一个异常处理表,方便发送异常的时候找到异常的代码,所以异常处理表也是帧数据区的一部分。

栈上分配         小对象(通常几十个bytes),在没有逃逸的状况下,能够直接分配在栈上         直接分配在栈上,能够自动回收,减轻GC压力         大对象或者逃逸对象没法栈上分配

· 本地方法栈(Native Method Stack) 本地方法栈也是线程私有的内存区域,与java栈比较类似,不一样之处在于该区域主要是保存Native方法相关的数据。Native方法是非Java语言编写的方法。 与虚拟机栈同样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

专一于Java架构师技术分享,撩我免费送Java全套架构师晋级资料 (Java架构师交流企Q鹅裙*/:445-820-*908 )

相关文章
相关标签/搜索