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

深入理解JVM

文章目录

  • 1. JVM内存区域划分
  • 2. JVM中类加载过程
    • 类加载
      • (1)类加载的基本流程
      • (2)双亲委派模型

《深入理解java虚拟机》
在这里插入图片描述

在这本书前,面试官对于JVM也不是很了解。
这本书主要还是写个一下开发 JVM 的人。

1. JVM内存区域划分

一个运行起来的Java进程,就是一个JVM虚拟机
需要从操作系统中申请一大块内存

就会把这个内存,划分成不同的区域,每块区域都有不同的作用

(1)方法区(1.7及其之前)/元数据区(1.8)
这里存储的内容,就是类对象(.class文件,加载之后,就成为了类对象)

(2)堆(占据空间最大的区域)
这里存储的内容就是代码中,new的对象

(3)栈
这里存储的内容,就是代码执行过程中,方法之间的调用关系
在这里插入图片描述

(4)程序计数器
比较小的空间,主要就是存放一个“地址”表示下一条要执行的指令,在内存中的哪个地方(方法区里)
每个方法里面的指令,都是以二进制的形式,保存在类对象中

在这里插入图片描述

虚拟机栈,程序计数器,每个线程都有一份

JVM进程中,有10个线程,就会有10个虚拟机栈和10个程序计数器

但是Heap(堆区)和Metaspace(元数据区),在JVM进程中只有一份(每个线程,有自己的程序计数器和栈空间;这些线程,公用一份堆和方法区)
每个线程有自己私有的栈空间

给你一个代码,问你某个变量,是处在内存中的哪个区?
在这里插入图片描述

  • 在new Test()时,这个new 出来的 Test()在堆上,里面包含的成员变量也自然在堆上
  • Test t 中的 t 变量是一个引用类型,是一个局部变量,处在栈上
  • static int a 带有static修饰的是静态变量,也叫类属性,它包含在类对象中,处在方法区/元数据区

在这里插入图片描述

2. JVM中类加载过程

类加载

(1)类加载的基本流程

java代码会被编译成 .class 文件(包含了一些字节码),java程序要想运行起来,就需要让JVM读取到这些 .class文件,并且把里面的内容,构造成类对象,保持到内存的方法区中

书上和官方文档把这个类加载过程中,分为5个步骤:

  1. 加载:找到.class文件,打开文件,并且读取文件内容

(往往我们的代码中,会给某个类“全限定类名”)
例如 java.lang.String,java.util.ArrayList ,JVM就会根据这个类名,在一些指定目录范围内查找

  1. 验证:.class文件是一个二进制的格式(某个字节,都是有特定含义的)

验证格式是不是符合要求
在这里插入图片描述

  1. 准备:给类对象分配内存空间(最终的目的,是要构造一个类对象) 这里的分配内存空间,还没有初始化,此时这个空间上的内存的数值就是全0的

此时如果尝试打印类对象的static成员,就是全0的

  1. 解析:针对类对象中,包含的字符串常量进行处理,进行一些初始化操作


在这里插入图片描述
在这里插入图片描述
这个过程,也叫做:把“符号引用”(文件偏移量)替换成“直接引用”(内存地址)

  1. 初始化:针对类对象进行初始化

类中的各个属性设置好,初始化好static成员,还需要执行静态代码块,加载一下父类

(2)双亲委派模型

(查找优先级)
属于类加载中第一个加载步骤中的一个环节,负责根据 全限定类名,找到.class文件

类加载器,是JVM的一个模块
JVM中内置了三个类加载器:
1.BootStrap ClassLoader(爷)
2.Extension ClassLoader (父)
3.Application ClassLoader(子)

这个父子关系,不"继承"构成的,而是这几个ClassLoader 里有一个 parent 这样的属性,指向了一个父“类加载器”

双亲:parent 这个单词“双亲之一”

在这里插入图片描述

如果给定的类你是标准库的类,任务仍然会被交给孩子执行

6.没有扫描到,就会回到Extension ClassLoader
Extension ClassLoader 就会扫描负责的拓展库的目录,如果没有找到,还是把任务交给孩子执行;如果找到了,就执行后续的类加载操作,此时查找结束

7.如果没有扫描到,就会回到Application ClassLoader
Application ClassLoader 就会负责扫描当前项目和第三方库的目录,如果找到,就执行后续的类加载操作,如果没有找到,就会抛出一个ClassNotExcption

设计一套这样的流程,主要目的是为了确保,标准库的类,被加载的优先级最高,其次是拓展库,其次是自己写的类和第三方库

假设你在自己代码中,写了一个 java.lang.String ,实际JVM加载的时候,不会加载到你自己写的这个类,而是加载标准库的类


http://www.mrgr.cn/news/69535.html

相关文章:

  • MySQL查询执行(六):join查询
  • yolo标签自动标注(使用python和yolo方法)
  • ubuntu20.04 解决Pytorch默认安装CPU版本的问题
  • CDA LEVEL 2考试大纲
  • D63【python 接口自动化学习】- python基础之数据库
  • 小程序服务商常见问题
  • 第一个 FastAPI 应用
  • centos7的maven配置
  • 【R78/G15 开发板测评】串口打印 DHT11 温湿度传感器、DS18B20 温度传感器数据,LabVIEW 上位机绘制演化曲线
  • SQLI LABS | Less-37 POST-Bypass mysql_real_escape_string
  • 网络管理利器:掌握常用的CMD命令
  • vscode生成项目目录结构
  • C# 自己编写web服务
  • 3DMAX城镇建筑区块生成插件TownBlocks使用方法详解
  • PySpark 数据处理实战:从基础操作到案例分析
  • Angular 和 Vue2.0 对比
  • 浅挖Java的BigDecimal类
  • 【JAVA】Java基础—面向对象编程:类与对象-对象的创建
  • 使用Python实现图像的手绘风格效果
  • STM32 4X4 键盘
  • 3.1 > Shell
  • python实战案例——爬取A站视频,m3u8格式视频抓取(内含完整代码!)
  • 离散数学的一些个人另类理解
  • I/O操作完成事件
  • Linux 下 mysql 9.1 安装设置初始密码 【附脚本】
  • DreamCut:AI驱动的视频编辑与屏幕录制工具