【Java八股】JVM
JVM
1. jvm内存区域分为哪些部分
线程私有的:程序计数器、虚拟机栈、本地方法栈
程序计数器:指示当前线程执行到的字节码文件的行号,是线程切换后保证线程能恢复到正确的执行位置的关键
虚拟机栈:用于存储方法调用的数据,由一个个栈帧组成,每个栈帧表示一个方法调用,包括局部变量表、操作数栈、动态链接、方法返回地址。其中局部变量表用于存储基本数据类型的局部变量和对象的引用,操作数栈用于存储中间计算结果,动态链接用于存储方法的符号引用,用于将符号引用转换为调用方法的直接引用。
线程共享的:堆、方法区、直接内存
堆:最大的一块内存区域,唯一目的就是存储对象实例,几乎所以对象实例都在这里分配内存(除了JIT逃逸分析后在栈上分配内存的)。另外堆中还包括字符串常量池。
方法区:JDK1.8以前,方法区是用堆中的永久代实现的,也就是在堆中分配内存,JDK1.8以后方法区是用元空间实现的,也就是在本地内存中。方法区中包括类信息、静态变量、运行时常量池。
直接内存:
2. 堆内存分为哪三个部分,对象是如何在堆中晋升的
新生代内存(Eden区、S0区、S1区)
老生代
永久代(用于实现方法区)
对象首先在Eden区分配内存,年龄为0;
一次垃圾回收后,如果对象还存活,就让它的年龄+1,并将它放在S0或S1;
此后每次垃圾回收后,如果对象还存活,就让它的年龄+1;
如果它的年龄达到15岁,就晋升到老年代。
另外大对象会直接进入老年代,大对象就是需要大量连续内存空间的对象,例如字符串,数组。
3. 运行时常量池是什么
运行时常量池用于存储编译期生成的各种字面量和符号引用
4. Java类加载的过程
1)加载
由类加载器完成,使用哪个类加载器取决于双亲委派模型。这一步骤主要完成了三件事:
根据类名找到二进制字节流;
将二进制字节流的静态存储结构转为方法区中的动态存储结构;
在内存中生成一个代表该类的class对象;
2)验证
确保二进制字节流的信息符合JVM规范
3)准备
为类变量分配内存并设置初始值;
4)解析
将符号引用替换为直接引用。(符号引用相当于仅有名称,不指向具体内存地址,符号引用存储在运行时常量池中,转换为直接引用,即内存实际地址后,才能进行具体访问操作)
5)初始化
执行类的初始化方法,即cinit方法
5. Java对象的创建过程
1)类加载检查
先检查该对象对应的类有没有被加载过,如果没有,先进行类加载过程;
2)分配内存
为对象分配足够的内存,所需内存大小在类加载完成后就可以确定。
分配方式有两种:
第一,指针碰撞
适用于堆内存规整的情况(即没有内存碎片)。用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可。
第二,空闲列表
虚拟机会维护一个列表,该列表中会记录哪些内存块是可用的,在分配的时候,找一块儿足够大的内存块儿来划分给对象实例,最后更新列表记录。(这种方式容易造成内存碎片)
3)初始化零值
将分配的内存区域都初始化为零
4)设置对象头
设置对象头信息,包括它属于哪个类、年龄是多少、哈希码是多少等信息。从这里可以看出来,对象的内存分为对象头、实例数据和对齐填充三部分。
5)执行init方法
6. 类加载器是什么,双亲委派模型是什么
类加载器是负责完成类加载的第一步:加载的。每个类都有一个classloader。
直白地说,类加载器就是负责将二进制字节码文件.class文件加载到JVM中,并生成一个class对象。
类加载时不会一次性加载所有的类,而是在用到该类的时候再动态地加载。
类加载器有三种:启动类加载器、扩展类加载器、应用程序类加载器。
启动类加载器是最顶层的加载类,用于加载JDK核心类库。
扩展类加载器用于加载jar包。
应用程序类加载器用于加载用户编写的类。
那么一个类到底由哪个类加载器去加载呢?这是由双亲委派模型指定的。
每个类加载器都有自己对应的父类加载器。
在classloader的loadClass方法中,双亲委派模型的执行流程如下:
1)首先检查该类是否被加载过,如果加载过,直接返回;
2)调用父类加载器的loadClass方法来加载类,这样根据类加载器的父子关系,所有请求最终会传递到顶层的启动类加载器;
3)当父类加载器反馈自己无法加载这个类时(即它没有搜索到这个类),子加载器就尝试自己加载;
4)如果子类加载器也无法加载这个类,就抛出异常;
为什么要使用双亲委派模型?
使用双亲委派模型是为了避免类的重复加载。如果不去调用父加载器的loadClass方法,而是每个类自己加载自己的话,那么如果两个类名字相同,就会出现类名相同但实际上不一样的两个类。
7. 死亡对象的判断方法
引用计数法
- 每当有一个地方引用它,计数器就加 1;
- 当引用失效,计数器就减 1;
- 任何时候计数器为 0 的对象就是不可能再被使用的。
这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间循环引用的问题。
可达性分析法:
用一系列GC Root作为起点,构建对象的引用链。当进行可达性分析时,从GC Root开始向下搜索,走过的对象即有引用的对象。
而如果从GC Root无法到达对象,就认为此对象是不可用的,需要被回收。
8. 对象的引用类型有哪些
强引用:绝不会被垃圾回收,当JVM内存不足时,即使抛出OOM也不会回收
软引用:可有可无,JVM内存不足时可能会被回收,JVM内存足够就不会被回收
弱引用:只有弱引用的对象,被JVM发现了就会被回收,不管内存是否足够
虚引用:形同虚设,跟没有引用一样,随时可能被回收
9. 如何判断一个常量是废弃常量
假如在字符串常量池中存在字符串 “abc”,如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量,如果这时发生内存回收的话而且有必要的话,“abc” 就会被系统清理出常量池了。
10. 如何判断一个类是无用的类,从而发生类卸载?
类卸载即类的class对象被垃圾回收。
类卸载的条件是:
1)该类的所有实例对象都已经被回收;
2)该类没有在其他任何地方被引用;
3)该类的加载器已经被回收;
11. JVM垃圾回收算法有哪些
1)标记清除算法
标记出所有不需要回收的对象,然后统一回收掉所有没有被标记的。
缺点:效率不高;会产生内存碎片;
2)复制算法
每次仅使用内存区域的一半,这一半使用完后将还存活的对象复制到另一半去,然后将这一半的全部空间清理掉。
缺点:可用内存空间变成了原来的一半,如果对象很大,复制会耗费大量时间。
3)标记整理算法
将存活的对象向一端移动,然后直接清理掉边界以外的全部内存。
缺点:因为要整理,效率也不高,适合老年代这种垃圾回收频率不是很高的场景。
4)分代收集算法
当前虚拟机的垃圾收集都采用分代收集算法,即根据新生代、老年代等分代,选择不同的垃圾收集算法。对于新生代,GC频率比较高、对象占用内存也不是很多的情况,可以选择复制算法。对于老年代,存活几率比较高,可以选择标记清除或者标记整理算法。
实际上JVM之所以对对象进行分代,也是为了垃圾回收时能够根据不同代对象的特点选择合适的算法。
12. 垃圾回收器有哪些
1)Serial串行收集器
历史最悠久的,单线程的,新生代标记复制算法,老生代标记整理算法
2)Serial Old
Serial收集器的老年代版本
3)并行收集器ParNew
其实就是Serial的多线程版本,仍然是新生代标记复制算法,老生代标记整理算法
4)Parallel Scavenge
JDK1.8采用的收集器。同样新生代标记复制算法,老生代标记整理算法,且为多线程。但提供了很多参数帮助用户实现最大吞吐量。
5)Parallel Old
Parallel Scavenge的老年代版本
6)CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。
7)G1收集器
G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。
12. JVM常用的参数有哪些
指定堆内存大小:-Xms用于指定最小堆内存大小,-Xmx用于指定最大堆内存大小
指定新生代内存:-XX:NewSize最小新生代内存, -XX:MaxNewSize最大新生代内存,-Xmn直接指定新生代内存大小,另外还可以通过-XX:NewRation指定新生代老生代内存比例
指定元空间大小:-XX:MetaspaceSize、-XX:MaxMetaspaceSize
选择垃圾回收器:-XX:+UseSerialGC选择串行收集器、-XX:+UseParallelGC选择并行收集器、-XX:+UseConcMarkSweepGC选择CMS收集器、-XX:+UseG1GC选择G1收集器
还有一些打印日志的参数:
-XX:+PrintGCDetails 打印GC信息
-XX:+PrintGCDateStamps 打印GC信息
-XX:+PrintTenuringDistribution # 打印对象分布
-XX:+PrintHeapAtGC # 打印堆数据
相关文章:
【Java八股】JVM
JVM 1. jvm内存区域分为哪些部分 线程私有的:程序计数器、虚拟机栈、本地方法栈 程序计数器:指示当前线程执行到的字节码文件的行号,是线程切换后保证线程能恢复到正确的执行位置的关键 虚拟机栈:用于存储方法调用的数据&…...
集成学习(一):从理论到实战(附代码)
一、引言 在机器学习领域,打造一个独立、强大的算法是解决问题的关键。然而,集成学习提供了一种不同的视角:通过组合多个“弱”学习器来创建一个更强大的模型。本文探讨集成学习的思想、方法及其应用。 二、机器学习 vs 集成学习思想 传统…...
Netty:高性能网络应用框架的深度解析
引言 Netty 是由 JBoss 提供的一个开源的 Java NIO 客户端/服务器框架,它用以快速开发网络应用程序,如协议服务器和客户端。它的设计目标是提供异步事件驱动的网络应用程序框架,支持高效的网络通信和数据处理。Netty 在性能、可扩展性、安全…...
神经网络常见激活函数 3-ReLU函数(修正线性单元)
文章目录 ReLU函数求导函数和导函数图像优缺点pytorch 中的 ReLU 函数tensorflow 中的ReLU函数 ReLU 修正线性单元 (Rectified Linear Unit) 函数求导 ReLU函数 ReLU max ( 0 , x ) { x x ≥ 0 0 x < 0 \begin{aligned} \operatorname{ReL…...
Android开发获取缓存,删除缓存
Android开发获取缓存,删除缓存 app设置中往往有清理缓存的功能。会显示当前缓存时多少,然后可以点击清理缓存 直接上代码: object CacheHelper {/*** 获取缓存大小* param context* return* throws Exception*/JvmStaticfun getTotalCache…...
如何通过PHP接入DeepSeek的API
想知道如何通过PHP接入DeepSeek的API。看起来他对之前的Python步骤比较熟悉,但这次想用PHP实现。 首先,我需要回顾一下DeepSeek API的文档,确认它支持哪些方法和参数。假设用户已经配置了环境变量,比如API密钥,接下来…...
一种基于Leaflet.Legend的图例动态更新方法
目录 前言 一、场景再现 1、需求描述 2、核心方法介绍 3、存在的问题 二、问题解决 1、重复解决办法 2、图例不展示解决办法 3、成果展示 三、总结 前言 在当今数字化时代,地理信息系统(GIS)技术已经广泛应用于各个领域,…...
Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ
Spring Boot: 使用 Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ 在微服务架构中,确保消息的可靠性和一致性非常重要,尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchron…...
LQB(2)-python-枚举
前言 python中的枚举一般有两个说法,一个是枚举算法(暴力求解法,算法层面),一个是遍历使用enumerate()函数或者enum模块创建()。 暴力求解法在之前的博文里面讲过了👇,…...
MongoDB开发规范
分级名称定义P0核心系统需7*24不间断运行,一旦发生不可用,会直接影响核心业务的连续性,或影响公司名誉、品牌、集团战略、营销计划等,可能会造成P0-P2级事故发生。P1次核心系统这些系统降级或不可用,会间接影响用户使用…...
为什么DeepSeek服务器繁忙?
致敬DeepSeek 用户层面 用户数量激增:DeepSeek 免费且功能强大,对普通用户和开发者都极具吸引力124。尤其是在新功能推出、新模型上线或相关热门活动期间,大量用户会在短时间内涌入9。例如春节期间,DeepSeek 的用户量达到四千万7。…...
律所录音证据归集工具:基于PyQt6与多线程的自动化音频管理解决方案
在律所日常工作中,音频证据的整理与归集是一个高频且复杂的任务。面对大量的案件录音文件,如何实现快速且准确的分类与存档,成为了律所提高效率、降低出错率的关键。本文将通过技术角度解析一款名为律所录音证据归集工具的项目,详…...
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue旅游管理网站
开题报告 本论文探讨了一款采用现代Web开发技术构建的台州市旅游综合信息与服务平台的设计与实现。该系统基于SpringBoot框架,以其轻量级、快速开发和强大的企业级应用支持能力为核心后端技术支撑,结合Vue.js前端框架及ElementUI组件库,为用…...
unity碰撞的监测和监听
1.创建一个地面 2.去资源商店下载一个火焰素材 3.把procedural fire导入到自己的项目包管理器中 4.给magic fire 0 挂在碰撞组件Rigidbody , Sphere Collider 5.创建脚本test 并挂在magic fire 0 脚本代码 using System.Collections; using System.Collections.Generic; usi…...
DeepSeek-R1 32B Windows+docker本地部署
最近国产大模型DeepSeek兴起,本地部署了一套deepseek同时集成Open WebUI界面,给大家出一期教程。 软件:Ollama、docker、Open WebUI 一、用Ollama下载模型 首先我们需要安装Ollama,它可以在本地运行和管理大模型。 到Ollama官网 https://ol…...
C++11新特性之unique_ptr智能指针
本节继续介绍智能指针,不了解的读者可以先阅读——C11新特性之shared_ptr智能指针-CSDN博客 1.介绍 unique_ptr是C11标准提供的另一种智能指针。与shared_ptr不同的是,unique_ptr指针指向的堆内存无法同其他unique_ptr共享,也就是每一片堆内…...
Vue与Konva:解锁Canvas绘图的无限可能
前言 在现代Web开发中,动态、交互式的图形界面已成为提升用户体验的关键要素。Vue.js,作为一款轻量级且高效的前端框架,凭借其响应式数据绑定和组件化开发模式,赢得了众多开发者的青睐。而当Vue.js邂逅Konva.js,两者结…...
python绘图之柱状堆积图的绘制
本节来学习用python来绘制柱状堆积图. 使用的库为matplotlib.pyplot,numpy 代码如下 # 导入必要的库 import matplotlib.pyplot as plt # 用于绘图 import numpy as np # 用于数值计算# 模拟一些数据 x [数值{}.format(i) for i in range(10)] # 创建一个包含10个元素的列…...
剪辑学习整理
文章目录 1. 剪辑介绍 1. 剪辑介绍 剪辑可以干什么?剪辑分为哪些种类? https://www.bilibili.com/video/BV15r421p7aF/?spm_id_from333.337.search-card.all.click&vd_source5534adbd427e3b01c725714cd93961af 学完剪辑之后如何找工作or兼职&#…...
DeepSeek从入门到精通:全面掌握AI大模型的核心能力
文章目录 一、DeepSeek是什么?性能对齐OpenAI-o1正式版 二、Deepseek可以做什么?能力图谱文本生成自然语言理解与分析编程与代码相关常规绘图 三、如何使用DeepSeek?四、DeepSeek从入门到精通推理模型推理大模型非推理大模型 快思慢想&#x…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...
