当前位置: 首页 > news >正文

JVM虚拟机--JVM的组成

(一)JVM的组成

在这里插入图片描述

一、JVM介绍

(1)JVM的作用

我们知道,Java代码要想在计算机中正常运行,就需要经过编译为class二进制字节码文件,而JVM就提供了class二进制字节码的运行环境。
在这里插入图片描述

  1. 一次编写,到处运行
    因为JVM是运行在操作系统当中的,通过屏蔽掉不同操作系统之间的差异,来实现自己作为跨平台语言的这种特性。因为无论在任何操作系统当中真正运行代码的不是这些操作系统,而是JVM,所以才能做到一次编写,到处运行
  2. 自动内存管理,垃圾回收机制
    与C语言相比,C语言需要程序员自行管理内存,如果编码不当很容易出现内存泄漏的现象。而Java虚拟机自带的垃圾回收机制就大大减轻了程序员的负担,减少出错机会。

(2)JVM的组成部分与运行流程

在这里插入图片描述

  1. Java Source
    指的是我们自己编写的Java代码,也就是.java文件
  2. Java Class
    将java文件编译为class文件
  3. 类加载子系统
    用于将java代码转换为字节码
  4. 运行数据区
    主要作用是把字节码加载到内存当中,因为程序必须要加载到内存才能运行。
    具体其他模块的功能将在后面进行细致介绍。
  5. 执行引擎
    用于把字节码翻译为底层系统指令。
    解释器:用于解释字节码信息:即使编辑器:会针对你的代码进行优化;GC垃圾回收:主要指的是运行数据区中的堆空间,后期将重点去讲解该垃圾回收机制。
  6. 本地方法接口与本地库
    由C/C++来实现,因为Java代码有时候并不能完全实现某些功能,只需要去记住系统提供的接口,再去进行调用即可。

(3)学习什么

在这里插入图片描述
在这里插入图片描述

二、程序计数器

在这里插入图片描述
线程私有的也就没有线程安全问题,因为每一个线程内部都有这样一个程序计数器。
在Java程序的class字节码文件中详细说明了代码的执行过程。
要想查看class字节码的信息就可以通过javap命令来查看字节码的反汇编信息:
在这里插入图片描述
在这里插入图片描述
这里面详细记录了main方法的执行过程,并且可以发现原来一行的sout打印代码被拆成了多行来执行。左侧代码的执行地址(0,3,5,8)可以理解为代码的执行行号。

  1. getstatic代表获取一个静态的变量,而System命令的out属性其实就是一个静态变量,类型是PrintStream。
  2. ldc加载常量,这里指的是String类型的字符串(hello world)。
  3. invokevirtual表面将要去调用的方法(println)。
  4. return指的是结束该方法。
    在这里插入图片描述
    假设现在在多线程环境下,要去执行当前代码,程序计数器就会给每一个线程去记录该行号。并且假设此时存在两条线程互相争夺执行权,线程1执行到第9行代码时被线程2夺走执行权,那么等线程2执行完毕或是线程1夺回执行权后,就会从先前执行到的第9行代码继续执行。

总结:

在这里插入图片描述

三、堆的详细介绍

(1)堆的介绍

在这里插入图片描述
1.线程共享区域肯定就会存在线程安全问题。
2.堆的划分
堆中又划分为了两个主要部分:年轻代与老年代;年轻代划分的三种类型Eden、S0、S1也存在一定区别,而S0、S1也被称为Survivor幸存者区。
通常情况如下:一个对象进来后先到Eden区,假如该对象在垃圾回收后依然存活,它就会被复制移动到S0或S1,且在挪动达到一定次数后也仍然存活,就会被放到老年代当中,老年代主要指的是生命周期比较长的对象。
而对象的挪动规则将会在后期讲解垃圾回收机制时会再详细说明。
3.元空间的作用
用于保存类的信息、静态变量、常量、编译后的代码。

(2)Java1.7与1.8的堆的区别是什么

在Java1.8之前,堆的区域当中还存在一个永久代,它的作用与元空间一样。
在这里插入图片描述
到了Java1.8之后,它把方法区/永久代放到了本地内存当中,也就是元空间中。为什么要放到本地内存:因为元空间与方法区主要存储的是一些类或常量,而随着项目运行时加载的类越来越多,这块方法区就会变得不可控,容易出现内存溢出或浪费内存,所以到了Java1.8优化过后就把他们都放到了本地内存,能够让堆来节省空间,最终目的都是避免OOM(内存溢出)

(3)总结

在这里插入图片描述

四、虚拟机栈

(1)什么是虚拟机栈

因为虚拟机栈是每个线程在运行时所需要的内存,多个线程运行时就会创建多个虚拟机栈,所以栈内存也是线程安全的
在这里插入图片描述

面试题:

在这里插入图片描述
在这里插入图片描述

  1. 垃圾回收是否涉及栈内存
    栈帧弹栈后释放内存的过程并不需垃圾回收器

(2)栈内存溢出情况

在这里插入图片描述

(3)总结

在这里插入图片描述
在这里插入图片描述

五、方法区

(1)方法区概述

在这里插入图片描述
元空间当中的Class用于存储类的信息,包括类的结构、方法、字段等;Classloader就是类加载器;运行时常量池将会在后面详细介绍。
通过Java代码来模拟本地内存溢出的情况:
因为元空间的默认大小是没有上限的,要想模拟内存溢出的情况首先就需要设置元空间大小上限为8m
在这里插入图片描述
在这里插入图片描述
执行该段代码,发现控制台中会提示元空间大小过小
在这里插入图片描述

(2)常量池

在这里插入图片描述

(3)运行时常量池

在这里插入图片描述

(4)总结

在这里插入图片描述

六、直接内存

(1)直接内存介绍

在这里插入图片描述
既然是操作系统的内存,那么是可以使用java程序来使用它的。
我们平时的IO是BIO,此处的NIO要比BIO的吞吐量高很多。

(2)常规IO数据拷贝流程

在这里插入图片描述
Java本身并不具备磁盘读写的能力,要想进行磁盘读写就必须调用操作系统所提供的函数,也就是本地的native方法。
常规IO的问题:在内存当中有两块缓冲区,这样读取数据时就必须要去读取、存储两份。因为java代码本身是访问不到系统缓冲区的,必须要把数据读到java缓冲区后才能使用java代码进行操作。这样就造成了一个不必要的数据复制,因此效率就比较低。

(3)NIO数据拷贝流程

在这里插入图片描述
这里出现的直接内存就相当于在操作系统中划出了一块缓冲区,可供系统与java代码共同访问,也就是共享的内存区域。这样java代码操作起来就非常方便了,提高运行效率,比较适合文件的IO操作。

(4)总结

在这里插入图片描述

http://www.xdnf.cn/news/35497.html

相关文章:

  • 自动化测试 VS 测试开发
  • xgboost原理及参数分析
  • 2025年Q1数据安全政策、规范、标准以及报告汇总共92份(附下载)
  • 最新得物小程序sign签名加密,请求参数解密,响应数据解密逆向分析
  • Java读取JSON文件并将其中元素转为JSON对象输出
  • C++ 数学算法全解析(二):解方程与三角函数实用指南
  • 【62期获取股票数据API接口】如何用Python、Java等五种主流语言实例演示获取股票行情API接口之沪深A股派现与募资对比数据及接口API说明文档
  • Linux进程控制
  • 点灯大师(第一步)
  • 【RL系列】ReTool: Reinforcement Learning for Strategic Tool Use in LLMs
  • LeetCode --- 154双周赛
  • 在串口通信中使用共享指针(`std::shared_ptr`)
  • 【HDFS入门】HDFS数据冗余与容错机制解析:如何保障大数据高可靠存储?
  • Ubuntu Linux 中文输入法默认使用英文标点
  • 深入理解FreeRTOS操作系统:计数型信号量的原理与应用
  • JavaWeb 课堂笔记 —— 13 MySQL 事务
  • 2000-2017年各省城市天然气供气总量数据
  • Ubuntu 25.04 “Plucky Puffin” 正式发布
  • 多线程和线程同步
  • 非接触式水位传感器详解(STM32)
  • office软件中word里面的编号库和列表库功能
  • 06-libVLC的视频播放器:推流RTMP
  • 第三届世界科学智能大赛新能源赛道:新能源发电功率预测-数据处理心得体会1
  • Java @Serial 注解深度解析
  • day46——两数之和-输入有序数组(LeetCode-167)
  • 人工智能在智慧农业中的应用:从田间到餐桌的变革
  • 【Vue】布局解析
  • Manus技术架构、实现内幕及分布式智能体项目实战 线上高级实训班
  • 洛谷的几道题
  • 某局部三层休闲娱乐中心建筑设计与结构设计