八股文之JVM

news2024/11/25 14:46:54

目录

1.JVM内存划分

2.JVM类加载过程

3.JVM垃圾回收机制GC

3.1.判断谁是垃圾

3.2.如何释放对应的内存


1.JVM内存划分

在一个Java程序运行起来之后,jvm就会从操作系统中申请一块内存,然后就会将该内存划分成多个部分,用于不同的用途。

(1)主要划分成五个部分

堆、栈、元数据区(方法区)、常数计数器(很少涉及)

图示:

像堆区中的各个部分划分,在后面的垃圾回收机制再拿出来鞭策一遍,在这里就不先做任何的赘述。

(2)每块内存区的功能

堆区:

整个内存区域中最大的区域,用于存放java代码中new出来的对象、和成员变量。

栈:

一般java是使用jvm虚拟机栈,这里保存了方法的调用关系、局部变量等。也就是每个方法怎么被调用,被谁调用等

元数据区:

元数据区,以前也成为方法区,用来存放类对象、类属性(静态成员)、常量

程序计数器:

属于内存中最小的区域,用来保存要执行的下一条指令的地址

(3)实战划分内存

看下嘛的一段代码,查看下面的变量和对象分别处于哪一块内存中

class Demo2 {

}
class Demo1 {
    public int a;
    Demo2 b = new Demo2();
    public String c = "love";
    public static int d;

}

public class Test {
    public static void main(String[] args) {
        Demo1 e = new Demo1();
    }
}

对于变量:a,b,c,d,e 其中a,b,c都属于成员变量,存在于堆上;而e属于局部遍历,存在栈上;而d属于静态成员变量,属于类属性,存在于元数据区。它们只是属于变量,里面存有一个值,会指向另一块内存空间。

各对象内存分布和指向关系

以上就是对应的各种关系。

对于上述的四个区域,堆和元数据区,在整个进程中只有一份,而栈和程序计数器,是每个线程都有一份。

2.JVM类加载过程

一个.java文件变成.class文件的过程,也是从硬盘加载到内存中,得到类对象的过程。

(1)类加载的五个环节

加载、验证、准备、解析、初始化

(2)每个环节对应的作用

1.加载

在硬盘上找到对应的.class文件,并且读取.class文件内容

2.验证

检查.class文件中的内容,是否符合要求(如文件格式等)

3.准备

给类对象分配内存空间

4.解析

对字符串常量初始化,把刚才.class文件中的常量内容取出来放到元数据区

5.初始化

针对类对象进行初始化,给静态成员初始化,也就是执行静态代码块

(3)“双亲委派模型”

在第一步的加载环节,目的是打开.class文件,前提就是需要通过“全限定类名”找到文件才能进行打开,所以“双亲委派模型”就是寻找.class文件的一种机制。

在这个环节,涉及到一个概念:类加载器

在JVM中也会包含一些类,负责完成后续的类加载工作。其中JVM内置了三个类加载器,负责加载不同的类

分别是三个类:BootstrapClassLoader、ExtentionClassLoader、ApplicationClassLoader

1)三个类加载器作用

所以成为双亲委派模型,但是跟准确的说法为:父亲委派模型或者单亲委派模型

2)加载过程

那么双亲委派模型是如何找类的呢?我们举一个例子,假设我们自己写了一个java程序,会给定一个全限定类名

3)双亲委派模型应对的场景

如果自己的代码中写的类的名字和标准库/扩展库冲突了,JVM会确保加载的类是标准库的类(不会加载自己写的类),如果标准库中的类无法加载,那么Java进行就没有办法正常工作了。

这样还有一个好处,就是可以确保自己写的类肯定可以被加载到。

3.JVM垃圾回收机制GC

对于Java,回收垃圾采取的是自动回收策略,策略也称为GC。

对于GC来说,回收的其实是堆上的内存。而对于堆,保存的主要是对象,换句话说,也就是主要回收对象,那怎么回收对象呢?主要有两个步骤:判断谁是垃圾和如何释放其对应的内存。

3.1.判断谁是垃圾

在判断谁是垃圾这一步,Java是采取很保守的做法,也就是可以保证只会释放后续不会再使用的对象,后续仍会使用到的对象,是不会进行回收的,所以才用的策略是:判断某个对象是否存在引用指向,如果没有引用指向,就可以判断为垃圾,反之不行。

判断谁是垃圾,GC有两种策略:引用技术和可达性分析,而JVM采取的策略只有可达性分析,引用计数则不是。

(1)引用计数

1)策略:每创建一个对象,就在对象前面多开辟一块空间,用来计数使用,有一个引用指向该对象,计数变量就+1,如果计数器为0,则需要回收该对象。

2)代码举例

class TT {

}
public class GC {
    public static void main(String[] args) {
        TT a = new TT();
        TT b = a;
    }
}

对于实例化的TT对象,当前有两个对象指向它,所以计数值为2(分别是引用a和b),如果a=null或者b=null,则计数值-1,两个都置为null,则计数为0.

对于引用计数存在两个问题

问题一:会消耗额外的内存空间

如果对象本身的内存比较大,相比来说计数的空间就很小;但是如果对象内存空间很小,那么计数空间就会显得很大,就会浪费很大的空间

问题二:存在“循环引用”问题

这类问题就会让外部代码无法对 对象进行释放

代码举例:

class T {
    T t;
}
public class GC {
    public static void main(String[] args) {
        T a = new T();
        T b = new T();
        a.t = b;
        b.t = a;
    }
}

这是一段有问题的代码

图示分析:

存在的问题:当将引用a和b置为null时,按理来说这两个对象是要被回收了,但是这里却不会,因为计数不为0,不能回收。所以这就是引用计数最大的一个问题。

(2)可达性分析

JVM采取的是可达性分析,既解决了空间问题,也解决了循环引用问题。

1)定义:JVM会把对象之间的引用关系,定义成树形结构,JVM可以不停的从根节点开始遍历,可以访问到的对象,成为“可达”,剩下的就是“不可达”。

标记为不可达的对象,也就被标记成垃圾。

2)举例

例如这样的结构,如果将c=null,那么c后面的两个对象f和g就变成不可达,就要成为垃圾。

访问这棵树的所有节点,都是要通过根节点a开始。

3)确定根节点

对于根节点,可能的情况有:栈上的引用局部变量、常量池中引用的对象、方法区中的静态成员。

3.2.如何释放对应的内存

当已经标记好垃圾之后,该怎么回收呢?下面介绍。一共四种,前面三种是铺垫,最后一种才是JVM真正使用的

(1)标记-清除

策略:直接把标记为垃圾对象的对应的内存回收,已经回收的内存,其他对象可以使用

缺点:这样做很存在内存碎片问题,后续就很难申请到一大块连续的空间

(2)复制算法

策略:要删除空间1中abcd中的ac,就直接将bd复制到另一块空间中

缺点:严重浪费空间。比如有8G内存,就只能使用4G

(3)标记-整理

策略:把不需要释放的内存空间覆盖到需要释放的空间上。可以解决内存碎片问题

缺点:时间开销很大

(4)分代回收

策略:根据不同的场景,采取不同的回收策略,这里的回收策略也就是上述介绍到的。

如何根据场景呢?就是要根据时间来,哪个时间呢?就是对象的年龄。

因为GC主要回收的地方就是堆区,所以堆区上会有对应的分区,不同的区代表对象的年龄

Eden:称为伊甸区,新创建的对象都处于这里。

这里的对象生命周期都很短,一般经过一轮GC就会成为垃圾。从伊甸区到达生存区,采取的是复制算法

s0:称为生存区,一般经过一轮还未被回收,就会到达下一个阶段

从生存区到达幸存区,也是通过复制算法

s1:称为幸存区

这里也称为生存区,到达这里也需要通过复制算法。

Old区:到达这里的对象都会成为老年代的对象,GC的扫描频率会大幅度降低。

对于老年代中的垃圾,就会通过标记-整理的方法进行回收

总结一下:伊甸区、生存区、幸存区都是通过复制算法回收垃圾很搬运到下一个区,对于老年区,则是通过标记-整理回收垃圾。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1832923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python-03

使用File操作文件 open(file, moder, buffering-1,encodingNone, errorsNone, newlineNone, closefdTrue, openerNone) file:要打开的文件 mode:文件打开模式。默认访问模式是读(r) buffering:缓冲区大小 encodin…

淘宝商品评论API接口测试实例(获取淘宝商品评论,翻页展示、支持并发)

item_review-获得淘宝商品评论 测试页 公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,item_get,item_search_shop…

学生党蓝牙耳机性价比排行榜,好评榜TOP5机型推荐

随着科技的飞速发展,蓝牙耳机已经成为我们日常生活中不可或缺的一部分,无论是运动健身、通勤路上还是休闲娱乐,它都为我们带来了极大的便利,然而,市面上的蓝牙耳机种类繁多,价格参差不齐,如何选…

pg——psql命令行交互式客户端工具

1、启动数据库 ./pg_ctl -D /usr/local/pgsql/data/ -l /usr/local/pgsql/log 2、登录数据库 psql template1 3、查看所有数据库 \l 4、创建数据库 create database testdb; 5、连接某数据库 \c 数据库 6、查看数据下的表 \d 7、 查看数据库下的所有schema \dn 8、查看表的结构…

业务表对应主键为varChar类型且无自增策略的新增与修改问题

业务表对应主键为varChar类型且无自增策略的新增与修改问题 上周五领到一个需求,在开发过程中遇到一点小插曲,在此记录下,话不多说,直接看表结构: 这里机构id为主键且无自增策略,也就是说机构id这个字段是…

PHP安装配置

文章目录 1.下载PHP2.配置环境变量3.Apache安装配置 1.下载PHP PHP即“超文本预处理器”,是一种通用开源脚本语言。PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言。PHP独特的语法混合了C、Java、Perl以及 PHP 自创的语法…

Samba 服务器的搭建以及windows server 2008客户端的使用实验报告

一、 实验目的 通过 Samba 服务器的搭建,基本了解搭建服务器的基本步骤,理解 Samba 服务器的实现文件共享的功能,如何配置 Samba服务器配置文件等。 二、 实验环境 准备一台安装 centOS7系统的 Linux 虚拟机作为 Samba 服务器 server,准备…

海外仓系统有哪些?主流海外仓系统类型、优缺点,不同海外仓如何选择

作为海外仓的经营者,不管海外仓大小,你都应该知道海外仓系统对提升仓库管理效率有多重要。 不过现在市场上的海外仓系统确实种类太多了,想选到一个适合自己海外仓,性价比又比较高的wms海外仓系统也不是一件容易的事情。 本文会详…

GD32 MCU启动后如何运行到main函数

GD32 MCU启动后如何运行到main函数入口?你是否也有这样的疑虑。在执行到main函数之前MCU干了哪些事情呢?下面为大家解答。 MCMCU上电后,首先会根据BOOT0和BOOT1的状态判断从主Flash/SRAM/ISP中启动,如果BOOT0为低电平&#xff0c…

windows反弹shell的方法

什么是正向shell和反向shell 首先说,正向shell是控制端主动连接被控制端,通过目标主机开放一个监听端口等待其他主机访问,从而获得对目标主机的shell访问,优点是控制端可以整个控制目标主机,但缺点会受到防火墙的连&a…

多标签识别:JoyTag模型的图像标注革命【开源】

公共视觉模型通常会对其训练数据集进行严格过滤,这限制了这些基础模型在广泛概念上的表现,进而限制了表达自由、包容性和多样性。JoyTag通过结合Danbooru 2021数据集和一组手动标记的图像,努力提高模型对不同类型图像的泛化能力。 JoyTag项目…

简易版 | 代码生成器(包含插件)

一、代码生成器 先导入依赖 <!-- Mybatis-Plus --> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.6</version> </dependency><!-- 代码生成器 --…

jvm必知必会-类的生命周期图文详解

类的生命周期描述了一个从加载、使用到卸载的过程; 而其中的 连接 部分又分为一下三个阶段: 验证准备解析6.1 加载阶段 Loading阶段第一步是 类加载器 会根据类全限定名通过不同的渠道以二进制流的方式获取字节码信息,程序员可以使用Java代码扩展不同的渠道。 比如通过 …

超强生图模型,抢先体验!

文生图模型Stable Diffusion 3 Medium开源啦&#xff01;优刻得GPU云主机目前已上线该模型镜像&#xff0c;开箱即用&#xff0c;即刻体验&#xff01;具体操作见文末。 近年来&#xff0c;生成式人工智能的快速发展正在改变我们的生活。作为这一领域的前沿技术之一&#xff0…

一个软件是如何开发出来的呢?

一、前言 如今&#xff0c;AI大爆发的时代&#xff0c;作为一名IT从业者&#xff0c;你是否也想尝试开发一套自己的系统&#xff0c;实现那些看似有可能实现的天马行空的想法&#xff0c;变成一个优秀甚至伟大的产品&#xff0c;甚至带来某个行业的革新&#xff0c;那作为一名…

rtthread stm32h743的使用(九)RT_WEAK报错

rtthread stm32h743的使用&#xff08;九&#xff09;RT_WEAK报错 我们要在rtthread studio 开发环境中建立stm32h743xih6芯片的工程。我们使用一块stm32h743及fpga的核心板完成相关实验&#xff0c;核心板如图&#xff1a; 我们新建工程&#xff0c;参考前面rtthread stm32h…

springboot 腾讯地图接口验签 java

1. 原因 需求需要通过小程序定位拿到用户所在行政区信息,但是小程序定位只能拿到经纬度信息,所以需要调用腾讯地图的逆地址解析(我认为:微信是腾讯的,那么使用腾讯地图的逆地址解析经度应该不会损失太多)如果WebServiceAPI Key配置中签名校验,那么调用接口就需要进行验签 2. W…

YOLOv8 + SAM实现自动标注分割数据集【附完整源码+步骤详解】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

eclipse maven打包报错: 致命错误: 在类路径或引导类路径中找不到程序包 java.lang的解决

还是上来帖张图&#xff1a; 1、系统之前是运行在mac上的&#xff0c;打包一切正常&#xff0c;但是现在在win11的eclipse打包就报错了。 2、致命错误: 在类路径或引导类路径中找不到程序包 java.lang&#xff0c;上面的问题应该是找不到java中的jar中的class导致。 解决&…

会声会影2023软件怎么下载安装? 【详细安装图文教程】

简介&#xff1a; 会声会影&#xff08;Corel VideoStudio&#xff09;为加拿大Corel公司发布的一款功能丰富的视频编辑软件。会声会影2023简单易用&#xff0c;具有史无前例的强大功能&#xff0c;拖放式标题、转场、覆叠和滤镜&#xff0c;色彩分级、动态分屏视频和新增强的…