Java虚拟机基础结构与字节码执行引擎

谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65251.html

JVM 基础结构

JVM 内部结构如下:栈、堆。

JVM基础结构与字节码执行引擎

JVM 中的栈主要是指线程里面的栈,里面有方法栈、 native 方法栈、 PC 寄存器等等;每个方法栈是由栈帧组成的;每个栈帧是由局部变量表、操作数栈等组成。

每个栈帧其实就代表一个方法

java 中所有对象都在堆中分配;堆中对象又分为年轻代、老年代等等,不同代的对象使用不同垃圾回收算法。

-XMs :启动虚拟机预留的内存

-Xmx :最大的堆内存

一、堆的分代假设

根据研究表明,堆中对象大部分都是创建后,立马就可以被销毁的。如:

JVM基础结构与字节码执行引擎

为了优化堆中的内存,将堆中对象分为不同代。在年轻代中, GC 发生比较频繁;在老年代中, GC 发生比较少。

二、堆的分代

Young Generation  
Old Generation/Tenured  
Permanent Generation  

永久代在 Java 虚拟机规范中是没有的,但是 Host Spot 虚拟机中有。

JVM基础结构与字节码执行引擎

三、方法区

方法区被所有线程共享;方法区是用来存储编译后的代码,即存储每个类的运行时常量池、字段和方法。

方法区在虚拟机启动时创建;虽然方法区在逻辑上是堆的一部分,但在一些简单的实现中,方法区可以选择不进行垃圾回收和紧凑化。

方法区在 java8 的变化

  • java7 之前:方法区的实现:永久代,是作为堆的一部分;
  • java8 之后:方法区的实现: metaspace ,是堆外的内存;

1、为什么要这样改变?

因为 java 可以动态加载字节码信息,这样方法区就会慢慢的挤占堆中内存。为了避免与堆争抢内存, java8 将方法区的实现移至堆外。

2、方法区、永久代、 MetaSpace 的区别?

方法区是 java 虚拟机规范所规定的一个概念。其中 java7 实现方法区的地方称为永久代; java8 实现方法区的地方称为 MetaSpace

字节码文件的结构

JVM基础结构与字节码执行引擎

但是,编译后的字节码是如何读取到 JVM 中的?字节码执行引擎是如何识别、执行指令?

JVM基础结构与字节码执行引擎

1、如何查看字节码文件

  • classpy 工具
  • IDEA 的 jclasslib Bytecode viewer 插件

2、字节码文件结构

一个字节码文件包含以下部分:

JVM基础结构与字节码执行引擎

(1)magic: 0xCAFEBABE

class 文件的 magic code ,用于标识该文件是 class 文件。

(2) minor_version 、 major_version用于标识该 class 文件的版本,防止高版本的 class 文件被低版本的 JVM 读取并执行。

(3) constant_pool :常量池

用于存储该 class 文件经常被使用的信息,优化内存。比如说 System.out.print()

(4) access_flag表示这个类得访问权限,对应到 java 源码就是 public 、 final 之类的

字节码执行引擎

这里以一个线程为例。一般来说,一个方法栈最底层的栈帧都是 Thread.run 方法。当一个线程准备调用另一个方法时,会先将实参拷贝一份到新栈帧的局部变量表里,然后再执行代码。

1、局部变量表

每次调用新方法时,会默认将当前对象的地址 this 作为局部变量表的第一个参数;后面存放传过来的参数。这与 javascript 的做法很相似。

2、方法调用的相关指令

  • invokevirtual :一般实例方法,有多态;
  • invokeinterface :接口方法,有多态
  • invokestatuc :静态方法,无多态
  • invokespecial :特殊方法,无多态
  • invokedynamic :动态调用, JDK7 新增,方法无需在编译时确定

3、方法调用的过程

(1)在开始时

this

(2)在返回时

  • 将返回值放在调用者方法栈帧中的操作数栈上;

(3)在异常出现时

  • 寻找匹配的异常处理代码

(4)在 finally 时

  • 为每个分支新增一个跳转

4、为什么 Mockito 、 EasyMock 无法对 private 、 static 方法进行 mock ?

因为他们 mock 方法是通过覆盖这些方法来实现的,而 private 、 static 没法被覆盖。 PowerMock 是通过修改字节码文件达到 mock 私有、静态方法的。谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65251.html

JVM 基础结构

JVM 内部结构如下:栈、堆。

JVM基础结构与字节码执行引擎

JVM 中的栈主要是指线程里面的栈,里面有方法栈、 native 方法栈、 PC 寄存器等等;每个方法栈是由栈帧组成的;每个栈帧是由局部变量表、操作数栈等组成。

每个栈帧其实就代表一个方法

java 中所有对象都在堆中分配;堆中对象又分为年轻代、老年代等等,不同代的对象使用不同垃圾回收算法。

-XMs :启动虚拟机预留的内存

-Xmx :最大的堆内存

一、堆的分代假设

根据研究表明,堆中对象大部分都是创建后,立马就可以被销毁的。如:

JVM基础结构与字节码执行引擎

为了优化堆中的内存,将堆中对象分为不同代。在年轻代中, GC 发生比较频繁;在老年代中, GC 发生比较少。

二、堆的分代

Young Generation  
Old Generation/Tenured  
Permanent Generation  

永久代在 Java 虚拟机规范中是没有的,但是 Host Spot 虚拟机中有。

JVM基础结构与字节码执行引擎

三、方法区

方法区被所有线程共享;方法区是用来存储编译后的代码,即存储每个类的运行时常量池、字段和方法。

方法区在虚拟机启动时创建;虽然方法区在逻辑上是堆的一部分,但在一些简单的实现中,方法区可以选择不进行垃圾回收和紧凑化。

方法区在 java8 的变化

  • java7 之前:方法区的实现:永久代,是作为堆的一部分;
  • java8 之后:方法区的实现: metaspace ,是堆外的内存;

1、为什么要这样改变?

因为 java 可以动态加载字节码信息,这样方法区就会慢慢的挤占堆中内存。为了避免与堆争抢内存, java8 将方法区的实现移至堆外。

2、方法区、永久代、 MetaSpace 的区别?

方法区是 java 虚拟机规范所规定的一个概念。其中 java7 实现方法区的地方称为永久代; java8 实现方法区的地方称为 MetaSpace

字节码文件的结构

JVM基础结构与字节码执行引擎

但是,编译后的字节码是如何读取到 JVM 中的?字节码执行引擎是如何识别、执行指令?

JVM基础结构与字节码执行引擎

1、如何查看字节码文件

  • classpy 工具
  • IDEA 的 jclasslib Bytecode viewer 插件

2、字节码文件结构

一个字节码文件包含以下部分:

JVM基础结构与字节码执行引擎

(1)magic: 0xCAFEBABE

class 文件的 magic code ,用于标识该文件是 class 文件。

(2) minor_version 、 major_version用于标识该 class 文件的版本,防止高版本的 class 文件被低版本的 JVM 读取并执行。

(3) constant_pool :常量池

用于存储该 class 文件经常被使用的信息,优化内存。比如说 System.out.print()

(4) access_flag表示这个类得访问权限,对应到 java 源码就是 public 、 final 之类的

字节码执行引擎

这里以一个线程为例。一般来说,一个方法栈最底层的栈帧都是 Thread.run 方法。当一个线程准备调用另一个方法时,会先将实参拷贝一份到新栈帧的局部变量表里,然后再执行代码。

1、局部变量表

每次调用新方法时,会默认将当前对象的地址 this 作为局部变量表的第一个参数;后面存放传过来的参数。这与 javascript 的做法很相似。

2、方法调用的相关指令

  • invokevirtual :一般实例方法,有多态;
  • invokeinterface :接口方法,有多态
  • invokestatuc :静态方法,无多态
  • invokespecial :特殊方法,无多态
  • invokedynamic :动态调用, JDK7 新增,方法无需在编译时确定

3、方法调用的过程

(1)在开始时

this

(2)在返回时

  • 将返回值放在调用者方法栈帧中的操作数栈上;

(3)在异常出现时

  • 寻找匹配的异常处理代码

(4)在 finally 时

  • 为每个分支新增一个跳转

4、为什么 Mockito 、 EasyMock 无法对 private 、 static 方法进行 mock ?

因为他们 mock 方法是通过覆盖这些方法来实现的,而 private 、 static 没法被覆盖。 PowerMock 是通过修改字节码文件达到 mock 私有、静态方法的。谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65251.html

JVM 基础结构

JVM 内部结构如下:栈、堆。

JVM基础结构与字节码执行引擎

JVM 中的栈主要是指线程里面的栈,里面有方法栈、 native 方法栈、 PC 寄存器等等;每个方法栈是由栈帧组成的;每个栈帧是由局部变量表、操作数栈等组成。

每个栈帧其实就代表一个方法

java 中所有对象都在堆中分配;堆中对象又分为年轻代、老年代等等,不同代的对象使用不同垃圾回收算法。

-XMs :启动虚拟机预留的内存

-Xmx :最大的堆内存

一、堆的分代假设

根据研究表明,堆中对象大部分都是创建后,立马就可以被销毁的。如:

JVM基础结构与字节码执行引擎

为了优化堆中的内存,将堆中对象分为不同代。在年轻代中, GC 发生比较频繁;在老年代中, GC 发生比较少。

二、堆的分代

Young Generation  
Old Generation/Tenured  
Permanent Generation  

永久代在 Java 虚拟机规范中是没有的,但是 Host Spot 虚拟机中有。

JVM基础结构与字节码执行引擎

三、方法区

方法区被所有线程共享;方法区是用来存储编译后的代码,即存储每个类的运行时常量池、字段和方法。

方法区在虚拟机启动时创建;虽然方法区在逻辑上是堆的一部分,但在一些简单的实现中,方法区可以选择不进行垃圾回收和紧凑化。

方法区在 java8 的变化

  • java7 之前:方法区的实现:永久代,是作为堆的一部分;
  • java8 之后:方法区的实现: metaspace ,是堆外的内存;

1、为什么要这样改变?

因为 java 可以动态加载字节码信息,这样方法区就会慢慢的挤占堆中内存。为了避免与堆争抢内存, java8 将方法区的实现移至堆外。

2、方法区、永久代、 MetaSpace 的区别?

方法区是 java 虚拟机规范所规定的一个概念。其中 java7 实现方法区的地方称为永久代; java8 实现方法区的地方称为 MetaSpace

字节码文件的结构

JVM基础结构与字节码执行引擎

但是,编译后的字节码是如何读取到 JVM 中的?字节码执行引擎是如何识别、执行指令?

JVM基础结构与字节码执行引擎

1、如何查看字节码文件

  • classpy 工具
  • IDEA 的 jclasslib Bytecode viewer 插件

2、字节码文件结构

一个字节码文件包含以下部分:

JVM基础结构与字节码执行引擎

(1)magic: 0xCAFEBABE

class 文件的 magic code ,用于标识该文件是 class 文件。

(2) minor_version 、 major_version用于标识该 class 文件的版本,防止高版本的 class 文件被低版本的 JVM 读取并执行。

(3) constant_pool :常量池

用于存储该 class 文件经常被使用的信息,优化内存。比如说 System.out.print()

(4) access_flag表示这个类得访问权限,对应到 java 源码就是 public 、 final 之类的

字节码执行引擎

这里以一个线程为例。一般来说,一个方法栈最底层的栈帧都是 Thread.run 方法。当一个线程准备调用另一个方法时,会先将实参拷贝一份到新栈帧的局部变量表里,然后再执行代码。

1、局部变量表

每次调用新方法时,会默认将当前对象的地址 this 作为局部变量表的第一个参数;后面存放传过来的参数。这与 javascript 的做法很相似。

2、方法调用的相关指令

  • invokevirtual :一般实例方法,有多态;
  • invokeinterface :接口方法,有多态
  • invokestatuc :静态方法,无多态
  • invokespecial :特殊方法,无多态
  • invokedynamic :动态调用, JDK7 新增,方法无需在编译时确定

3、方法调用的过程

(1)在开始时

this

(2)在返回时

  • 将返回值放在调用者方法栈帧中的操作数栈上;

(3)在异常出现时

  • 寻找匹配的异常处理代码

(4)在 finally 时

  • 为每个分支新增一个跳转

4、为什么 Mockito 、 EasyMock 无法对 private 、 static 方法进行 mock ?

因为他们 mock 方法是通过覆盖这些方法来实现的,而 private 、 static 没法被覆盖。 PowerMock 是通过修改字节码文件达到 mock 私有、静态方法的。谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65251.html

JVM 基础结构

JVM 内部结构如下:栈、堆。

JVM基础结构与字节码执行引擎

JVM 中的栈主要是指线程里面的栈,里面有方法栈、 native 方法栈、 PC 寄存器等等;每个方法栈是由栈帧组成的;每个栈帧是由局部变量表、操作数栈等组成。

每个栈帧其实就代表一个方法

java 中所有对象都在堆中分配;堆中对象又分为年轻代、老年代等等,不同代的对象使用不同垃圾回收算法。

-XMs :启动虚拟机预留的内存

-Xmx :最大的堆内存

一、堆的分代假设

根据研究表明,堆中对象大部分都是创建后,立马就可以被销毁的。如:

JVM基础结构与字节码执行引擎

为了优化堆中的内存,将堆中对象分为不同代。在年轻代中, GC 发生比较频繁;在老年代中, GC 发生比较少。

二、堆的分代

Young Generation  
Old Generation/Tenured  
Permanent Generation  

永久代在 Java 虚拟机规范中是没有的,但是 Host Spot 虚拟机中有。

JVM基础结构与字节码执行引擎

三、方法区

方法区被所有线程共享;方法区是用来存储编译后的代码,即存储每个类的运行时常量池、字段和方法。

方法区在虚拟机启动时创建;虽然方法区在逻辑上是堆的一部分,但在一些简单的实现中,方法区可以选择不进行垃圾回收和紧凑化。

方法区在 java8 的变化

  • java7 之前:方法区的实现:永久代,是作为堆的一部分;
  • java8 之后:方法区的实现: metaspace ,是堆外的内存;

1、为什么要这样改变?

因为 java 可以动态加载字节码信息,这样方法区就会慢慢的挤占堆中内存。为了避免与堆争抢内存, java8 将方法区的实现移至堆外。

2、方法区、永久代、 MetaSpace 的区别?

方法区是 java 虚拟机规范所规定的一个概念。其中 java7 实现方法区的地方称为永久代; java8 实现方法区的地方称为 MetaSpace

字节码文件的结构

JVM基础结构与字节码执行引擎

但是,编译后的字节码是如何读取到 JVM 中的?字节码执行引擎是如何识别、执行指令?

JVM基础结构与字节码执行引擎

1、如何查看字节码文件

  • classpy 工具
  • IDEA 的 jclasslib Bytecode viewer 插件

2、字节码文件结构

一个字节码文件包含以下部分:

JVM基础结构与字节码执行引擎

(1)magic: 0xCAFEBABE

class 文件的 magic code ,用于标识该文件是 class 文件。

(2) minor_version 、 major_version用于标识该 class 文件的版本,防止高版本的 class 文件被低版本的 JVM 读取并执行。

(3) constant_pool :常量池

用于存储该 class 文件经常被使用的信息,优化内存。比如说 System.out.print()

(4) access_flag表示这个类得访问权限,对应到 java 源码就是 public 、 final 之类的

字节码执行引擎

这里以一个线程为例。一般来说,一个方法栈最底层的栈帧都是 Thread.run 方法。当一个线程准备调用另一个方法时,会先将实参拷贝一份到新栈帧的局部变量表里,然后再执行代码。

1、局部变量表

每次调用新方法时,会默认将当前对象的地址 this 作为局部变量表的第一个参数;后面存放传过来的参数。这与 javascript 的做法很相似。

2、方法调用的相关指令

  • invokevirtual :一般实例方法,有多态;
  • invokeinterface :接口方法,有多态
  • invokestatuc :静态方法,无多态
  • invokespecial :特殊方法,无多态
  • invokedynamic :动态调用, JDK7 新增,方法无需在编译时确定

3、方法调用的过程

(1)在开始时

this

(2)在返回时

  • 将返回值放在调用者方法栈帧中的操作数栈上;

(3)在异常出现时

  • 寻找匹配的异常处理代码

(4)在 finally 时

  • 为每个分支新增一个跳转

4、为什么 Mockito 、 EasyMock 无法对 private 、 static 方法进行 mock ?

因为他们 mock 方法是通过覆盖这些方法来实现的,而 private 、 static 没法被覆盖。 PowerMock 是通过修改字节码文件达到 mock 私有、静态方法的。谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65251.html

JVM 基础结构

JVM 内部结构如下:栈、堆。

JVM基础结构与字节码执行引擎

JVM 中的栈主要是指线程里面的栈,里面有方法栈、 native 方法栈、 PC 寄存器等等;每个方法栈是由栈帧组成的;每个栈帧是由局部变量表、操作数栈等组成。

每个栈帧其实就代表一个方法

java 中所有对象都在堆中分配;堆中对象又分为年轻代、老年代等等,不同代的对象使用不同垃圾回收算法。

-XMs :启动虚拟机预留的内存

-Xmx :最大的堆内存

一、堆的分代假设

根据研究表明,堆中对象大部分都是创建后,立马就可以被销毁的。如:

JVM基础结构与字节码执行引擎

为了优化堆中的内存,将堆中对象分为不同代。在年轻代中, GC 发生比较频繁;在老年代中, GC 发生比较少。

二、堆的分代

Young Generation  
Old Generation/Tenured  
Permanent Generation  

永久代在 Java 虚拟机规范中是没有的,但是 Host Spot 虚拟机中有。

JVM基础结构与字节码执行引擎

三、方法区

方法区被所有线程共享;方法区是用来存储编译后的代码,即存储每个类的运行时常量池、字段和方法。

方法区在虚拟机启动时创建;虽然方法区在逻辑上是堆的一部分,但在一些简单的实现中,方法区可以选择不进行垃圾回收和紧凑化。

方法区在 java8 的变化

  • java7 之前:方法区的实现:永久代,是作为堆的一部分;
  • java8 之后:方法区的实现: metaspace ,是堆外的内存;

1、为什么要这样改变?

因为 java 可以动态加载字节码信息,这样方法区就会慢慢的挤占堆中内存。为了避免与堆争抢内存, java8 将方法区的实现移至堆外。

2、方法区、永久代、 MetaSpace 的区别?

方法区是 java 虚拟机规范所规定的一个概念。其中 java7 实现方法区的地方称为永久代; java8 实现方法区的地方称为 MetaSpace

字节码文件的结构

JVM基础结构与字节码执行引擎

但是,编译后的字节码是如何读取到 JVM 中的?字节码执行引擎是如何识别、执行指令?

JVM基础结构与字节码执行引擎

1、如何查看字节码文件

  • classpy 工具
  • IDEA 的 jclasslib Bytecode viewer 插件

2、字节码文件结构

一个字节码文件包含以下部分:

JVM基础结构与字节码执行引擎

(1)magic: 0xCAFEBABE

class 文件的 magic code ,用于标识该文件是 class 文件。

(2) minor_version 、 major_version用于标识该 class 文件的版本,防止高版本的 class 文件被低版本的 JVM 读取并执行。

(3) constant_pool :常量池

用于存储该 class 文件经常被使用的信息,优化内存。比如说 System.out.print()

(4) access_flag表示这个类得访问权限,对应到 java 源码就是 public 、 final 之类的

字节码执行引擎

这里以一个线程为例。一般来说,一个方法栈最底层的栈帧都是 Thread.run 方法。当一个线程准备调用另一个方法时,会先将实参拷贝一份到新栈帧的局部变量表里,然后再执行代码。

1、局部变量表

每次调用新方法时,会默认将当前对象的地址 this 作为局部变量表的第一个参数;后面存放传过来的参数。这与 javascript 的做法很相似。

2、方法调用的相关指令

  • invokevirtual :一般实例方法,有多态;
  • invokeinterface :接口方法,有多态
  • invokestatuc :静态方法,无多态
  • invokespecial :特殊方法,无多态
  • invokedynamic :动态调用, JDK7 新增,方法无需在编译时确定

3、方法调用的过程

(1)在开始时

this

(2)在返回时

  • 将返回值放在调用者方法栈帧中的操作数栈上;

(3)在异常出现时

  • 寻找匹配的异常处理代码

(4)在 finally 时

  • 为每个分支新增一个跳转

4、为什么 Mockito 、 EasyMock 无法对 private 、 static 方法进行 mock ?

因为他们 mock 方法是通过覆盖这些方法来实现的,而 private 、 static 没法被覆盖。 PowerMock 是通过修改字节码文件达到 mock 私有、静态方法的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值