摘自:https://www.cnblogs.com/qizhelongdeyang/p/12125146.html
深入JVM(二)JVM概述
一.JVM的原理
Java虚拟机是Java平台的基石,解决了硬件和操作系统的相互独立性。不同平台(Windows,Linux和MacOS)的JVM都是不同的,但是他们都提供了相同的接口。虚拟机可以分为系统虚拟机和程序虚拟机。系统虚拟机就是VMware和VirtualBox这一类的,完全是对物理资源的隔离。而Java虚拟机是程序虚拟机,它包含了一组指令集并在运行时操作各个不同内存区域,这些指令在JVM中称为Java字节码指令。
二.JVM的结构
JVM的基本结构如下图所示:
图中的Java文件泛指所有构建在Java虚拟机上的编程语言文件,如Groovy, Scala, Kotlin等。JVM不和上述任何语言关联,而是使用javac把这些语言编译为“Class文件”的这种二进制格式。Class文件中包含了JVM指令集和符号表已经其他一些信息。
2.1 类加载子系统
负责从class字节码文件中并存放在方法区的内存中,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
2.2 执行引擎
负责执行虚拟机的字节码,JVM制定了自己的指令集和体系结构,输入字节码文件并输出执行结果。
2.3 程序计数器
是一块较小的内存空间,可以看做是当前线程所执行的字节码行号指示器,每个线程都有一个独立的程序计数器。在虚拟机概念模型中,字节码解释器工作时就是通过改变计数器的值来选取下一条待执行的指令。当发生CPU时间片切换的时候,由程序计数器来确保当线程重新获取到CPU时间片后能够恢复到正确的执行位置。
如果当前方法是Java方法,程序计数器的值是正在执行的虚拟机字节码指令地址;如果是Native方法,则为空
![](/qrcode.jpg)
2.4 虚拟机栈
是线程私有的,并与线程的生命周期相同。虚拟机栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。
其中的局部变量表存放了各种基本数据类型,对象引用地址和returnAddress。所以局部变量表所需要的内存空间在编译期就可以完成分配。当进入到一个方法的时候,该方法所需要在栈帧中的大小是确定的,并且在运行期间不会改变
2.5 本地方法栈
本地方法栈的作用类似于虚拟机栈,只不过虚拟机栈是为执行Java方法服务,而本地方法栈则为虚拟机使用到的native方法服务
2.6 堆
堆在虚拟机启动的时候创建,是被所有线程共享的一块内存区域。几乎所有的对象都放在堆上,堆也就成为了垃圾回收的主要区域。在JDK1.8之前,堆可以分为新生代和老年代,其中新生代又可以细分为Eden,From和To三块区域。
从JDK1.8开始,永久代从堆内存中被转移到本地内存中
2.7 方法区
各个线程共享的内存区域,用于存储已经被加载的类信息、常量、静态变量、及时编译器编译后的代码等。在HotSpot虚拟机上方法区就对应上图中的永久代。该区域不需要连续的内存区域,GC回收的主要目标是针对常量池和类型的卸载。
微信公众号: Randy的技术笔记
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
一.JVM的原理
Java虚拟机是Java平台的基石,解决了硬件和操作系统的相互独立性。不同平台(Windows,Linux和MacOS)的JVM都是不同的,但是他们都提供了相同的接口。虚拟机可以分为系统虚拟机和程序虚拟机。系统虚拟机就是VMware和VirtualBox这一类的,完全是对物理资源的隔离。而Java虚拟机是程序虚拟机,它包含了一组指令集并在运行时操作各个不同内存区域,这些指令在JVM中称为Java字节码指令。
二.JVM的结构
JVM的基本结构如下图所示:
图中的Java文件泛指所有构建在Java虚拟机上的编程语言文件,如Groovy, Scala, Kotlin等。JVM不和上述任何语言关联,而是使用javac把这些语言编译为“Class文件”的这种二进制格式。Class文件中包含了JVM指令集和符号表已经其他一些信息。
2.1 类加载子系统
负责从class字节码文件中并存放在方法区的内存中,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
2.2 执行引擎
负责执行虚拟机的字节码,JVM制定了自己的指令集和体系结构,输入字节码文件并输出执行结果。
2.3 程序计数器
是一块较小的内存空间,可以看做是当前线程所执行的字节码行号指示器,每个线程都有一个独立的程序计数器。在虚拟机概念模型中,字节码解释器工作时就是通过改变计数器的值来选取下一条待执行的指令。当发生CPU时间片切换的时候,由程序计数器来确保当线程重新获取到CPU时间片后能够恢复到正确的执行位置。
如果当前方法是Java方法,程序计数器的值是正在执行的虚拟机字节码指令地址;如果是Native方法,则为空
2.4 虚拟机栈
是线程私有的,并与线程的生命周期相同。虚拟机栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。
其中的局部变量表存放了各种基本数据类型,对象引用地址和returnAddress。所以局部变量表所需要的内存空间在编译期就可以完成分配。当进入到一个方法的时候,该方法所需要在栈帧中的大小是确定的,并且在运行期间不会改变
2.5 本地方法栈
本地方法栈的作用类似于虚拟机栈,只不过虚拟机栈是为执行Java方法服务,而本地方法栈则为虚拟机使用到的native方法服务
2.6 堆
堆在虚拟机启动的时候创建,是被所有线程共享的一块内存区域。几乎所有的对象都放在堆上,堆也就成为了垃圾回收的主要区域。在JDK1.8之前,堆可以分为新生代和老年代,其中新生代又可以细分为Eden,From和To三块区域。
从JDK1.8开始,永久代从堆内存中被转移到本地内存中
2.7 方法区
各个线程共享的内存区域,用于存储已经被加载的类信息、常量、静态变量、及时编译器编译后的代码等。在HotSpot虚拟机上方法区就对应上图中的永久代。该区域不需要连续的内存区域,GC回收的主要目标是针对常量池和类型的卸载。