jvm简述

一次编译到处运行是如何实现的

Java程序从编写到运行需要:首先编写Java源代码,然后通过Javac编译器将Java源代码编译成.class字节码文件,然后把字节码文件交由jvm虚拟机,虚拟机会在执行Java程序的时候把字节码转换为二进制的机器码执行。

字节码文件是平台无关性的重要一环,Java能在不同平台上运行,是依托了不同平台上不同的Java虚拟机。不同的虚拟机会根据同一份字节码文件转换成个平台对应的机器码运行。虚拟机也支持其他语言的符合规范的字节码文件转换成机器码运行。

什么是JVM java virtual machine

java虚拟机有自己的硬件架构:处理器、堆栈、寄存器等,还有相应的指令系统。屏蔽了具体的操作系统,使得Java程序只在虚拟机上生成相应的字节码并运行,实现了Java语言的跨平台性。

JVM是Java程序运行的环境,同时是一个操作系统的一个应用程序进程,因此它有自己的生命周期,也有自己的代码和数据空间。

jvm主要两个jvm内部体系结构分三个子系统以及两大组件:类装载器(class loader)子系统、执行引擎子系统、GC子系统,组件是内存区域和本地接口。

从进程角度解释jvm

虚拟机是运行在操作系统中的,而运行在操作系统中的基本单元是进程。所以当虚拟机运行时,他就是操作系统中的进程实例。没有运行时就是程序。

普通的命令行,当你敲下命令回车后就会创建一个进程,该进程会加载对应的可执行文件到进程的地址空间中,并执行指令。

而java命令,首先启动jvm进程,读取Java类文件(包括jdk的基础类),把他作为初始类加载到内存,对这个类进行初始化和动态链接,生成相应的字节码指令,然后从这个类的main方法开始执行。所以说我们的.class文件是托管到jvm进程上的。

虚拟机的三个重要功能系统

类加载器子系统:

这个系统根据需要在运行时加载类,而不是一开始就把所有类都加载进来。

执行引擎子系统:

由虚拟机加载的类,被加载到Java虚拟机内存中之后,虚拟机会读取并执行它里面存在的字节码指令。虚拟机中执行字节码指令的部分叫做执行引擎。

垃圾收集子系统:

Java虚拟机会进行自动内存管理。具体说来就是自动释放没有用的对象,而不需要程序员编写代码来释放分配的内存。这部分工作由垃圾收集子系统负责。 

虚拟机的内存结构

虚拟机的运行,需要加载class类文件,执行class类文件内的字节码指令,需要自己的空间。

加载的字节码,需要单独空间存放。

线程的执行,也需要内存空间维护方法调用关系。

存放方法中的数据以及中间结果。

创建的对象需要单独内存空间存放。

1、程序计数器(线程私有)

每个线程拥有一个程序计数器,在线程创建时创建,

指向下一条指令的地址

执行本地方法时,其值为undefined

通俗点讲,Java支持多线程,执行A线程时,跑去执行B线程,然后又跑回来执行A,那么怎么知道A执行到哪呢。为了线程切换后能够恢复到正确的执行位置,每条线程都有一个独立的程序计数器,属于线程私有内存。

2、Java虚拟机栈:(线程私有)

每启动一个新线程时,虚拟机都会为其分配一个Java栈,线程内每个方法调用时都会创建一个栈帧,用于存储局部变量表,操作栈,动态链接,方法出口等信息。每个方法被调用直到执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。

压栈出栈过程

当方法运行过程中需要创建局部变量时,就将局部变量的值存入栈帧中的局部变量表中。

Java 虚拟机栈的栈顶的栈帧是当前正在执行的活动栈,也就是当前正在执行的方法,PC 寄存器也会指向这个地址。只有这个活动的栈帧的本地变量可以被操作数栈使用,当在这个栈帧中调用另一个方法,与之对应的栈帧又会被创建,新创建的栈帧压入栈顶,变为当前的活动栈帧。

方法结束后,当前栈帧被移出,栈帧的返回值变成新的活动栈帧中操作数栈的一个操作数。如果没有返回值,那么新的活动栈帧中操作数栈的操作数没有变化。

局部变量表:是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在Java程序被编译成Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需要分配的最大局部变量表的容量。

操作栈:虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。

动态链接:用到某个类再加载进内存

3、本地方法栈:

java虚拟机栈是为虚拟机执行java方法服务的,而本地方法栈则为虚拟机执使用到的Native方法服务

4、Java堆:即堆内存(线程共享)

(1)堆是java虚拟机所管理的内存区域中最大的一块,java堆是被所有线程共享的内存区域,在java虚拟机启动时创建,堆内存的唯一目的就是存放对象实例几乎所有的对象实例都在堆内存分配。

(2)堆是GC管理的主要区域,从垃圾回收的角度看,由于现在的垃圾收集器都是采用的分代收集算法,因此java堆还可以初步细分为新生代和老年代

(3)Java虚拟机规定,堆可以处于物理上不连续的内存空间中,只要逻辑上连续的即可。在实现上既可以是固定的,也可以是可动态扩展的。如果在堆内存没有完成实例分配,并且堆大小也无法扩展,就会抛出OutOfMemoryError异常。

在 JDK 1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域(永久代使用的是JVM的堆内存空间,而元空间使用的是物理内存,直接受到本机的物理内存限制)。

5、方法区:(线程共享)

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

(2)Sun HotSpot虚拟机把方法区叫做永久代(Permanent Generation),方法区中最重要的部分是运行时常量池。

6、运行时常量池:

(1)运行时常量池是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池信息(用于存放编译期生成的各种字面量和符号引用)

(2)运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时就会抛出OutOfMemoryError异常。 

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页