Java面试篇基础部分-JVM详细介绍(java面试必备 基础知识篇)

createh51个月前 (02-01)技术教程21

JVM的运行机制

JVM(Java Virtual Machine)是用于运行Java字节码的虚拟计算机,其中包括一套字节码的指令集、程序寄存器、虚拟机栈、虚拟机堆、本地方法区、垃圾回收器。JVM运行在操作系统上层,它不跟底层硬件直接进行交互。如下图所示


Java源代码通过了编译器编译成响应的.Class文件。.Class文件在JVM中被解释为机器码,在不同的操作系统上运行。而它的跨平台特性也是从这里体现出来的。由于在不同平台上虚拟机不同,但是运行在JVM中的.Class文件是统一的解释器规则。也有了跨平台的特性。

在运行一个Java进程之后,虚拟机就开始实例化,有多少个Java的进程就有多少个虚拟机实例被创建。而进程退出或者是关闭了,虚拟机实例也就会消失。在多个虚拟机之间是不能进行数据的共享操作,这也就是分布式锁产生的原因。

Java程序代码运行机制如下

  • 1、Java源代码文件被编译器编译成字节码文件
  • 2、JVM将字节码文件编译成对应操作系统的机器码
  • 3、机器码通过调用相应的操作系统的本地方法库进行执行对应的内容。

JVM包括了一个类加载子系统(Class Loader SubSystem)、运行时数据区(Runtime Data Area)、执行引擎和本地接口库(Native Interface Library)。本地接口库通过调用本地方法库(Native Method Library)与操作系统进行交互。如下图所示

  • 1、类加载器子系统将编译好的字节码文件添加到JVM中;
  • 2、运行时数据区用于存储在JVM运行过程中所产生的数据内容,包括程序计数器、方法区、本地方法区、虚拟机栈和虚拟机堆。
  • 3、执行引擎中包括了编译器和垃圾回收器,及时编译器用于将Java的字节码编译成具体的机器码,垃圾回收器用于回收在运行过程中不再引用的对象
  • 4、本地接口库用于调用操作系统的本地方法库完成具体的指令操作。

多线程相关

在一个多核的操作系统上,JVM是允许在一个进程中同时并发执行多个线程。JVM中的线程操作是与操作系统中的线程操作是有对应关系的。在JVM线程的本地存储、缓冲区分配、同步对象、栈、程序计数器等的准备工作都完成之后,JVM会调用操作系统的接口创建一个与之对应的操作系统的线程。


JVM中的线程运行结束的时候,操作系统线程也会被回收。操作系统负责的是所有线程的调度,并且操作系统为每个线程分配CPU时间片,在操作系统初始化完成之后,就会调用Java线程操作中的run()方法执行该操作,在线程结束之后,会释放所有的对应的资源。


JVM后台运行的线程主要有如下的一些

  • 1、虚拟机程序(JVMThread):虚拟机线程在JVM到达安全点(SafePoint)时出现
  • 2、周期性任务线程:通过定时器调度线程来实现周期性的执行操作
  • 3、GC线程:GC线程支持JVM中不同的垃圾回收操作
  • 4、编译器线程:编译器线程在运行字节码的时候编译成本地机器码。是JVM跨平台的具体实现。
  • 5、信号分发线程:接收发送到JVM的信号并调用JVM方法。

JVM的内存区域

JVM的内存区域分为如下几个

  • 线程私有的区域:程序计数器、虚拟机栈、本地方法区
  • 线程共享区域:堆、方法区
  • 直接内存

线程稀有区域的生命周期与线程的生命周期是相同的。随着线程的启动而创建,随着线程的结束而销毁。

在JVM内,每个线程都与操作系统的本地线程直接映射。所以这部分内存区域的存在与否与本地线程的启动和销毁是对应的。

线程共享区域随着虚拟机的启动而创建,随虚拟机的关闭而销毁。

直接内存也叫作堆外的内存,不作为JVM运行时数据域的一部分,但是在Java并发操作中会被频繁使用。JDK的NIO模块提供的基于Channel与Buffer的I/O操作方式就是基于堆外的内存实现的。NIO模块通过调用Native函数库直接在操作系统上分配内存空间,然后通过DirectByteBuffer对象作为内存引用来对堆外的内存进行操作。

Java进程可以通过堆外内存技术避免了再Java堆和Native堆中来回复制数据带来的资源消耗问题。所以堆内存在高并发场景中被广泛地使用,实现了零拷贝操作。

程序计数器

在JVM中程序计数器作为一块很小的内存空间,主要的作用是存储当前线程运行中所执行的字节码行号的指示器。每个运行中的线程都有一个独立的程序计数器,在方法正在执行的时候,这个方法的程序计数器记录的是实时虚拟机字节码的指令地址;当然如果这个方法是一个Native方法的时候,程序计数器的值是Undefined。

程序计数器属于线程私有的内存区域,是唯一一个没有内存溢出的区域。

虚拟机栈

虚拟机栈是描述Java方法的执行过程的内存模型,它在当前栈帧(Stack Frame)中存储了局部变量表、操作数栈、动态连接、方法出口等信息。

栈帧用来存储部分运行时数据及其数据结构,处理动态连接(Dynamic Linking)方法的返回值和异常分派(Dispatch Exception)。

栈帧用来记录方法的执行过程,方法在被执行的时候虚拟机会为其创建一个与之对应的栈帧,方法的执行和返回对应栈帧的虚拟机栈中中的入栈和出栈操作。

无论方法是正常运行完成还是异常完成,都可以看做方法运行结束。如图所示,展示了线程运行及栈帧变化的过程。

本地方法区

本地方法区和虚拟机栈的作用类似,区别是虚拟机栈为执行Java方法服务,本地放啊栈为Native方法服务。

在JVM运行过程中创建的对象和产生的数据都被存储在堆内存中,堆内存是一个被线程共享的内存区域,也是垃圾收集器进行垃圾回收的主要的内存区域。由于JVM采用分代收集算法,所以Java堆从GC的角度还可以被细分为新生代、老年代和永久代。

方法区

方法区被称为永久代,用于存储常量、静态变量、类信息、即时编译器编译之后的机器码、运行时常量池等数据。如图所示

JVM把GC的分代收集扩展到了方法区,使用Java堆的永久代来实现方法区,这些JVM就可以用管理堆内存的方法来管理方法区内存。

Java中常量被放到运行时的常量池中,这块内存是方法区的一部分。静态变量的存储也是属于方法区的一部分,在Class文件中不但保存了类的版本、字段、方法、接口等描述信息,同时还保存了常量信息。

在即时编译之后,代码的内容将在类加载完成之后被保存到方法区的运行时常量池中。JVM对Class每部分的格式都有严格的规定,只有满足了规范才能通过JVM的检查然后被装载、执行。

相关文章

一章带你了解Java虚拟机——JVM(揭秘java虚拟机:jvm设计原理与实现)

1、JVM 的体系结构"堆"中存在垃圾而"栈"中不存在垃圾的原因:堆(Heap)用途:堆主要用于存储对象实例和数组。在Java中,几乎所有通过new关键字创建的对象都会存储在堆内存中。内存分配与释放:...

Java的jvm你应该知道的(jvm有什么)

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。 由于Java的跨平台性,经过编...

JVM(Java虚拟机)从0到1全部合集,强烈建议收藏

JVM(Java虚拟机)现在已经属于Java面试的重灾区,大厂面试现在基本属于必考内容,建议大家需要重点掌握。为了方便大家更好的掌握好JVM(Java虚拟机),也为了让知识更系统化,这里我单独把JVM...

Java 动态调试技术原理及实践(java的动态性指的是什么)

调试是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。最常用的断点调试技术会在断点位置停顿,导致应用停止响应。本文将介绍一种Java动态调试技术,希望能对大家有帮助。同时也欢迎读者朋友们一起交...

JVM简介—1.Java内存区域(jvm内存分布包括哪些部分)

大纲1.运行时数据区的介绍2.运行时数据区各区域的作用3.各个版本内存区域的变化4.直接内存的使用和作用5.站在线程的角度看Java内存区域6.深入分析堆和栈的区别7.方法的出入栈和栈上分配、逃逸分析...

读完这份JVM高级笔记,彻底玩转Java虚拟机,面试再也不用“虚”

提到Java虚拟机(JVM),可能大部分人的第一印象是“难”,但当让我们真正走入“JVM世界”的时候,会发现其实问题并不像我们想象中的那么复杂。唯一真正令我们恐惧的,其实是恐惧本身。JVM 一直都是面...