JVM之内存区域划分、类加载和垃圾回收

news2024/9/24 13:25:19

文章目录

  • 前言
  • 一、JVM内存区域划分
  • 二、类加载
    • 1.类加载是什么?
    • 2.类加载的过程
    • 3.何时触发类加载?
    • 4.双亲委派模型
  • 三、垃圾回收(GC)
    • 1.GC是什么?
    • 2.GC回收哪部分内容?
    • 3.怎么回收?
    • (1)怎么判定对象是否是垃圾
      • 判定对象是否存在引用的办法:
        • 1.引用计数(不是JVM采取的办法,Python、PHP等有用)
        • 2.可达性分析(是JVM采取的办法)
    • (2)具体怎么回收垃圾
      • 1.标记清除
      • 2.复制算法
      • 3.标记整理
      • 4.引入“分代回收”


前言

程序在执行之前,需要通过javac将java代码编译为字节码(class文件),jvm则需要把字节码通过一定的方式进行类加载器把文件加载到运行时数据区,再通过特定的执行引擎将字节码翻译成底层系统指令交给CPU执行。java程序是一个名为java的进程,这个进程就是jvm,jvm是java运行的基础,也是实现一次编译到处执行的基础,所以深入了解JVM的运行时数据区、类加载过程以及垃圾回收有助于我们理解JVM执行过程。


一、JVM内存区域划分

jdk1.7以前可将内存区域划分为如下模块:
(1)程序计数器:放的是下一个要执行的指令的地址。
(2)方法区:放的是类对象。(加载好的类、静态变量)
(3)栈:放的是方法之间的调用关系。(局部变量)
(4)堆:放的是new的对象。(成员变量)
可参考之前写过的一篇文章。
jdk1.8以后可将内存区域划分为如下模块:
去掉方法区,加了一个元数据区。
之前方法区是在JVM申请到的这一块内存里划分了个区域;而元数据区是用本地内存(JVM内部,C++代码里搞的内存)
例:

public class Test {
	private int x = 0;
	private static int y = 10;
	public static void main(String[] args) {
		Test t = new Test();
	}
}

t是局部变量在栈上;
x是成员变量在堆上;
y是静态变量在方法区上。
变量在哪个部分,和变量类型无关,和变量的形态有关。

二、类加载

1.类加载是什么?

java程序在运行之前,需要先编译,将.java 文件编译为.class文件,运行的时候,JVM就会读取对应的.class文件,并解析内容,在内存中构造出类对象并进行初始化。这里的类对象(反射、Jackson、synchronized都有用到)描述了这个类有哪些属性、方法、继承哪个父类、实现哪个接口,同时类对象也是创建实例的具体依据。

2.类加载的过程

根据官方文档,可分为以下几步:
在这里插入图片描述

(1)加载:找到.class文件,读取文件内容,并且按照.class规范的格式来解析。
连接:
(2)验证:检查当前的.class里的内容格式是否符合要求。(.class的具体格式官方文档会有明确描述)
在这里插入图片描述

初始化:
(3)准备:给类里的静态变量分配内存空间。
(4)解析:初始化字符串常量,把符号引用替换成直接引用。
(3)初始化:针对类进行初始化,初始化静态成员,执行静态代码块,并且加载父类等等。

3.何时触发类加载?

使用到一个类的时候,就触发加载。
(1)创建这个类的实例;
(2)使用了类的静态方法/静态属性;
(3)使用类的子类(加载子类会触发加载父类)。

4.双亲委派模型

JVM加载类,是由类加载器(class loader)进行负责的,JVM自带了多个类加载器,各自负责各自的片区,如下所示,当然也可以自己实现。
(1)Bootstrap ClassLoader:负责加载标准库中的类。
(2)Extension ClassLoader:负责加载JVM扩展的类。
(3)Application ClassLoader:负责加载自己的项目里的自定义类。
描述上述类加载器相互配合的过程,就是双亲委派模型。
在这里插入图片描述
a.这三个类加载器存在父子关系;
b.进行类加载的时候,输入的内容,全限定类名,例如:java.lang.Thread;
c.加载的时候,从Application ClassLoader开始;
d.某个类加载器开始加载的时候,不会立即扫描自己负责的路径,而是先把任务委派给父“类加载器”来先进行处理;
e.找到最上面的Bootstrap ClassLoader,再往上没有父类加载器了,只能自己手动加载了;
f.如果父亲没找到类,就交给自己的儿子,继续加载;
g.如果一直找到最下面的Application ClassLoader也没有找到类,就会抛出一个“类没找到”的异常,即类加载失败。

按照这样的顺序加载,最大的好处在与,如果自己写个类,正好与标准库中的类冲突,此时仍然保证加载可以加载到标准库中的类,防止代码加载错了带来问题。

三、垃圾回收(GC)

1.GC是什么?

对于申请的内存,手动释放,最大的问题在于,容易忘记,就会发生内存泄漏,为了解决这个问题,程序员也想出来了一些方案,其中GC就是一个主流的方案,Java、Python、Js、Go、PHP…都有用,只需要负责申请内存,释放内存的工作交给JVM来完成,JVM会自动判定当前的内存是啥时候需要释放,认为这个内存不再使用了,就自动释放了。
GC中最大的问题是STW(Stop The World)问题。

2.GC回收哪部分内容?

GC主要针对堆来回收。
在这里插入图片描述
注意:一定要保证,内存不再使用才能回收。
GC中回收内存,不是以“字节”为单位,而是以“对象”为单位。

3.怎么回收?

(1)先找出垃圾;
(2)再回收垃圾(释放内存)。

(1)怎么判定对象是否是垃圾

如果一个对象也不再用了,就说明是垃圾。主要是通过引用来判定当前对象是否还能被使用,没有引用指向就视为是无法被使用的。

判定对象是否存在引用的办法:

1.引用计数(不是JVM采取的办法,Python、PHP等有用)

每次多一个引用指向该对象,计数器就+1,每次少一个引用执行该对象,计数器就-1。
当引用数值为0,则说明该对象无人使用,此时就可以释放了。
优点:简单,容易实现,执行效率也较高。
缺点:空间利用率低,尤其是小对象;可能会出现循环引用的情况。
例如:以下代码就会出现循环引用,内存无法被释放的情况。

class Test {
	Test x;
}
Test a = new Test();
Test b = new Test();
a.x = b;
b.x = a;
a = null;
b = null;

2.可达性分析(是JVM采取的办法)

约定一些特定的变量,成为“GC roots”,每隔一段时间,从GC roots出发,进行遍历,看看当前哪些变量是能够被访问到的,能被访问到的变量就成为“可达”,否则就是“不可达”。
GC roots:(1)栈上的变量;(2)常量值引用的对象;(3)方法区,引用类型的静态变量。

(2)具体怎么回收垃圾

1.标记清除

标记处垃圾之后,直接把对象对应的内存空间进行释放。
这种方式最大的问题:内存碎片。

2.复制算法

针对上面所说的内存碎片问题,来进行引入的办法。
(1)申请两倍内存,使用左侧时,右侧不用;使用右侧时,左侧不用;
(2)将“非垃圾”拷贝到另外一侧;
(3)再将之前的这一半整个释放。
缺点:
(1)空间利用率低;
(2)如果一轮GC下来,大部分对象要保留,只有少数对象要回收,这时候复制开销就很大。

3.标记整理

这个方法就是针对以上两种方法的缺点提出的办法,类似于顺序表删除元素,搬运操作。
(1)先标记垃圾;
(2)再将“非垃圾”进行搬运;
(3)释放垃圾。
这个方式,相对于上述的复制算法来说,空间利用率提高了,同时也解决了内存碎片问题,但是搬运操作也是比较耗时的。

4.引入“分代回收”

上述三个方式,都有缺点,我们需要根据实际的场景,因地制宜的解决问题。
分代回收,就是综合以上方法,根据对象不同的特点,采取不同的回收方法。
针对对象的年龄进行分类,把堆里的对象分成了新生代和老年代。
新生代GC扫描的频率更高;老年代GC扫描的频率降低。
在这里插入图片描述
(1)刚创建出来的新对象,进入伊甸区;
(2)进入伊甸区的对象,如果熬过一轮GC还存在,就通过复制算法,复制到生存区中;
(3)生存区的对象,也要经历GC的考验,每熬过一轮GC,通过复制算法拷贝到另一个生存区,只要这个对象不消亡就会在两个生存区中间来回拷贝;
(4)如果一个对象在生存区中经历了很多轮,还存在,就会把它放到老年代。
(5)对象来到老年代,定期进行GC的频率更低了,这里采取标记整理的方法来处理老年代对象。


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

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

相关文章

Rust 跑简单的例子

Rust 一门赋予每个人构建可靠且高效软件能力的语言 安装 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh 提示失败 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh info: downloading installer curl: (60) SSL certificate problem: certifi…

FastDFS搭建及整合Nginx实现文件上传

一、准备环境 FastDFS需要两个服务,一个tracker跟踪器,一个storage存储节点,tracker做调度配置,storage完成文件存储上传等功能。 这里我们使用两台虚拟机服务器(centos 7)来部署,有条件的同学建议直接上云…

Vue中多条件图片路径通过Map存储获取避免嵌套if-else

场景 若依前后端分离版手把手教你本地搭建环境并运行项目: 若依前后端分离版手把手教你本地搭建环境并运行项目_霸道流氓气质的博客-CSDN博客_前后端分离项目本地运行 前端接收到后台数据之后需进行多个条件判断进而显示对应的图片路径。 比如先判断车辆的类型、…

第十三章:AQS

AQS 基础概念为什么 AQS 是 JUC 最重要的基石?AQS 能干什么AQS内部结构AQS内部类NodeAQS 源码分析以 lock方法为入口讲解nonfairTryAcquire 方法addWaiter方法线程B线程CacquireQueued 方法B节点C节点unlockcancelAcquire 方法总结AQS 基础概念 AQS 全称&#xff1…

【树莓派】了解wiringPi库、控制继电器

目录一、wiringPi库二、继电器1、继电器介绍及接线说明2、树莓派控制继电器一、wiringPi库 wiringPi是一个很棒的树莓派IO控制库,使用C语言开发,提供了丰富的接口:GPIO控制,中断,多线程等。 在树莓派命令行输入gpio -…

供应商管理软件有哪些特点和优势?

在这个快节奏的商业环境中,企业常常需要同时处理多个供应商。手动处理所有这些流程会有不少困难,为了克服这个问题,供应商管理软件是市场上可用的最佳解决方案。 好用的供应商管理软件,比如广受客户好评的8Manage SRM&#xff0c…

Spring 长事务导致connection closed,又熬了一个大夜!

大家好,我是不才陈某~ 是的,今早一到公司就收到了机器人的告警,从异常日志来看是数据库连接已关闭,然后我在解决这个问题的过程中发现了几个问题,不急,听我一一道来 异常被try后没有继续抛出,导…

CN_广域网WAN@PPP协议

文章目录WAN和LANPPP协议PPP协议有三个组成部分:LCPNCP成帧方法PPP帧的格式信息部分范围工作过程PPP协议特点透明传输WAN&InternetWAN和LAN WAN:广域网(全写为 wide area network) 广 域 网局 域 网覆盖范围很广,通常跨区域较小,通常在一个区域内连…

Ubuntu内核OverlayFS权限逃逸漏洞(CVE-2021-3493)

文章目录前言关于linux kernel一、漏洞介绍二、漏洞原理三、漏洞影响版本四、漏洞复现五、修复方法前言 关于linux kernel Linux Kernel 一般指Linux内核。Linux是一种开源电脑操作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix操作系统。 一、漏洞介绍 …

如何掌握HEC-RAS建模方法与涉河建设项目防洪评价报告编制

随着社会经济的快速发展,我国河道周边土地开发利用率不断增大,临河建筑物与日俱增,部分河道侵占严重,导致防洪压力增大。迫切需要对全国从事防洪评价咨询类的技术人员开展防洪评价技术方面的学习,为了让相关工程技术人…

深度学习-支持向量机(SVM)

1. 简介 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别、分类(异常值检测)以及回归分析。SVM算法中,我们将数据绘制在n维空间中(n代表数据的特征数),…

C++ 函数指针探幽

首先看下面两个声明代表什么意思? double* (*(*pf)[2])(double*,int); double* (*pa[2])(double*,int);要搞清楚这两个式子,则先要清楚 指向指针的指针指针数组与指向数组的指针函数指针 指向指针的指针 指针的指针特殊点在于指向的是一个指针而已&am…

栈与队列2:用队列实现栈

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。 转载代码随想录 原文链接: 代码随想录 leetcode链接:344. 反转字符串 题目: 请你仅使用两个队列实现一个后入先出(LIFO)的栈&#x…

计量经济学复习

计量经济学 习题(史浩江版) 习题一 一. 单项选择题 1、横截面数据是指(A)。 A 同一时点上不同统计单位相同统计指标组成的数据 B 同一时点上相同统计单位相同统计指标组成的数据 C 同一时点上相同统计单位不同统计指标组成的…

GPT-Chinese 复现

github 环境准备 conda -create gpt_cn python3.7 conda activate gpt_cnconda install pytorch1.10.0 torchvision0.11.0 torchaudio0.10.0 -c pytorch pip install -r requirements.txt错误 module distutils has no attribute version解决方案: pip uninstal…

[附源码]计算机毕业设计基于Springboot游戏交易平台

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

MinIO实战

1.简介 MinIO 是一款基于Go语言发开的高性能、分布式的对象存储系统。客户端支持Java,Net,Python,Javacript, Golang语言。 2.部署 2.1单机器单节点(docker) 官网教程:https://min.io/docs/minio/container/index.html mkdir -p ~/minio/dat…

Node.js编程

Node.js编程 一、实验目的与要求 实验任务 用户信息增删改查 掌握数据库软件的安装了解集合、文档的概念掌握使用mongoose创建集合的方法创建集合掌握对数据库中的数据进行增删改查操作 二、实验任务和步骤 实验1. 用户信息增删改查 需求说明 (1)搭建网站服务器&#xf…

第十章 降维与度量学习

10.1 k近邻学习 k近邻学习(kNN)是一种常用的监督学习方法,其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个邻居的信息来进行预测。 k近邻学习似乎与…

2022 计网复习计算题【太原理工大学】

期末复习汇总,点这里!https://blog.csdn.net/m0_52861684/category_12095266.html?spm1001.2014.3001.5482 三、计算题 1. 假定 1km 长的 CSMA/CD 网络的数据率为 1Gb/s,设信号在网络上的传播速率为 200000km/s。求能够使用此协议的最短帧长…