Java虚拟机-JVM的运行原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21983189/article/details/72901028

Java技术,主要包括Java编程语言、Java类文件格式、Java虚拟机(JVM)和Java应用程序接口(Java API)四部分。这里,我们特意来深刻认识一下JVM的工作和运行原理。

JVM的生命周期

产生:当启动一个Java程序时,一个JVM实例就产生了;
运行:main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程非守护线程main属于非守护线程, 守护线程通常由JVM自己使用,java程序也可以标明自己创建的线程是守护线程
销毁:当程序中的所有非守护线程都销毁时,jvm会自己退出。若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出。

JVM的内部体系结构
(1)类加载器(ClassLoader)子系统:用来装载.class文件,JVM将整个类加载过程划分为三个步骤:
a.装载
装载过程负责找到二进制字节码并加载至JVM中;
JVM通过类名、类所在的包名通过ClassLoader来完成类的加载;
同样,也采用以上三个元素来标识一个被加载了的类:类名+包名+ClassLoader实例ID。
b.链接
链接过程负责对二进制字节码的格式进行校验、 初始化装载类中的静态变量以及解析类中调用的接口、类。
在完成了校验后,JVM初始化类中的静态变量,并将其值赋为默认值。
最后一步为对类中的所有属性、方法进行验证, 以确保其需要调用的属性、方法存在,以及具备应的权限(例如public、private域权限等), 会造成NoSuchMethodError、NoSuchFieldError等错误信息。
c.初始化
初始化过程即为执行类中的静态初始化代码、构造器代码以及静态属性的初始化,在四种情况下初始化过程会被触发执行:
1).调用了new;
2).反射调用了类中的方法;
3).子类调用了初始化;
4).JVM启动过程中指定的初始化类。

(2)执行引擎:执行字节码,或者执行本地方法。
JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈出栈操作。
JVM执行class字节码,线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。栈的结构如下图所示:
这里写图片描述

(3)运行时数据区:JVM在运行时将数据划分为了6个区域来存储,而不仅仅是大家熟知的Heap区域,分别是PC寄存器,方法区(method),栈内存(stack),堆内存(heap),运行时常量池,本地方法栈(java中的jni调用)
这里写图片描述
第一块: PC寄存器
PC寄存器是用于存储每个线程下一步将执行的JVM指令,如该方法为native的,则PC寄存器中不存储任何信息
第二块:JVM栈
JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量,部分返回结果以及函数的参数值,非基本类型的对象的JVM栈上仅存放一个指向堆上的地址
第三块:堆(Heap)
Heap是大家最为熟悉的区域,它是JVM用来存储对象实例以及数组值的区域,可以认为java中所有通过New创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收
第四块:方法区域(Method Area)
(1)方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,可见方法区域的重要性,同样,方法区域也是全局共享的,在一定的条件下它也会被GC;当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
(2)在Sun JDK中这块区域对应的为Permanet Generation,又称为持久代,默认为64M,可通过-XX:PermSize以及-XX:MaxPermSize来指定其大小。
第五块:运行时常量池(Runtime Constant Pool)
类似C中的符号表,存放的为类中的固定的常量信息、方法和Field的引用信息等,其空间从方法区域中分配。
第六块:本地方法堆栈(Native Method Stacks)
JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态

JVM的垃圾回收机制
堆里聚集了所有由应用程序创建的对象,JVM也有对应的指令比如 new, newarray, anewarray和multianewarray,然并没有向 C++ 的 delete,free 等释放空间的指令,Java的所有释放都由 GC 来做,GC除了做回收内存之外,另外一个重要的工作就是内存的压缩,这个在其他的语言中也有类似的实现,相比 C++ 不仅好用,而且增加了安全性,当然它也有弊端,比如性能这个大问题。

猜你喜欢

转载自blog.csdn.net/qq_21983189/article/details/72901028
今日推荐