JVM概述

一、什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不一样平台上运行时不须要从新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。
Java虚拟机本质上就是一个程序,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。
Java语言的可移植性正是创建在Java虚拟机的基础上。任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就能够在该平台上运行。这就是“一次编译,屡次运行”。java

二、JDK、JRE和JVM关系

JDK = JRE + 开发工具(如编译器javac.exe)
JRE = JVM + 类库函数

Java程序的开发过程为:工具

    一、咱们利用 JDK (调用 Java API)编写出 Java 源代码,存储于 .java 文件中
    二、JDK 中的编译器 javac 将 Java 源代码编译成 Java 字节码,存储于 .class 文件中
    三、JRE 加载、验证、执行 Java 字节码
    四、JVM 将字节码解析为机器码并映射到 CPU 指令集或 OS 的系统调用。性能

三、JVM的组成结构

JVM包含两个子系统和两个组件开发工具

两个子系统:命令行

  • Class loader(类装载)
  • Execution engine(执行引擎)

两个组件:线程

  • Runtime data area(运行时数据区)
  • Native Interface(本地接口)

四、JVM运行时数据区

一、程序计数器(PC Register)对象

做用:记录的是正在执行的虚拟机字节码指令的地址;若是正在执行的是Native方法,这个计数器值则为空。blog

异常:此内存区域是惟一一个在Java虚拟机规范中没有规定任何OutOfMemoryError状况的区域。接口

二、虚拟机栈(JVM Stacks)

做用:是Java方法执行的内存模型,每一个方法在执行的同时都会建立一个栈帧用于存储数据。每个方法从调用直至执行完成,对应栈帧在虚拟机栈中入栈到出栈的过程。

异常:会抛出StackOverflowError和OutOfMemoryErrror异常。

栈帧(Stack Frame)包含如下几个部分

一、局部变量表:是存放方法参数和局部变量的区域

二、操做栈:是个初始状态为空的桶式结构栈。在方法执行过程当中,会有各类指令往栈中写入和提取信息。JVM的执行引擎式基于栈的执行引擎,其中的栈指的就是操做栈。i++和++i(字节码指令)

三、动态连接:每一个栈帧中包含一个在常量池中对当前方法的引用,目的是支持方法调用过程的动态链接

四、方法返回地址:方法执行有两种退出状况,正常退出和异常退出,二者都将返回至方法当前被调用的位置。方法退出的过程至关于弹出当前栈帧

三、本地方法栈(Native Method Stacks)

做用:与虚拟机栈所发挥的做用很是类似,为虚拟机使用到的Native方法服务。线程开始调用本地方法时,会进入再也不受JVM约束的世界。本地方法能够经过 JNI(Java Native Interface)来访问虚拟机运行时的数据区。

异常:会抛出StackOverFlowError和OutOfMemoryError异常。

四、方法区(Method Area)

做用:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

异常:当方法区没法知足内存分配需求时,将抛出OutOfMemoryError异常。

垃圾回收:垃圾收集行为在这个区域时比较少出现的,其内存回收目标主要是对常量池的回收和对类型的卸载。JDK8以前,Hotspot中方法区的实现是永久代,JDK8开始使用元空间(Meta Space),之前永久代全部内容的字符串常量移至元空间,元空间直接在本地内存分配。

运行时常量池

一、是方法区的一部分

二、存放编译期生成的各类字面量和符号引用

三、Class文件中除了存有类的版本、字段、方法、接口等描述信息,还有一项是常量池,存有这个类的编译期生成的各类字面量和符合引用,这部份内容将在类加载后,存放到方法区的运行时常量池中

为何废除1.7中永久代?

一、移除永久代是为融合Hotspot JVM与JR'ockit VM而作出的努力,由于JRockit没有永久代,不须要配置永久代

二、现实使用中,因为永久代内存常常不够用或发生内存泄露,爆出异常 java.lang.OutOfMemoryError: PermGen

三、基于此,将永久区废弃,而改用元空间,改成了使用本地内存空间

五、堆(Heap)

做用:Java虚拟机所管理的内存中最大的一块。Java堆是被线程共享的一块内存区域,在虚拟机启动时建立。此内存区域的惟一目的就是存放对象实例,几乎全部的对象实例都在这里分配内存。

异常:若是在堆中没有内存完成实例分配,而且堆也没法再扩展时,将会抛出OutOfMemoryError异常。

六、直接内存(Direct Memory)

直接内存(Direct Memory)并非虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。

在 JDK 1.4 中新加入了 NIO,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可使用 Native 函数库直接分配堆外内存,而后经过一个存储在 Java 堆中的 DirectByteBuffer 对象做为这块内存的引用进行操做。这样能在一些场景中显著提升性能,由于避免了在 Java 堆和 Native 堆中来回复制数据。

程序计数器、虚拟机栈、本地方法栈是线程私有的,方法区、堆是线程共享的