JVM(面试用)

目录

一、JVM运行时数据区

二、JVM类加载

类加载过程

1、加载(loading)

2、验证(Verification)

3、准备(Perparation)

4、解析(Resolution)

5、初始化(Initialization)

双亲委派模型 

机制

优点

1、避免重复加载类

2、安全性

打破双亲委任模型

三、JVM中的垃圾回收机制

1、死亡对象的判断算法

1)引用计数算法

2)可达性分析算法

2、垃圾回收算法

1)标记-清除法

2)复制算法

3)标记-整理法

4)分代算法


JVM,Java Virtual Machine,Java虚拟机

虚拟机是指软件模拟的具有完整功能的、运行在一个完全隔离的环境中的完整计算机系统

常见的虚拟机:JVM、VMwave、Virtual Box

JVM和其他两个虚拟机的区别:

  1. VMware与VirtualBox是通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器
  2. JVM则是通过软件模拟Java字节码的指令集,JVM中则是主要保留了PC寄存器,其他的寄存器都进行了裁剪

JVM是一台被定制过的现实当中不存在的计算机

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

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

一、JVM运行时数据区

Java虚拟机运行时数据区是Java程序在运行过程中使用的内存区域,用于存储程序运行时所需要的数据

这些数据区包括了不同用途的内存区域,每个区域都有特定的作用和生命周期

注意它和Java内存模型(Java Memory Model,JMM)完全不同,属于完全不同的概念

其中堆和方法区都是线程共享的,Java虚拟机栈、本地方法栈、程序计数器是线程私有的

有自己的空间:别的线程也能访问;有自己私有的空间:别的线程无法访问

1、 堆(占据空间最大):存放程序中创建的对象

堆区分为两个区域:新生代和老生代,新生代放新建的对象,当经过一定GC次数之后还存活的对象会放入老生代

垃圾回收时会将Endn中存活的对象放到一个未使用的Survivor中,并把当前的Endn和正在使用的Survivor清除掉

2、Java虚拟机栈:存放方法之间的调用关系,描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息

Java虚拟机栈的生命周期和线程相同

  • 局部变量表:存放编译器可知的8大基本数据类型对象引用存放方法参数和局部变量
  • 操作栈:每个方法会生成一个先进后出的操作栈
  • 动态链接:每个方法会生成一个先进后出的操作栈
  • 方法返回地址:PC寄存器的地址

3、本地方法栈

本地方法栈和虚拟机栈类似,只不过Java虚拟机栈是给JVM使用的,而本地方法栈是给本地方法使用的(使用非Java语言编写的方法,如C、C++)

两种栈都是存放方法之间的调用关系

4、程序计数器:存放下一条要执行的指令的地址

5、方法区(元数据区):存储被虚拟机加载的信息、常量、静态变量、即时编译器编译后的代码等数据的(.class文件加载到内存之后就成了类对象,所以就是存放类对象)

运行常量池是方法区的一部分,存放字面量和字符引用

  • 字面量:字符串(JDK8移动到堆中)、final常量、基本数据类型的值
  • 符号引用:类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符
class Test{public int r=100;//成员变量r处于堆上public static int a=10;//静态变量(类属性)包含在类对象中,处在方法区(元数据区)void main(){Test t=new Test();//t是一个引用类型的局部变量,存放在栈的局部变量表中,存储一个对象的地址//new出来的对象在堆上}
}

二、JVM类加载

类加载过程

其中前五步是固定的顺序并且也是类加载的过程,其中中间的3步我们都属于连接,所以对于类加载来说总共分为一下几个步骤:加载、连接(验证、准备、解析)、初始化

1、加载(loading)

找到.class文件,打开文件,读取内容。将类的字节码数据从磁盘加载到内存中。这个过程是由类加载器完成的。在加载阶段,虚拟机需要完成一下三件事情:

  • 通过类的全限定名获取类的二进制字节流
  • 将字节流代表的静态存储结构转化为方法区的运行时数据结构
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
2、验证(Verification)

确保类的字节码文件符合虚拟机规范,不会危害虚拟机的运行时环境

主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证

3、准备(Perparation)

为类的静态变量分配内存并设置初始值(零值)

这里不包括final修饰的static变量,因为final在编译时就分配了初始值

4、解析(Resolution)

将常量池中的符号引用替换为直接引用的过程(初始化常量)

主要包括:类或接口的解析、字段解析、类方法解析、接口方法解析

5、初始化(Initialization)

Java虚拟机真正开始执行类中编写的Java程序代码,将主导权移交给应用程序

初始化阶段就是执行类构造器<clinit>()方法的过程,在初始化阶段,虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步,确保类的初始化只会进行一次

针对类对象进行初始化:设置好类对象中需要的各个属性、static成员变量、静态代码块、以及还可能加载一下父类

双亲委派模型 

双亲委派模型是和Java中多个类加载器(启动类加载器、扩展类加载器、应用程序类加载器)的运行规则,通过这个规则可以避免类的非安全性问题和类被重复加载的问题,但他也遇到了一些问题,比如JNDI和JDBC不能通过这个规则进行加载,它需要打破双亲委派模型的方式来加载

机制

如果一个类加载器收到了类加载的请求,它首先不会去尝试加载这个类,而是把这个请求委派给父类加载器去完成。

每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围没有找到需要的类)时,子加载器才会尝试自己去完成加载,如果能找到就返回对象,若直到应用程序类加载器都无法加载这个类,则抛出ClassNotFound异常

1)启动类加载器是由C++实现的,用于加载<JAVA_HOME>/jre/lib/rt.jar 和 resources.jar等jar包结构(即标准库的目录lib目录)

2)扩展类加载器用于加载<JAVA_HOME>/jre/lib/ext目录下的jre包(JDK中一些扩展库对应的目录,lib或ext目录)

3)应用类程序加载器用于加载classpath,也就是用户的所有类的(用户自定义的类和第三方库对应目录)

优点
1、避免重复加载类

比如A类和B类都有一个父类C类,那么当A启动时就会将C类加载起来,那么在B类进行加载时就不需要再重复加载C类了

2、安全性

当使用双亲委派模型时,用户就不能伪造一些不安全的系统类了。比如jre已经提供了String类在启动类加载时加载,那么用户若再自定义一个不安全的String类时,按照双亲委派模型就不会再加载用户自定义的那个不安全的String类了,这样就可以避免非安全的问题发生了

打破双亲委任模型

双亲委派模型虽然有其优点,但在某些也存在一些问题,比如Java中SPI(Service Provider Interface,服务提供接口)机制中的JDBC实现

tomcat中加载webapp时就是用的自定义的类加载器,就只能在webapp指定目录中查找,若在这里找不到就不会再去标准库啥的地方找了,直接抛异常

三、JVM中的垃圾回收机制

        在C++中,动态分配内存管理允许程序在运行时分配和释放内存,相比静态内存管理(编译时确定内存分配大小),动态管理内存提供了更大的灵活性和控制能力。

        C++中的动态内存管理通过new和delete关键字进行手动管理,同时智能指针提供了更安全和高效的方式来管理动态分配的内存,帮助开发者避免内存泄漏等问题。

        相比C语言中的malloc分配内存,new不仅分配内存还进行了初始化。

        Java也使用了new来进行动态内存管理,但相比之下Java给出了一个方案解决内存泄漏问题—垃圾回收机制(GC),即让JVM自行判定某个内存是否不再使用,若不再使用则回收,此时就不必程序员手动写代码回收。

上面讲了Java运行时内存的各个区域,对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭。

并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回收了。

因此讲内存分配何回收关注的是Java方法区这两个区域。

Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些存活,哪些已经“死去”,判断对象是否已经”死去“有如下几种算法:

1、死亡对象的判断算法
1)引用计数算法

每个对象都有一个引用计数器,记录着有多少个引用指向该对象。当引用计数器为0时,表示该对象不再被任何引用指向,即认为该对象是死亡的,可以被垃圾回收器回收

实现简单,对垃圾对象的回收比较及时;但是难以处理循环引用,会导致引用计数器无法归零,从而造成内存泄漏

2)可达性分析算法

通过一组称为”GC Roots"的根对象作为起始点,从这些根对象开始往下搜索,可达的对象被认为是存活的,不可达的对象则是被判断为死亡,可以被回收

GC Roots:包括线程栈(本地变量表)、静态变量、常量池中的引用,它们保证了对象之间的可达性链条

能够有效处理循环引用的问题,不会导致内存泄漏;但是相对于计数算法,实现和运行时开销较大

        在Java中,主流的垃圾回收器(如Serial, Parallel, CMS, G1等)通常使用可达性分析算法来判断对象的存活状态,这种算法能够更精确地确定不再使用的对象,从而安全有效地回收内存资源,提高程序性能和可靠性。

2、垃圾回收算法
1)标记-清除法

首先从根节点出发标记所有可达对象,再清除所有未标记对象(即不可达对象)

简单粗暴,适用于处理大对象和长时间存活的对象,但可能导致内存碎片化,影响内存分配效率

2)复制算法

将堆内存分为两块,每次只使用其中一块,当其中一块内存被占满时,将存活对象复制到另一块内存中,然后清除原内存中的所有对象

适用于处理短生命周期的对象,能够有效避免内存碎片化,但会消耗一定的内存空间

3)标记-整理法

类似于标记-清除法,但在清除阶段会将存活对象向一端移动,然后直接清除边界外的所有对象。这样可以保持存活对象的持续性,减少内存碎片化

适用于处理长时间存活对象和避免内存碎片化,但需要额外的移动存活对象的操作

4)分代算法

根据对象的存货周期将堆内存划分为不同的代,通常分为新生代和老生代。针对不同代使用不同的垃圾回收算法,如新生代使用复制算法,老生代使用标记-清除或标记-整理算法

充分利用对象的存活特性,提高垃圾回收效率,减少对整个内存的扫描次数

        在实际应用中,Java的垃圾回收器通常会根据应用程序的特性和运行环境的不同,结合多种垃圾回收算法,采用分代收集和并发收集等技术,以达到最佳的垃圾回收效果。不同的垃圾回收器(如Serial, Parallel, CMS, G1等)会选择不同的算法组合和优化策略,以满足不同的性能和响应时间需求。

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

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

相关文章

秒懂C++之deque及反向迭代器

目录 前言 一.deque的常用接口 二.deque的原理 2.1 vector与list的优缺点 2.2 deque的原理 三.反向迭代器 四.全部代码 前言 秒懂C之List-CSDN博客 秒懂C之vector&#xff08;下&#xff09;-CSDN博客 本文后面关于反向迭代器的操作会涉及到前面的文章~ 一.deque的常用接…

uni-app封装组件实现下方滑动弹出模态框

子组件 <template><div class"bottom-modal" :class"{show: showModal}"><div class"modal-content" :class"{show: showModal}"><!-- 内容区域 --><slot></slot></div></div></…

【JAVA多线程】AQS,JAVA并发包的核心

目录 1.概述 1.1.什么是AQS 1.2.AQS和BlockQueue的区别 1.3.AQS的结构 2.源码分析 2.1.CLH队列 2.2.模板方法的实现 2.2.1.独占模式 1.获取资源 2.释放资源 2.2.2.共享模式 1.概述 1.1.什么是AQS AQS非常非常重要&#xff0c;可以说是JAVA并发包&#xff08;java.…

案例开发-日程管理2第一期(超详细教程、配备图文和源代码注释,没学过也能看懂)

文章目录 一、 项目前期准备1.数据库准备2.导入依赖3.pojo包处理4.dao包处理5.service包处理6.controller包处理7.加密工具类的使用8.页面文件的导入 总结 一、 项目前期准备 1.数据库准备 创建schedule_system数据库并执行如下语句 SET NAMES utf8mb4; SET FOREIGN_KEY_CHE…

WPF学习(4)- VirtualizingStackPanel (虚拟化元素)+Canvas控件(绝对布局)

VirtualizingStackPanel虚拟化元素 VirtualizingStackPanel 类&#xff08;虚拟化元素&#xff09;和StackPanel 类在用法上几乎差不多。其作用是在水平或垂直的一行中排列并显示内容。它继承于一个叫VirtualizingPanel的抽象类&#xff0c;而这个VirtualizingPanel抽象类继承…

大数据-68 Kafka 高级特性 物理存储 日志存储概述

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Java之SpringBoot入门(含Spring Mvc)

1.Spring Boot Helper的安装 首先我们要装好Spring Boot Helper 但是由于直接在IDEA中下的是收费版&#xff0c;在学习阶段我们可以去官网下载一些免费版使用 Spring Boot Helper - IntelliJ IDEs Plugin | Marketplace&#xff08;点击即可进入官网&#xff09; 然后在IDEA…

【practise】删除有序数组中的重复项

关于博主&#xff1a; 今天分享一道简单的关于“双指针”算法的题目。算是双指针中非常基础的题目&#xff0c;有兴趣可以借鉴一波~ 目录 1.题目介绍2.题解思路&#xff1a;双指针法3.代码示例 1.题目介绍 题目链接&#xff1a;LINK 本题要求是&#xff1a;对给定的有序数组…

回溯分割+子集篇--代码随想录算法训练营第二十二天| 131.分割回文串,93.复原IP地址,78.子集,90.子集II

131.分割回文串 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 讲解视频&#xff1a;131.分割回文串 题目描述&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文串 。返回 s 所有可能的分割方案。 示例 …

sql二次注入实战--2018年网顶杯

网址&#xff1a;BUUCTF在线评测 (buuoj.cn) 当我们进入后显示这个页面&#xff1a; 当我们第一次点击发帖的时候就会跳转到登陆页面&#xff0c;上面有提示&#xff0c;告诉我们账号为zhangwei,密码为zhangwei***&#xff1a; 这里我们可以使用bp抓包工具来进行暴力破解密码&…

makefile举例说明

文章目录 makefile文件config.mk配置文件common.mk文件 目录结构 makefile文件 include config.mk导入config.mk的文件&#xff0c;通常包含项目的配置变量。 all:for dir in $(BUILD_DIR); \do \make -C $$dir; \doneall是项目主目标&#xff0c;遍历BUILD_DIR变量每个子目录…

基于springboot+vue+uniapp的“口腔助手”小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

Python开发: 飞机大战 小游戏

玩法 你可以控制飞机左右移动&#xff0c;躲避敌机子弹&#xff0c;同时发射自己的炮弹&#xff0c;将敌人击落&#xff01; 部署方案&#xff1a; 1、代码如下图&#xff1b; 2、将代码保存到一个python中&#xff0c;比如planeFight.py&#xff1b; 3、在你的电脑中安装p…

为什么需要云仓?

云仓&#xff0c;即云端仓储管理&#xff0c;是指通过互联网技术整合和管理仓储资源&#xff0c;实现高效、低成本的库存管理和物流服务。随着电子商务的发展和企业供应链全球化的加剧&#xff0c;云仓成为现代企业管理的一种重要手段。 1、云仓可以显著提高仓储管理效率&#…

算法测试.

一.CodeForces 1829A 题意&#xff1a; 题目意思就是给你t个字符串&#xff0c;让你找出每个串与codeforces这个串有多少不同的字母&#xff1b; 题解&#xff1a; 定义一个变量循环比较字符串&#xff0c;不相同计数即可&#xff1b; 代码&#xff1a; #include <iost…

SQL二次注入

目录 1.什么是二次注入&#xff1f; 2.二次注入过程 2.1寻找注入点 2.2注册admin#用户 2.3修改密码 1.什么是二次注入&#xff1f; 当用户提交的恶意数据被存入数据库后&#xff0c;因为被过滤函数过滤掉了&#xff0c;所以无法生效&#xff0c;但应用程序在从数据库中拿…

TCP Analysis Flags 之 TCP Window Full

前言 默认情况下&#xff0c;Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态&#xff0c;并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时&#xff0c;会对每个 TCP 数据包进行一次分析&#xff0c;数据包按照它们在数据包列表中出现的顺序进行处理。可…

supermap制作发布二三维地图服务

一、下载安装 软件版本&#xff1a; SuperMap iDesktopX 11i(2023) SP1 for Windows SuperMap iServer 11i(2023) SP1 for Windows 下载地址&#xff1a; http://support.supermap.com.cn/DownloadCenter/ProductPlatform.aspx 二、运行 服务端&#xff1a;双击iserver的…

C# Unity 面向对象补全计划 设计者模式 之 单例模式

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 本系列作为七大原则和设计模式的进阶知识&#xff0c;看不懂没关系 了解我的专栏C#面向对象与进阶:http://t.csdnimg.cn/mIitr&#xff0c;尤其是关于类的那篇文章即…

Python(模块---pandas+matplotlib+pyecharts)

import pandas as pd import matplotlib.pyplot as plt dfpd.read_excel(简易数据.xlsx) # print(df) plt.rcParams[font.sans-serif][SimHei] #设置画布的大小 plt.figure(figsize(10,6)) labelsdf[电影中文名] ydf[国籍] # print(labels) # print(y)# import pandas as pd im…