深入理解Java虚拟机到底是什么

article/2025/8/22 17:16:59

什么是Java虚拟机


作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的。但是如果要问什么是虚拟机,恐怕很多人就会模棱两可了。在本文中,我会写下我对虚拟机的理解。因为能力所限,可能有些地方描述的不够欠当。如果你有不同的理解,欢迎交流。

我们都知道java程序必须在虚拟机上运行。那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释:

虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器堆栈寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

这种解释应该算是正确的,但是只描述了虚拟机的外部行为和功能,并没有针对内部原理做出说明。一般情况下我们不需要知道虚拟机的运行原理,只要专注写java代码就可以了,这也正是虚拟机之所以存在的原因--屏蔽底层操作系统平台的不同并且减少基于原生语言开发的复杂性,使java这门语言能够跨各种平台(只要虚拟机厂商在特定平台上实现了虚拟机),并且简单易用。这些都是虚拟机的外部特性,但是从这些信息来解释虚拟机,未免太笼统了,无法让我们知道内部原理。



从进程的角度解释JVM


让我们尝试从操作系统的层面来理解虚拟机。我们知道,虚拟机是运行在操作系统之中的,那么什么东西才能在操作系统中运行呢?当然是进程,因为进程是操作系统中的执行单位。可以这样理解,当它在运行的时候,它就是一个操作系统中的进程实例,当它没有在运行时(作为可执行文件存放于文件系统中),可以把它叫做程序。


对命令行比较熟悉的同学,都知道其实一个命令对应一个可执行的二进制文件,当敲下这个命令并且回车后,就会创建一个进程,加载对应的可执行文件到进程的地址空间中,并且执行其中的指令。下面对比C语言和Java语言的HelloWorld程序来说明问题。


首先编写C语言版的HelloWorld程序。

#include <stdio.h>
#include <stdlib.h>int main(void) {printf("hello world\n");return 0;
}

编译C语言版的HelloWorld程序:

gcc HelloWorld.c -o HelloWorld

运行C语言版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloWorld/src$ ./HelloWorld 
hello world

gcc编译器编译后的文件直接就是可被操作系统识别的二进制可执行文件,当我们在命令行中敲下 ./HelloWorld这条命令的时候, 直接创建一个进程, 并且将可执行文件加载到进程的地址空间中, 执行文件中的指令。


作为对比, 我们看一下Java版HelloWord程序的编译和执行形式。


首先编写源文件HelloWord.java :

public class HelloWorld {public static void main(String[] args) {System.out.println("HelloWorld");}
}

编译Java版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloJava/src$ javac HelloWorld.java 
zhangjg@linux:/deve/workspace/HelloJava/src$ ls
HelloWorld.class  HelloWorld.java

运行Java版的HelloWorld程序:

zhangjg@linux:/deve/workspace/HelloJava/src$ java -classpath . HelloWorld 
HelloWorld

从上面的过程可以看到, 我们在运行Java版的HelloWorld程序的时候, 敲入的命令并不是 ./HelloWorld.class 。 因为class文件并不是可以直接被操作系统识别的二进制可执行文件 。 我们敲入的是java这个命令。 这个命令说明, 我们首先启动的是一个叫做java的程序, 这个java程序在运行起来之后就是一个JVM进程实例。 


上面的命令执行流程是这样的:

java命令首先启动虚拟机进程,虚拟机进程成功启动后,读取参数HelloWorld”,把他作为初始类加载到内存,对这个类进行初始化和动态链接(关于类的初始化和动态链接会在后面的博客中介绍),然后从这个类的main方法开始执行。也就是说我们的.class文件不是直接被系统加载后直接在cpu上执行的,而是被一个叫做虚拟机的进程托管的。首先必须虚拟机进程启动就绪,然后由虚拟机中的类加载器加载必要的class文件,包括jdk中的基础类(如StringObject等),然后由虚拟机进程解释class字节码指令,把这些字节码指令翻译成本机cpu能够识别的指令,才能在cpu上运行。


从这个层面上来看,在执行一个所谓的java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程,而不是我们写的一个个的class文件。这个叫做虚拟机的进程处理一些底层的操作,比如内存的分配和释放等等。我们编写的class文件只是虚拟机进程执行时需要的原料。这些原料在运行时被加载到虚拟机中,被虚拟机解释执行,以控制虚拟机实现我们java代码中所定义的一些相对高层的操作,比如创建一个文件等,可以将class文件中的信息看做对虚拟机的控制信息,也就是一种虚拟指令。


编程语言也有自己的原理, 学习一门语言, 主要是把它的原理搞明白。 看似一个简单的HelloWorld程序, 也有很多深入的内容值得剖析。



JVM体系结构简介


为了展示虚拟机进程和class文件的关系,特意画了下面一张图:



根据上图表达的内容,我们编译之后的class文件是作为Java虚拟机的原料被输入到Java虚拟机的内部的,那么具体由谁来做这一部分工作呢?其实在Java虚拟机内部,有一个叫做类加载器的子系统,这个子系统用来在运行时根据需要加载类。注意上面一句话中的根据需要四个字。在Java虚拟机执行过程中,只有他需要一个类的时候,才会调用类加载器来加载这个类,并不会在开始运行时加载所有的类。就像一个人,只有饿的时候才去吃饭,而不是一次把一年的饭都吃到肚子里。一般来说,虚拟机加载类的时机,在第一次使用一个新的类的时候。本专栏后面的文章会具体讨论Java中的类加载器。


由虚拟机加载的类,被加载到Java虚拟机内存中之后,虚拟机会读取并执行它里面存在的字节码指令。虚拟机中执行字节码指令的部分叫做执行引擎。就像一个人,不是把饭吃下去就完事了,还要进行消化,执行引擎就相当于人的肠胃系统。在执行的过程中还会把各个class文件动态的连接起来。关于执行引擎的具体行为和动态链接相关的内容也会在本专栏后续的文章中进行讨论。


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


从上面的论述可以知道, 一个Java虚拟机实例在运行过程中有三个子系统来保障它的正常运行,分别是类加载器子系统, 执行引擎子系统和垃圾收集子系统。 如下图所示:



虚拟机的运行,必须加载class文件,并且执行class文件中的字节码指令。它做这么多事情,必须需要自己的空间。就像人吃下去的东西首先要放在胃中。虚拟机也需要空间来存放个中数据。首先,加载的字节码,需要一个单独的内存空间来存放;一个线程的执行,也需要内存空间来维护方法的调用关系,存放方法中的数据和中间计算结果;在执行的过程中,无法避免的要创建对象,创建的对象需要一个专门的内存空间来存放。关于虚拟机运行时数据区的内容,也会出现在本专栏后续的文章中。虚拟机的运行时内存区大概可以分成下图所示的几个部分。(这里只是大概划分, 并没有划分的很精细)



总结


写到这里,基本上关于我对java虚拟机的理解就写完了。这篇文章的主题虽然是深入理解Java虚拟机,但是你可能感觉一点也不深入,也只是泛泛而谈。我也有这样的感觉。限于自己水平有限,也只能这样了,要是想深入理解java虚拟机,强烈建议读一下三本书:


《深入Java虚拟机》

《深入理解Java虚拟机JVM高级特性与最佳实践》

Java虚拟机规范》


其实我也读过这几本书,但是它们对虚拟机的解释也是基于一个外部模型,而没有深入剖析虚拟机内部的实现原理。虚拟机是一个大而复杂的东西,实现虚拟机的人都是大牛级别的,如果不是参与过虚拟机的实现,应该很少有人能把它参透。本专栏后面的一些文章也参考了这三本书, 虽然讲解Java语法的书不计其数, 但是深入讲解虚拟机的书, 目前为止我就见过这三本,并且网上的资料也不是很多。


最后做一个总结:

虚拟机并不神秘,在操作系统的角度看来,它只是一个普通进程。

这个叫做虚拟机的进程比较特殊,它能够加载我们编写的class文件。如果把JVM比作一个人,那么class文件就是我们吃的食物。

加载class文件的是一个叫做类加载器的子系统。就好比我们的嘴巴,把食物吃到肚子里。

虚拟机中的执行引擎用来执行class文件中的字节码指令。就好比我们的肠胃,对吃进去的食物进行消化。

虚拟机在执行过程中,要分配内存创建对象。当这些对象过时无用了,必须要自动清理这些无用的对象。清理对象回收内存的任务由垃圾收集器负责。就好比人吃进去的食物,在消化之后,必须把废物排出体外,腾出空间可以在下次饿的时候吃饭并消化食物。




更多关于深入理解Java的文章, 请关注我的专栏 : http://blog.csdn.net/column/details/zhangjg-java-blog.html

更多关于Java和Android等其他技术的文章, 请关注我的博客: http://blog.csdn.net/zhangjg_blog



http://chatgpt.dhexx.cn/article/uppwnseM.shtml

相关文章

java虚拟机(JVM)

一、虚拟机的组成 虚拟机的组成主要有&#xff1a;方法区、堆都为线程共享区域&#xff0c;有线程安全问题。 栈、本地方法栈、程序计数器为线程的独享区域&#xff0c;不存在线程安全问题。 注&#xff1a;JVM的调优主要是针对堆和栈进行的 1.1&#xff1a;运行时数据区域 …

JVM——Java虚拟机架构

0. 前言 Java虚拟机&#xff08;Java virtualmachine&#xff09;实现了Java语言最重要的特征&#xff1a;即平台无关性。 平台无关性原理&#xff1a;编译后的 Java程序&#xff08;.class文件&#xff09;由 JVM执行。JVM屏蔽了与具体平台相关的信息&#xff0c;使程序可以…

深入理解Java虚拟机

前言 JVM是什么&#xff1f; JVM&#xff08;Java Virtual Machine&#xff0c;Java 虚拟机&#xff09;顾名思义就是用来执行 Java 程序的“虚拟主机”&#xff0c;实际的工作是将编译生成的.class 文件&#xff08;字节码&#xff09;翻译成底层操作系统可以运行的机器码并…

一文彻底了解JVM

目录 JVM内存结构 GC算法和收集器 JDK性能调优监控工具 GC调优 JVM内存结构 类加载机制 Java运行时编译源码(.java)成字节码&#xff0c;由jre运行。jre由java虚拟机实现。JVM分析字节码&#xff0c;后解释并执行。 1、全盘负责委托机制 当一个ClassLoader加载一个类的时…

通俗易懂理解JAVA虚拟机

目录 前言 一、什么是JAVA虚拟机&#xff08;JVM&#xff09; 二、内存结构 1.程序计数器 2.虚拟机栈 3.本地方法栈 4.堆 5.方法区&#xff08;元数据区&#xff09; 6、执行引擎 7、直接内存 三、垃圾回收 1.如何判断对象可以回收&#xff0c; 2.垃圾回收算法…

Java虚拟机(JVM)你只要看这一篇就够了!

本文是学习了《深入理解Java虚拟机》之后的总结&#xff0c;主要内容都来自于书中&#xff0c;也有作者的一些理解。一是为了梳理知识点&#xff0c;归纳总结&#xff0c;二是为了分享交流&#xff0c;如有错误之处还望指出。 用XMind画了一张导图&#xff08;源文件对部分节点…

简单的文本编辑器

今天应同学的需求写了一个文本编辑器可以简单的时间文本的打开、删除、显示、查找、插入的简单功能 C语言代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #define MAX 10000 #include <stri…

使用vue的富文本编辑器操作

使用vue的富文本编辑器操作 vue的富文本编辑器使用以及多图片文件上传与回显 一. vue-quill-edit 1. 安装vue的富文本 cd 当前的vue项目路径 npm install quill --save npm install vue-quill-editor --save2. 在页面中引入vue的富文本 //引入Vue的ueditor的资源 import {q…

Ckeditor富文本编辑器

开发工具与关键技术&#xff1a; MVC 撰写时间&#xff1a;2021/9/28 下面我们讲Ckeditor富文本编辑器的使用&#xff1b; 要使用Ckeditor富文本编辑器&#xff0c;需要在Ckeditor官网中下载js插件&#xff0c;下载后会得到一个ckeditor文件&#xff1a; 其中包含以下文件&am…

[web]前端富文本编辑器

关于富文本编辑器 在HTML中&#xff0c;用于输入文本的只是<input type"text"/>和<textarea>这2种标签&#xff0c;这些标签都只能输入纯文本&#xff0c;不可以对输入的内容进行编排&#xff01; 在实际应用时&#xff0c;例如发布文章&#xff0c;需要…

深入浅出富文本编辑器

‍ ‍大厂技术 坚持周更 精选好文 编辑器介绍 常见的富文本编辑器现实方式可以分成两大类&#xff0c;分别是用 textarea 和 contenteditable 来实现。 textarea 结构简单使用方便&#xff0c;一些文本格式和复杂的样式难以实现&#xff0c;推荐仅在对编辑要求不高的场景使用…

推荐几个非常不错的富文本编辑器

1、wangEditor——基于javascript和css开发的 Web富文本编辑器&#xff0c; 轻量、简洁、界面美观、易用、开源免费。 界面截图&#xff1a;官网地址 2、TinyMCE——TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器&#xff0c;由JavaScript写成。它对IE6和Firefox1.5都有…

vue使用富文本编辑器vue-quill-editor

问题描述&#xff1a; 我们在开发过程中经常会遇到使用富文本编辑器进行操作&#xff0c;当前插件市场上关于富文本的编辑器挺多的&#xff0c;我们就不一一个介绍了&#xff0c;现在我们主要讲解一些vue-quill-editor富文本编辑器的使用操作和注意事项。 效果图 具体操作使用…

LayUI - 富文本编辑器

一个做后端的猿&#xff0c;难免用到LayUI&#xff0c;首先在这里&#xff0c;不推荐使用&#xff0c;坑多 我这里用的是layui-v2.5.7版本 一、富文本编辑器 缺点&#xff1a;功能太少&#xff0c;只能满足简单需求&#xff0c;只有下面这几个功能 废话少说&#xff0c;直接丢…

最佳文本编辑器

原文&#xff1a; donationcoder.com  译者&#xff1a; xbeta善用佳软  说明&#xff1a;仅做翻译&#xff0c;忠实原文。不代表同意文中观点&#xff08;xbeta认为最好的编辑器为VIM&#xff09;。 最佳文本编辑器 当前&#xff0c;好用的文本编辑器比比皆是——无论商…

Qt实现文本编辑器(一)

在Qt中QMainWindow是一个为用户提供主窗口程序的类&#xff0c;包含了&#xff1a;菜单栏、工具栏、锚接部件、状态栏以及一个中部件。今天我就来通过实现一个简单的文本编辑器讲解下对QMainWindow的各种功能讲解。 想要完整的实现一个编辑器&#xff0c;所需要的功能还是比较…

文本编辑器推荐

对于程序员或者开发者来说&#xff0c;可以通过电脑文本编辑器来完成语言的编译或输入&#xff0c;那么文本编辑器哪个好呢&#xff0c;其实使用系统自带的文本框就不错&#xff0c;当然还有不少其他软件可用。 文本编辑器哪个好&#xff1a; 一、记事本 1、这是系统自带的文…

富文本编辑器汇总

富文本编辑器&#xff1a;&#xff08;Rich Text Editor&#xff0c;RTE&#xff09;是一种可内嵌于浏览器&#xff0c;所见即所得的文本编辑器。它提供类似于Office Word 的编辑功能&#xff0c;方便那些不太懂HTML用户使用&#xff0c;富文本编辑器的应用非常广泛&#xff0c…

十五种文本编辑器

很多时候比如编程查看代码或者打开各种文档下我们都会用到文本编辑器&#xff0c;Windows自带的记事本功能很简陋并且打开大文件很慢&#xff0c;因此很多童鞋都会有自己喜欢的一款文本编辑器。在这里&#xff0c;西西挑选前15个最佳的文本编辑器&#xff0c;这些编辑器实际上主…

强烈呼吁弃用Notepad++,优秀替代品献上

Notepad作为一款开源文本编辑软件&#xff0c;无可厚非是一款优秀的软件, 但是由于“种种原因”, 坚决弃用。 禁用NotePad 推荐三款优秀的免费替代品&#xff1a; 可以直接去官网下载&#xff0c;也可以在下面的网盘地址下载&#xff08;分别提供了安装版&#xff08;分32位和…