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

JVM基础知识

一、JVM的内存区域划分

一个进程在运行的时候,会向操作系统申请到内存资源,从来存放程序运行的相关数据。

JVM本质上就是一个java进程,在运行的时候也会从操作系统那搞一块内存,供Java代码执行使用。

JVM又把申请的一块内存根据不同的用途划分出了不同区域。

每一个线程中都独有一份自己的栈空间和程序计数器(PC)

栈:存放方法调用关系,局部变量。

程序计数器(PC):记录当前线程执行的下一条指令的内存地址。

堆:存放对象的实例,即new出来的对象都在这里。

方法区(元数据区):存放类对象,常量池,静态成员。

二、JVM类加载机制

类加载本质上就是将.class文件(硬盘)加载到内存(方法区)中。

Java程序最开始在编写的时候是一个.java文件,然后通过编译生成.class(字节码)文件,运行java程序,JVM就会读取.class文件,把文件的内容放到内存中,构造.class对象。

类加载的过程

  • 加载:找到.class文件,打开文件,读取文件内容。

  • 验证:检查当前.class文件的格式。

  • 准备:给类对象分配内存空间。给类对象分配空间并进行默认初始化(一般置为0)。

  • 解析:主要针对字符串常量,将常量池中的符号引用替换为直接引用。

    符号引用:相对的位置

    直接引用:真是的内存地址

    在.class文件中,由于还未加载到内存中,无法确定内存地址,只能使用一个相对偏移量来表示内存地址。当JVM将.class文件进行加载分配了内存地址,此时字符串常量就有了真实地址,然后将一些引用变量中的"符号引用"替换成直接引用。

  • 初始化:对类对象进行初始化。初始化静态成员,执行静态代码块,加载父类.....

双亲委派模型

双亲委派模型描述的是类加载的过程中,如何找.class文件。

JVM在加载.class文件的时候,需要用到类加载器,在JVM中就自带了三个类加载器。

这三个类加载器存在"父子关系",这里的父子关系并不是通过继承形成的,而是对象中有一个引用指向"父类"加载器实例

  • Bootstarp ClassLoader 负责加载标准库中的类(Java标准文档中规定了需要提供哪些基本类)

  • Extension ClassLoader 负责加载JVM扩展库中的类(JVM厂商可能还会添加一些类)

  • Application ClassLoader 负责加载第三方库的类(mysql、jackson.......以及一些自己写的类)

双亲委派模型就描述了类加载的流程:

1.先从Application ClassLoader开始,此时并不会立即搜索第三方库的类,而是先把加载任务委派给"父亲",让父亲先尝试加载

2.到了Extension ClassLoader,此时也不会立即搜索扩展库的类,而是再把加载任务委派给"父亲",让父亲先尝试加载

3.到了Bootstrap ClassLoader,此时Bootstrap ClassLoader没有"父亲"了,只好自己去加载类了。如果找到了这个类,就会进行下一个类的加载,如果没找到了就会回到委派的那个类加载器,即Extension ClassLoader

4.任务回到Exension ClassLoader,此时只能自己去搜索扩展库的类了。如果找到了这个类,就会进行下一个类的加载,如果没找到了就会回到委派的那个类加载器,即Application ClassLoader

5.任务回到Application ClassLoader,此时只能自己去搜索第三方库的类了。

如果找到了这个类,就会进行下一个类的加载,如果没找到了会抛出异常。

总结:双亲委派模型就是一个找.class文件的过程。平时如果我们创建一个跟标准库中名字一样的类,使用的时候依旧是标准库中的那一个,因为双亲委派模型机制,会优先使用标准库的类,这也是这个机制的意义。

类加载时机

类加载使用了懒汉模式,即当使用的时候才会进行加载。

大致可以分为三个时机:

  1. 构造类的实例

  2. 使用了类的静态方法/静态属性

  3. 子类的加载会触发父类

一旦类被加载好了,后续使用就不必再加载了,直接使用即可。

三、JVM垃圾回收机制

在C语言中使用malloc手动申请完内存后需要手动释放,如果光申请而不去释放的话,到达一定程度后,内存被耗尽,程序就会崩溃,但是通过程序猿来手动操作就非常考验个人水平了,无法保证可靠。

Java为了解决上述问题,就引入了垃圾回收机制,自动的把垃圾释放掉。

虽然这个垃圾回收(GC)这个机制非常香,但是也是需要付出代价的,即消耗额外的系统资源和性能开销,同时也出现STW问题。

STW问题:

Stop-The-World 简称 STW,是指在执行垃圾回收的过程冻结所有用户线程的运行,直到垃圾回收线程执行结束。

垃圾回收的主战场在堆区,进行垃圾回收需要两步:判断对象是否为"垃圾"; 释放对象的内存。

判断对象是否为"垃圾"

当一个对象,在后续代码中不会被继续使用了,即这个对象已经没有任何引用指向它了,就可以认为是垃圾了。

如何判断,有如下两种思路:引用计数和可达性分析

引用计数

核心思路:给每个对象里面安排一个计数器,每当有引用指向它的时候,就把计数器的值+1,每当引用被销毁,计数器的值-1.当计数器为0的时候,表示这个对象为垃圾。

优点:简单,好实现。

缺点:空间利用率低,浪费内存空间(当对象本身比较小的时候,会大大降低空间利用率);

​          存在循环引用问题,导致对象不能被正确识别为垃圾。如图:

此时对象A,B在外部已经没有人指向了,即此时我们无法通过代码再去操作A和B了,按理来说已经成为了垃圾,但此时他们的计数器都不为0,无法正确的被识别为垃圾。

在Java中没有使用这种方式,但在Python,PHP的虚拟机中就是使用了引用计数的方式来完成的

可达性分析

在Java中就采用了这个方案。

核心思路:JVM首先会从现有代码中的能直接访问到的引用出发,尝试遍历所有能访问的对象,只要对象能访问到,就会被标记为"可达"。完成整个遍历后,除开可达对象外,其它的也就是不可达对象,也就相当于是垃圾了。

优点:能够很好的解决引用计数中的循环引用问题。

缺点:需要消耗更多的时间。

释放对象内存

释放对象内存主要有三种方式:标记清除;复制算法;标记整理。

标记清除

标记清除是一种直接释放对象内存的方式。这种方式简单粗暴,但会遇到如下问题,即当GC对象是离散,空间不连续的时候:

此时如果直接释放对象的话,就会引起"内存碎片"。在申请内存空间的时候都是申请一块连续的内存,当使用标记清除直接释放的话,此时如果申请的内存空间比正GC对象大的话,就无法使用这块已经被回收的内存。

例如:假设上图中的每个GC对象的大小是1MB,但我们此时要申请一个2MB的内存空间,由于每个GC对象内存的前后的内存被占用了,我们就无法申请到空间.

复制算法

复制算法的核心思路是将空间分成两份,把有效对象复制到另一部分内存空间,来避免内存空间。

先是将左侧有效对象进行复制,放到右侧,然后再释放内存,当用了一段时间后,右侧也会有许多需要GC的对象,此时就将有效对象复制到左侧,循环往复。

虽然这种方式能有效的解决内存碎片问题,但当需要复制的对象内容比较多,就会引发不小的开销,并且由于会将内存进行划分,也会造成内存利用低的问题。

标记整理

标记整理是使用顺序表删除元素的思路。

每当要GC一个对象,会将后面的对象往前搬运。

这种方式,不仅可以解决内存碎片问题,也解决了内存利用率低的问题,但是会涉及频繁搬运的问题,这就会带来不小的开销。


分代回收

设计JVM的大佬集百家之长,搞了一个综合性的解决方法:分代回收。

分代回收是基于"一个对象存在的越久,那么它将继续存在的可能性就越高"的事实,然后对每个对象使用"年龄"标记,根据年龄来制定不同的回收策略。

分代回收将整个堆分成了两部分:新生代和老年代。在新生代中又划分了两个不同的区域:伊甸区和幸存区。

在新生代中以复制算法为主,在老年代中以标记整理算法为主。

伊甸区中存放的是新生的对象,在经过一轮的GC后,没有被回收的对象就会被通过复制算法,复制到幸存区中。

幸存区中又划分了两块不同的空间,用来针对后续的复制算法,当第二轮GC后,没有被回收的对象就会被复制到幸存区中另一块空间。

如果一个对象在幸存区中存活了好多轮都没有挂,这个对象的年龄就比较大了,就会被复制到老年代中。

在新生代中每一轮GC留下的对象并不会很多,所以进行复制算法的开销并不会很大,而在老年代中,对象比较重要,所以销毁的也很少,此时标记整理开销也不会很大。

相关文章:

JVM基础知识

一、JVM的内存区域划分 一个进程在运行的时候,会向操作系统申请到内存资源,从来存放程序运行的相关数据。 JVM本质上就是一个java进程,在运行的时候也会从操作系统那搞一块内存,供Java代码执行使用。 JVM又把申请的一块内存根据不同的用途划分出了不同区域。 每一…...

618网购节,电商能挡住恶意网络爬虫的攻击吗?

目录 爬虫盗取电商数据的步骤 电商平台如何发现网络爬虫? 如何拦截违法网络爬虫 2023年,杭州中院审结了两起涉及“搬店软件”的不正当竞争案件。本案的原告是国内某大型知名电子商务平台的运营主体,而被告则是开发了一款名为“某搬家快速商品…...

Codeforces Round 951 (Div. 2) C、D(构造、线段树)

1979C - Earning on Bets 构造题:观察到k范围很小,首先考虑最终硬币总数可以是多少,我们可以先假设最终的硬币总数为所有k取值的最小公倍数,这样只需要满足每个结果添加1枚硬币即可赚到硬币。 // Problem: C. Earning on Bets //…...

elmentUI el-table 总结行

背景 原因:表格展示的都是明细数据,需要对当前的明细数据的部分字段进行汇总难点:汇总的条件不一定,有时候客户查的是1天,有时候是10天 官方写法 只开启开关 开启汇总开关如果没有汇总方法, 会自动汇总所有…...

【大数据】计算引擎:Spark核心概念

目录 前言 1.什么是Spark 2.核心概念 2.1.Spark如何拉高计算性能 2.2.RDD 2.3.Stage 3.运行流程 前言 本文是作者大数据系列中的一文,专栏地址: https://blog.csdn.net/joker_zjn/category_12631789.html?spm1001.2014.3001.5482 该系列会成体…...

Python | C# | MATLAB 库卡机器人微分运动学 | 欧拉-拉格朗日动力学 | 混合动力控制

🎯要点 🎯正向运动学几何矩阵,Python虚拟机器人模拟动画二连杆平面机械臂 | 🎯 逆向运动学几何矩阵,Python虚拟机器人模拟动画三连杆平面机械臂 | 🎯微分运动学数学形态,Python模拟近似结果 | …...

Signac|成年小鼠大脑 单细胞ATAC分析(1)

引言 在本教程中,我们将探讨由10x Genomics公司提供的成年小鼠大脑细胞的单细胞ATAC-seq数据集。本教程中使用的所有相关文件均可在10x Genomics官方网站上获取。 本教程复现了之前在人类外周血单核细胞(PBMC)的Signac入门教程中执行的命令。…...

【POSIX】运行时so库动态加载

运行时可以自己自定义so库的动态加载框架&#xff0c;主动去加载某些库&#xff0c;并调用其中的某些方法 首先写一些方法&#xff0c;并生成so库 // hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容 */// 1. 使用extern // dlsym(handle, "hello&qu…...

爱普生SG2520CAA汽车电子中控专用晶振

随着汽车电子技术的飞速发展&#xff0c;汽车中控系统变得越来越智能化和复杂化。为了确保这些系统的高性能和高可靠性&#xff0c;选择符合AEC-Q200标准的高品质晶振至关重要。爱普生SG2520CAA晶振凭借其优异的特性&#xff0c;成为汽车电子中控系统的理想选择。 爱普生晶振SG…...

Vue——监听器简单使用与注意事项

文章目录 前言编写简单demo注意事项 前言 监听器&#xff0c;在官网中称为侦听器&#xff0c;个人还是喜欢称之为监听器。官方文档如下&#xff1a; vue 官网 侦听器 编写简单demo 侦听器在项目中通常用于监听某个属性变量值的变化&#xff0c;并根据该变化做出一些处理操作。…...

OpenCV的“画笔”功能

类似于画图软件的自由笔刷功能&#xff0c;当按住鼠标左键&#xff0c;在屏幕上画出连续的线条。 定义函数&#xff1a; import cv2 import numpy as np# 初始化参数 drawing False # 鼠标左键按下时为True ix, iy -1, -1 # 鼠标初始位置# 鼠标回调函数 def mouse_paint(…...

uniapp封装picker选择器组件,支持关键字查询

CommonPicker.vue组件 路径在 components\CommonPicker.vue <template><view><uni-easyinput v-model"searchQuery" :placeholder"placeholder" /><picker :range"filteredOptions" :range-key"text" v-model&…...

智慧城市的规划与实施:科技引领城市运行效率新飞跃

随着信息技术的飞速发展&#xff0c;智慧城市的构想正逐步成为现实。作为地理信息与遥感领域的研究者&#xff0c;我深知在这一转型过程中&#xff0c;技术的创新与应用是提升城市运行效率的关键。本文旨在探讨如何利用地理信息系统&#xff08;GIS&#xff09;、遥感技术、大数…...

Linux——内存管理代码分析

虚空间管理 页框和页的关系 页框 将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个页框&#xff0c;也叫页帧&#xff0c;即物理页面&#xff0c;是linux划分内存空间的结果。 每个页框都有一个页框号&#xff0c;即内存块号、物理块号。 页 将用户…...

手机自动化测试:4.通过appium inspector 获取相关app的信息,以某团为例,点击,搜索,获取数据等。

0.使用inspector时&#xff0c;一定要把不相关的如weditor啥的退出去&#xff0c;否则&#xff0c;净是事。 1.从0开始的数据获取 第一个位置&#xff0c;有时0.0.0.0&#xff0c;不可以的话&#xff0c;你就用这个。 第二个位置&#xff0c;抄上。 直接点击第三个启动。不要…...

个人项目———密码锁的实现

布局组件 布局效果 组件绑定 密码锁的实现代码 using TMPro; using UnityEngine; using UnityEngine.UI;public class PasswordPanel : MonoBehaviour {// public Button button;// 所有按键的父物体public Transform buttonPanel;// 输入字符串的文本框public TMP_Text input…...

关于Input【type=number】可以输入e问题及解决方案

一、为什么 因为在数学里e 代表无理数&#xff0c;e是自然对数的底数&#xff0c;同时它又是一个无限不循环小数&#xff0c;所以我们在输入 e 时&#xff0c;输入框会默认 e 是数字&#xff0c;从而没有对它进行限制。 二、解决方案 小提示&#xff1a;vue下监听事件需要加n…...

zabbix“专家坐诊”第241期问答

问题一 Q&#xff1a;华为交换机的100GE 1/0/1口的光模块收光值监测不到&#xff0c;有没有人碰到过这个问题呢&#xff1f;其他的端口都能监测到收光值&#xff0c;但是100GE 1/0/1口监测不到收光值。底层能查到&#xff0c;zabbix 6.0监控不到&#xff0c;以下是端口的报错信…...

了解Kubernetes-RKE2的PKI以及证书存放位置

一、什么是PKI&#xff1f; 简称&#xff1a;证书基础设施。 可以方便理解为当你的集群有Server,Client架构&#xff0c;那么为了安全加密之间的通信&#xff0c;则需要使用证书进行交互&#xff0c;那么利用PKI架构可以安全加密组件之间的通信。 二、Kubernetes的PKI架构什…...

利用大语言模型进行事实匹配

论文地址:Automated Claim Matching with Large Language Models: Empowering Fact-Checkers in the Fight Against Misinformation | Companion Proceedings of the ACM on Web Conference 2024 WWW 2024 Automated Claim Matching with Large Language Models: Empowering F…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...