哈喽,又是好久不见呀,今天主要要给大家分享的是JVM的内存区域划分,这个就是纯纯的八股文了呦,但是我依旧还是会尽我最大的努力给友友讲清楚的,快来看看吧.
目录
1.JVM快速扫盲
2.JDK、JRE、JVM的关系
3.JVM内存区域划分
3.1 堆
3.2 java虚拟机栈
3.3 本地方法栈
3.4 程序计数器
3.5 方法区
1.JVM快速扫盲
JVM全称Java Virtual Machine,也称java虚拟机。那什么是虚拟机呢,相信大家应该多多少少都有听说过。就是通过软件来模拟的一个具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。简单粗暴的可以理解为可以在上面进行一些操作的一个计算机,但是这个计算机是虚拟的、不存在。知道了虚拟机,那java虚拟机又是什么呢?
java虚拟机是一种程序虚拟机,java虚拟机是可运行的java程序的假想计算机。java虚拟机有自己假想的硬件,如处理器,寄存器,堆,栈等,还有相应的指令系统。
学过java的应该都知道,java语言有个特性就是具有可移植性.这就与java虚拟机有着直接的关系。一般高级语言在不同的平台上运行时需要编译成不同的目标代码。但是当引入Java虚拟机之后,java语言只需编译生成能在java虚拟机上运行的目标代码(字节码),在各种不同的平台下,引入java虚拟机,java代码就可以不加任何修改编译运行起来。
java虚拟机规范定义了一个抽象的,虚拟的机器。这个规范描述了一个指令集,一组寄存器,一个堆,一个栈,一个垃圾堆和一个方法区。一旦一个java虚拟机在给定的平台上运行,则任何一个java程序的字节码文件都可以在通过java虚拟机在此平台上运行起来。
目前我们知道,运行一个java程序时,需要先通过一个叫javac的编译器,将代码编译成class文件,最终加载到JVM中,将其解释成各个平台都能识别的机器码,最终实现跨平台。
2.JDK、JRE、JVM的关系
JDK(Java Development Kit):即java开发工具包,用于java程序的开发,针对于开发者。是整个java的核心,包含了java运行环境jre、Java基础的类库、jvm实现标准、java核心类库等。
java基础类库就是Java API,包括rt.java.Java API就是Java应用程序接口,比如基本的语言结构,I/O,网络等,开发者可以直接调用.
JRE(Java Runtime Environment):即java运行环境,不能编译(java源文件的编译在jdk中),只能运行.class文件,针对于用户.
JRE包含了一个JVM(java虚拟机),java核心类库和其支持的一些文件.于jdk不同,jre不包含开发工具--编译器,调试器和其他工具.
一个java程序的运行必少不了jre,编译后的java程序必须要在jre上才能运行.如果想要运行一个已经编译好的java程序,只需要在计算机中安装jre即可.
JVM(Java Virtual Machine):将字节码(拓展名为.class)文件解释成各系统能识别的机器指令.
以下是三者之间的包含关系:
JVM是java程序能实现跨平台的最核心部分.java程序编译成字节码文件(.class)之后,字节码文件不直接与操作系统打交道,而是在JVM上执行,JVM会将该文件解释成系统能识别的机器指令.JVM再与操作系统进行交互(JVM是运行在操作系统上面的).
"java一次编译到处运行":通过JVM屏蔽底层系统(Windows,Linux,Mac等)的差异来实现的.java程序被编译之后,形成字节码文件,该文件运行在jvm上,jvm运行在操作系统上,jvm内部做了不同操作系统的适配,所以不同的操作系统不会影响java程序输出结果的一致性.
3.JVM内存区域划分
JVM本质上就是一个java进程。当JVM运行时,就会从操作系统那边申请一大块内存,这一大块内存被分为五部分,分别有着自己的作用。这五大部分如下图:
3.1 堆
堆存放的就是new的对象(包括对象里面的成员方法),同时也是这五部分中占地面积最大的区域。堆是被所用线程共用的一块内存,在虚拟机启动时创建,此内存就是用来存放java对象实例的,几乎所有的java对象实例都存放在对堆上。
3.2 java虚拟机栈
java虚拟机栈中存放在的是方法之间的调用关系和局部变量。java虚拟机栈是线程私有的,生命周期与线程相同。每个方法在执行时,就会java虚拟机栈中为其分配一块栈帧,栈帧中存放的就是每个方法的局部变量表,操作栈,动态链接,方法返回出口等信息。每一个方法从执行到结束就是一个对应着一个栈帧在java虚拟机中入栈和出栈的过程。
局部变量表:用来存储局部变量(包括方法中的非静态变量和方法形参)。对于基本数据类型,直接存值;对于引用数据类型,存其对象的引用。
动态链接:每一个栈帧内部都包含一个运行时常量池中该栈帧所属方法的引用。包含这个引用就是为了支持当前方法能够实现动态链接。有些方法的调用,编译期无法确定,只能在程序运行期间将调用方法的符号引用转为直接引用。
方法返回出口:当一个方法执行结束之后,要返回调用它的地方。这时就需要在栈帧中保存它的返回地址。
3.3 本地方法栈
与java虚拟机栈的管理机制大致相同,也是线程私有的。java虚拟机用来管理java方法的调用;本地方法栈用来管理本地方法(Native)的调用。当某个线程调用一个本地方法时,他就进入一个全新的并且不再受虚拟机的限制。在HotSpot的jvm中将本地方法栈和虚拟机栈合二为一。
本地方法:java程序需要和java环境外的环境交互时,就需要调用本地方法。比如:JVM不是一个完整的系统,它需要操作系统的支持,因此,需要与操作系统交互。通过本地方法,我们可以用Java实现JRE与底层系统的交互。
3.4 程序计数器
占地最小的区域,存储了当前线程下一个要执行的指令地址(即存的就是当前代码执行到哪个指令了).
因为java虚拟机的多线程是通过线程的轮流切换、分配处理机执行时间的方式来实现的,故每一个线程都需要有一个自己独立的程序计数器,负责记录当前线程执行到哪了,以便线程能恢复到原来正确的位置再次执行。
3.5 方法区
方法区里放的是类对象和静态变量。我们写的程序是.java文件,后需要被编译成.class文件,然后JVM就会将.class文件加载到内存中,构造成类对象。也就是说就我们写的这个java代码的信息反馈到类对象中了。
类对象中包含了类的名字是什么,继承谁,实现了哪些接口,有什么属性,属性名是什么,类型是什么,访问权限是什么,有什么方法,方法内部的指令是什么,方法名是什么,参数是什么,返回值是什么等等。
在《Java虚拟机规范》中,此区域称之为方法区,而在HotSpot虚拟机的实现中,在JDK7时,此区域称为“永久代”,在JDK8时,此区域称为“云空间”(Metaspace)。
好啦,这部分知识就到这啦,希望看完的友友能有所收获呀,多多看我的博客,我们一起进步呀