首页 > 编程语言 >Java JVM 零基础,详细讲解一(基础结构)。

Java JVM 零基础,详细讲解一(基础结构)。

时间:2024-09-09 19:25:14浏览次数:3  
标签:Java 收集器 虚拟机 基础 回收 内存 JVM

在 Java 编程的世界里,JVM是一个至关重要的存在。如果你是一个零基础的开发者,想要深入了解 JVM,那么这篇博客将为你提供超详细的讲解。

一、什么是 JVM?

JVM(Java Virtual Machine,Java 虚拟机)是一种用于计算设备的规范,它是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现。对于 Java 语言来说,JVM 是其运行的基础。Java 程序并不是直接在操作系统上运行,而是在 JVM 上运行。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序可以在不同的操作系统上实现 “一次编写,到处运行”。

二、JVM 的体系结构

(这里涉及多线程相关的知识,如果不理解可以先去了解一下多线程)

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

Java虚拟机栈描述的是Java方法执行的线程内存模型:方法执行时,JVM会同步创建一个栈帧,用来存储局部变量表、操作数栈、动态连接等

本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务

方法区是比较特别的一块区域,和堆类似,它也是各个线程共享的内存区域,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据

程序计数器也被称为PC寄存器,是一块较小的内存空间。它可以看作是当前线程所执行的字节码的行号指示器

执行引擎就是用于执行在class中定义的指令

本地库接口用于和其他语言进行交互 , 提供和其他编程语言交互的入口

2.1 JVM 运行时数据区(面试题)

组成部分:堆、方法区、栈、本地方法栈、程序计数器(详细内容看上面)。

三、JDK、JRE和JVM的关系

JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。

JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。

JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。

这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。

所以,我们再写Java代码之前,只需要下载一个jdk就能够运行代码。

四、垃圾回收机制

垃圾回收(Garbage Collection,GC)是 JVM 自动管理内存的一种机制。在 Java 程序中,程序员不需要手动管理内存,JVM 会自动回收不再使用的对象所占用的内存空间。

4.1、如何判断对象是否可回收?

引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加 1;当引用失效时,计数器值就减 1。当计数器值为 0 时,表示该对象没有被任何地方引用,可以被回收。但是,引用计数法存在一个问题,就是无法解决循环引用的问题。

可达性分析算法:通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的,可以被回收。

4.2、垃圾回收算法

标记 - 清除算法:首先标记出所有需要回收的对象,然后在标记完成后统一回收所有被标记的对象。这种算法的缺点是会产生大量的内存碎片,可能会导致后续程序在运行过程中需要分配较大的连续内存空间时无法满足要求。
复制算法:将内存分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另一块内存上,然后再把已使用过的内存空间一次清理掉。这种算法的优点是实现简单,运行高效,不会产生内存碎片。但是,它的缺点是需要将内存空间一分为二,导致可用内存空间减少一半。
标记 - 整理算法:标记过程与标记 - 清除算法一样,但是在后续步骤中,不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。这种算法的优点是不会产生内存碎片,缺点是整理过程比较耗时。

4.3、垃圾回收器

Serial 收集器:是一个单线程的收集器,它在进行垃圾回收时,必须暂停其他所有的工作线程,直到它收集结束。
ParNew 收集器:是 Serial 收集器的多线程版本,它可以充分利用多 CPU 的优势,提高垃圾回收的效率。
Parallel Scavenge 收集器:是一个新生代收集器,它采用复制算法,目标是达到一个可控制的吞吐量。
Serial Old 收集器:是 Serial 收集器的老年代版本,它采用标记 - 整理算法。
Parallel Old 收集器:是 Parallel Scavenge 收集器的老年代版本,它采用标记 - 整理算法。
CMS(Concurrent Mark Sweep)收集器:是一种以获取最短回收停顿时间为目标的收集器,它采用标记 - 清除算法,整个过程分为四个阶段:初始标记、并发标记、重新标记和并发清除。
G1(Garbage-First)收集器:是一种面向服务端应用的垃圾收集器,它将整个 Java 堆划分为多个大小相等的独立区域(Region),在进行垃圾回收时,优先回收价值最大的 Region。

五、总结

JVM 是 Java 程序运行的基础,了解 JVM 的体系结构和垃圾回收机制对于提高 Java 程序的性能和稳定性至关重要。希望这篇博客能够帮助零基础的开发者更好地理解 JVM。

标签:Java,收集器,虚拟机,基础,回收,内存,JVM
From: https://blog.csdn.net/weixin_70171141/article/details/142058345

相关文章

  • 《Java 归并排序:高效稳定的排序算法》
      一、归并排序简介介绍归并排序是一种基于分治思想的经典排序算法,适用于各种规模的数据排序任务。 二、算法原理(一)分治策略将未排序数组分割成两个子数组,递归地对子数组进行排序,最后合并成有序数组。(二)关键步骤1.分割阶段:将数组分成两个子数组,通常是平均分割。2.......
  • 【数据结构】基础学习
    线性数据结构1.链表(LinkedList)链表是一种线性数据结构,每个节点包含数据和指向下一个节点的引用(即指针)。1.链表的基本操作(Java中的LinkedList类)LinkedList是Java标准库中的一个双向链表实现。我们将通过一些插入、删除和获取操作来演示其使用。importjava.util.L......
  • 【Java基础】
    Java基础1.变量与数据类型在Java中,变量用于存储数据,每个变量都有类型。Java的数据类型分为两类:基本数据类型(如int,double,char,boolean)引用数据类型(如String,数组,对象)示例:publicclassMain{publicstaticvoidmain(String[]args){//......
  • [Java面向对象]static方法
    static方法不能重写在Java中,静态方法不能被重写。静态方法属于类本身,而不是类的实例。因此,当你在子类中定义一个与父类静态方法同名的方法时,这不是重写,而是隐藏。publicclassclassA{publicstaticvoidmethod(){System.out.println("classA的静态方法");......
  • 【最新华为OD机试E卷-支持在线评测】通过软盘拷贝文件(200分)多语言题解-(Python/C/Ja
    ......
  • 【C++基础概念理解——std::unique_ptr如何管理动态分配的对象的生命周期?】
    文章目录问题解释问题std::unique_ptr用于管理动态分配的对象的生命周期,那么这种智能指针怎么实现管理生命周期的呢?解释用于确保对象不再使用时自动释放,从而避免内存泄漏。std::unique_ptr独占管理对象的所有权,同一时间只能有一个std::unique_ptr指向该对象。确保......
  • 【python篇】——python基础语法一篇就能明白,快速理解
    前言:本文章是在已经学习了C语言之后作者角度下进行书写的一篇关于python当中基础的语法说明。文章目录快速深入理解python当中的语法基本数据类型算数运算符类型的查看与转换变量的输入与输出条件语句比较运算符和逻辑运算符if、elif、else三目运算符循环语句while......
  • 题单2:基础练习
    小技巧int型整数所能表示的范围较少,因此当需要精确的表示大数时,建议使用longlongint为便于使用,可以采用宏定义#defineINTlonglongint更好的做法是使用cstdint库中的int64_t类型#include<cstdint>int64_tmyVariable=1234567890123456789LL;题单96A:Football......
  • java毕业设计-基于springboot+vue的高校运动会管理系统设计和实现,基于springboot+vue
    博主介绍:✌️码农一枚,专注于大学生项目实战开发、讲解和毕业......
  • java毕业设计-基于springboot+vue的篮球吧一体化服务平台设计和实现,-基于springboot的
    博主介绍:✌️码农一枚,专注于大学生项目实战开发、讲解和毕业......