文章目录
1、什么是JVM
(1)JVM即Java Virtual Machine,java虚拟机。它是一个虚构出来的机器,是通过实际计算机上的仿真模拟各种功能实现的。
(2)JVM包含了一套字节码指令集,一组寄存器、一个占、一个垃圾回收堆和一个存储方法域。
(3)JVM支持java程序跨平台。因为它屏蔽了与具体操作系统平台相关信息,使我们的Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令来执行。
2、jdk、jre、jvm关系
(1)JRE(Java Runtime Environment),也就是java平台。所有的java程序都要在JRE环境下才能运行。
(2)JDK(Java Development Kit),是开发者用来编译、调试程序用的开发包。JDK也是JAVA程序需要在JRE上运行。
(3)JVM(Java Virtual Machine),是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。
Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。
3、JVM执行过程
(1)jvm是java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
(2)java编译器只要面向jvm,生成jvm能理解的字节码文件。java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码,通过特定平台运行。

4、JVM执行程序的过程

第一步:程序员写出各种java文件 通过编译器编译成class字节码文件
第二步:然后我们通过tomcat 或者java -jar的形式在linux或windows上运行
第三步:前提安装了jdk 我们的jar或war程序就整体是一个jvm,在运行时会首先去让最顶层的父层 启动类加载器(BootStrap ClassLoader)去java的lib包下加载核心类库。然后通过 Extension ClassLoader 扩展类加载器 在lib/ext下加载扩展类 ,再然后通过Application ClassLoader应用程序类加载器 加载我们自己的java程序中的class字节码文件 。。。。。其中加载过程中会有双亲委派机制,就是当前应用程序类加载器向上层父级扩展类中找寻是否该类应由其执行,扩展类加载器在向上。到达启动类加载器去核心类库中找寻是否是自己的类。如果是则有自己进行类加载进jvm内存方法区中。如果没有则再向下进行委派。直到找到是属于各级加载器自己的类。如果每一层都没有。那么由发起方自己去执行该类(类加载进方法区)
第四部:如果我们是通过tomcat加载的话。tomcat会将应用程序解析,验证,通过自定义类加载加载如tomcat自己的jvm方法区。
第五步:放入方法区的class类会被字节码引擎执行字节码指令进行各种操作(读写),过程中会有程序计数器来记录指令执行的位置。
第六步:执行过程从各个方法也就是线程执行起始,该对象在建立的时候会被放入堆内存中。
第七步:初始化的对象 都会有自己的成员变量,赋完默认值,会将成员变量进行压栈,进入java虚拟机栈中成为栈帧。并且每一个成员变量都在栈内存中指向堆内存的对象。堆栈相互关联。
第八步:垃圾回收时刻监测堆内存中是否有未被栈内存中成员变量指向的对象。如果有,则进行垃圾回收。
第九步:而在方法去的类和栈中的栈帧什么时候被回收呢?首先该类所有的实例化对象都在堆内存中被回收。其次加载该类的类加载器已经被回收,最后对该类的class文件没有任何堆内存的线程或线程中变量引用。这三种情况全部满足,栈和方法区的线程和类都全部被回收了。
5、JVM运行时数据区

从图来看,我们可以把Java内存区分为堆内存(Heap)和栈内存(Stack)。虽然这种分法比较粗糙,实际上要复杂的多,不过初学者来说这是我们最关注的的两块区域。
总内存=堆内存(Xmx)+方法区内存(MaxPermSize)+栈内存(Xss)*线程数+直接内存(MaxDirectMemorySize,堆外)+虚拟机内存
虚拟机栈(线程私有)
(1)Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)
(2)指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)
(3)方法返回地址(Return Address)和一些额外的附加信息。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。

这块区域存在两种异常情况:
(1)如果线程请求的栈深度大于虚拟机允许的深度,抛出StackOverflowError异常;
(2)如果虚拟机栈可以动态扩展,且扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
在这里也说一个题外话,由于每个方法从进入到返回对应着栈帧的压入和弹出,这个过程需要耗费一定的时间和资源,所以也意味着代码中调用的方法越多,执行效率也会越低。所以拆分方法的也不是越多越好的。
本地方法栈(线程私有)
本地方法栈和Java虚拟机栈的功能很相似,Java虚拟机栈用于管理Java函数的调用,而本地方法栈用于管理Native方法的调用。本地方法并不是用Java实现的,而是使用C实现的。在HotSpot虚拟机中,不区分本地方法栈和虚拟机栈,因此和虚拟机栈一样,它也会抛出Stac

本文详细介绍JVM的基础概念、执行过程及内存管理等内容。涵盖JVM的组成部分、内存分配与垃圾回收机制,帮助读者掌握JVM调优技巧。
最低0.47元/天 解锁文章
1万+





