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留下的对象并不会很多,所以进行复制算法的开销并不会很大,而在老年代中,对象比较重要,所以销毁的也很少,此时标记整理开销也不会很大。

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

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

相关文章

酷我音乐 v10.8.2.1 解索SVIP版,畅享无界音乐盛宴!

酷我音乐 v10.8.2.1 解索SVIP版 酷我音乐,一款多功能音乐软件,集成了音乐播放、歌曲下载、歌词同步、在线电台等多项服务。该应用致力于提供高品质的音乐欣赏体验和独特的音乐探索机会,无论用户身处何地。此外,它还支持大量付费高…

eNSP学习——配置RIP抑制接口及单播更新

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、搭建基础的RIP网络 3、配置RIP抑制接口,优化公司网络 4、配置RIP单播更新,恢复网络通信 5、验证另一种抑制接口方式 需要eNSP各种配置命令的点击链接自取&#xf…

day52 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV

123.买卖股票的最佳时机III 关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。 动态规划五部曲 1.确定dp数组以及下标的含义 一天一共就有五个状态, 没有操作 (其实我们也可以不设置这个状态&a…

Docker 国内镜像源更换

实现 替换docker 镜像源 前提要求 安装 docker docker-compose 参考创建一键更换docker国内源 vim /docker_daemon.sh #!/bin/bash # -*- coding: utf-8 -*- # Author: make.han # Email: CIASM@CIASM # Date: 2024/06/07 # docker daemon.jsondaemon_json_file="/et…

[网络基础]——计算机网络(OSI)参考模型 详解

🏡作者主页:点击! 🌐网络通信基础TCP/IP专栏:点击! ⏰️创作时间:2024年6月2日21点59分 🀄️文章质量:93分 目录 🎟️OSI基本概念 🎄分层架构…

使用Qt实现文本文件的读写操作

文章目录 文本读写简介QFileDialog简介常用方法示例代码 QFile简介常用方法示例代码 QTextStream简介常用方法示例代码 结合使用示例完整示例代码(读写操作,可直接复制运行我使用的Qt版本为QT5.14)mainwindow.hmainwindow.cppmain.cpp代码解释 文本读写简介 在现代…

前端经典面试手写题

前端面试中常会遇到的手写题主要考察应聘者对前端基础知识的掌握程度以及编程能力。以下是一些经典的前端手写题及其解答思路: 手写深拷贝(Deep Clone) 深拷贝是指复制一个对象及其所有子对象,使得新的对象和原对象完全独立。 …

聊聊DoIP吧(二)-报文结构和时间参数

书接上回,DoIP报文及其在以太网帧中的位置:图片来自Vector官网 这里我们来看看DoIP报文结构: DoIP协议时间参数详解 - 知乎 (zhihu.com)

实验三-8086指令的应用《计算机组成原理》

一、实验目的 掌握8086指令的应用 二、实验原理 三、实验仪器 计算机1台,emu8086软件。 四、实验步骤 1、建立00H~0FH~00H 31个数,00H~0FH数据逐渐增大,0FH~00H逐渐减小,即DI指针所表示的地…

linux进程间通讯指南-打通IPC大门,高效沟通无阻

在现代操作系统中,进程就像独立的个体,有时需要相互合作、数据共享,这就要求进程间能够高效通信。本文将为你揭开Linux进程间通信(IPC)的神秘面纱,探讨各种IPC工具的运作原理,同步机制的重要性,以及如何规避…

手动安装Nvidia驱动和CUDA Toolkit

1、打开cuda-toolkit 网站 CUDA Toolkit Archive | NVIDIA Developer 根据自己需要选择CUDA Toolkit版本,这里选择12.0.0 2、点击链接跳转到下载页面,选择操作系统类型和安装包类型 3、下载CUDA Toolkit 安装包 4、执行下载命令 wget https://develo…

【C语言】学生管理系统:完整模拟与实现

🌈个人主页:是店小二呀 🌈C语言笔记专栏:C语言笔记 🌈C笔记专栏: C笔记 🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅 🔥引言 本篇文章为修改了在校期间实训报告,使用C…

停止一个正在运行的线程

暴力停止方法 stop 该方法是不安全的,已经过时的方法,在其方法描述上 This method is inherently unsafe,这个方法实际上是不安全的 package com.alibaba.fescar.core.protocol.test;public class TestThreadStop {public static void main(S…

基于STM32开发的智能水族箱管理系统

目录 引言环境准备智能水族箱管理系统基础代码实现:实现智能水族箱管理系统 4.1 温度传感器数据读取4.2 水泵与加热器控制4.3 水位传感器数据读取4.4 用户界面与显示应用场景:水族箱管理与优化问题解决方案与优化收尾与总结 1. 引言 智能水族箱管理系…

day51 动态规划 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 动态规划 1.确定dp数组(dp table)以及下标的含义 dp[i][0] 表示第i天持有股票所得最多现金 ,这里可能有同学疑惑,本题中只能买卖一次,持有股票之后哪还有现金呢? 其实一开始现…

我们正迈向万物互联

物联网(Internet of Things,IoT)是近年来信息技术领域最引人注目的创新之一。它通过将物理世界与数字世界紧密相连,为我们的日常生活、工业生产、城市管理等多个领域带来了前所未有的变革。本文将深入探讨物联网的基本概念、技术原…

Java 18 新功能概述

Java 18 在 2022 年 3 月 22 日正式发布,Java 18 不是一个长期支持版本。 包含多项新特性和改进,如文件系统链接、文本块、表达式求值API、ForkJoinPool优化、Optional新方法等。 亮点还包括预览特性:Record Pattern Matching for Switch和增…

C++ - 查找算法 和 其他 算法

目录 一. 查找算法: 1.顺序查找: 2.二分查找: 二. 其他算法: 1.遍历算法: 2.求和、求平均值等聚合算法。 a.求和算法: b.求平均值算法: 一. 查找算法: 1.顺序查找&#xff1…

Python深度学习基于Tensorflow(15)OCR验证码 文本检测与识别实例

文章目录 文本检测文本识别CTC层生成验证码并制作数据集建立模型模型推理 参考 文本检测 文本检测和目标检测类似,其不同之处在于文本目标具有序列特征,有连续性,可以通过结合 Faster R-CNN 和 LSTM 的方式进行文本检测,如 CTPN …

学习请求接口

axios的方法 方法一 方法二 方式三 方式四 ajax请求 fetch请求 学习一下