久违的重新写了一篇面试汇总的,关于JVM的一篇,一共三篇,今天写了第一篇,继续重新学习,重新卷起来,come on baby
1.什么情况下会触发类的初始化?

(1)首先是类未被初始化时,创建类的实例(new 的方式),访问某个类或接口的静态变量,或者对该静态变量赋值,调用类的静态方法。
(2)对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
(3)如果在初始化某一个类时候,其父类没有被初始化时候,则会触发父类的初始化。
(4)当咱们打的jar包,在执行完java -jar命令后,用户需要指定一个要执行的主类(包含 main() 方法的那个类,例如SpringBoot的那个启动类的main方法,非SpringBoot的,咱们自己手动打包的一般在MANIFEST.MF文件中指定),虚拟机会先初始化这个主类。
(5)JDK 1.7新增了一种反射方式java.lang.invoke.MethodHandle,通过实MethodHandle同样是访问静态变量,对该静态变量赋值,调用类的静态方法,前提仍然是该类未被初始化。

2.谈谈你对解析与分派的认识。

(1)解析调用是将那些在编译期就完全确定,在类加载的解析阶段就将涉及的符号引用全部转变为可以确定的直接引用,不会延迟到运行期再去完成。
(2)分派又分为静态分派和动态分派
(3)静态分派:同样是将编译期确定的调用,重载(Oveload)就是这种类型,在编译期通过参数的静态类型(注意不是实际类型)作为判断依据,找到具体的调用的方法。

public class TestOverLoad {public static void main(String[] args) {//静态类型都是Parent,实际类型分别是Sun和DaughterParent sun = new Sun();Parent daughter = new Daughter();TestOverLoad test = new TestOverLoad();//输出结果按照静态类型执行test.testMethod(sun);test.testMethod(daughter);}static abstract class Parent { }static class Sun extends Parent { }static class Daughter extends Parent { }public void testMethod(Parent parent) {System.out.println("hello, Parent");}public void testMethod(Sun sun) {System.out.println("hello, Sun");}public void testMethod(Daughter daughter) {System.out.println("hello, Daughter");}
}//输出
hello, Parent
hello, Parent

(4)动态分派:运行期根据实际类型确定方法执行版本的分派过程称为动态分派。重写(Override),在运行时期,通过判断实体的真实类型,判断具体执行哪一个方法。

public class TestOverride {public static void main(String[] args) {//静态类型都是Parent,实际类型分别是Sun和DaughterParent sun = new Sun();Parent daughter = new Daughter();//这时候输出结果按照实际类型找到方法sun.testMethod();daughter.testMethod();}static abstract class Parent {public void testMethod() {System.out.println("hello, Parent");}}static class Sun extends Parent {@Overridepublic void testMethod() {System.out.println("hello, Sun");}}static class Daughter extends Parent {@Overridepublic void testMethod() {System.out.println("hello, Daughter");}}
}
//输出
hello, Sun
hello, Daughter
3.Java类加载器包括⼏种?它们之间的⽗⼦关系是怎么样的?双亲委派机制是什么意思?有什么好处?

(1)启动类加载器(Bootstrap ClassLoader),由C语言编写的。负责把<JAVA_HOME>\lib目录中的类库加载到虚拟机内存中。
(2)扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.LauncherExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。 (3)应用程序类加载器(Application ClassLoader):这个类加载器由sun.misc.LauncherApp-ClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
(4)自定义类加载器。下面是自定义类加载器的方式,这个有几点注意,TestDemo编译出来class,把class复制到idea或者eclipse生成target目录之外,因为需要删除掉TestDemo.java,这样target下的class可能也自动没有了,另外如果不删除TestDemo.java会导致一直输出默认的应用程序加载器,因为你运行环境里有,双亲委派的应用程序加载器能找TestDemo,所以默认用父类的了,所以必须删除掉。

package test;public class TestDemo {private String name;public TestDemo(){}public TestDemo(String name){this.name = name;}public String getName(){return name;}public void setName(String name){this.name = name;}public String toString(){return "Demo name is " + name;}
}
package test;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;public class TestMyClassLoader extends ClassLoader
{public TestMyClassLoader(){}public TestMyClassLoader(ClassLoader parent){super(parent);}protected Class<?> findClass(String name) throws ClassNotFoundException{File file = getClassFile(name);try{byte[] bytes = getClassBytes(file);Class<?> c = this.defineClass(name, bytes, 0, bytes.length);return c;}catch (Exception e){e.printStackTrace();}return super.findClass(name);}private File getClassFile(String name){//重点是这个路径,在本地编译好TestDemo后,把class放在一个其他路径下//不要默认用idea或者eclipse的target路径//注意运行这个类之前把代码的TestDemo.java删除掉或者注释掉//否则怎么运行都是默认的加载器AppClassLoaderFile file = new File("/Users/buxuesong/TestDemo.class");return file;}private byte[] getClassBytes(File file) throws Exception{// 这里要读入.class的字节,因此要使用字节流FileInputStream fis = new FileInputStream(file);FileChannel fc = fis.getChannel();ByteArrayOutputStream baos = new ByteArrayOutputStream();WritableByteChannel wbc = Channels.newChannel(baos);ByteBuffer by = ByteBuffer.allocate(1024);while (true){int i = fc.read(by);if (i == 0 || i == -1)break;by.flip();wbc.write(by);by.clear();}fis.close();return baos.toByteArray();}public static void main(String[] args) throws Exception{TestMyClassLoader mcl = new TestMyClassLoader();Class<?> c1 = Class.forName("test.TestDemo", true, mcl);Object obj = c1.newInstance();System.out.println(obj);System.out.println(obj.getClass().getClassLoader());}
}
//输出
Demo name is null
test.TestMyClassLoader@5cad8086
//如果没删除TestDemo.java输出
Demo name is null
sun.misc.Launcher$AppClassLoader@18b4aac2

(5)扩展类加载器的父类是启动类加载器,应用程序类加载器的父类是扩展类加载器,自定义类加载器的父类是应用程序类加载器。
(6)双亲委派机制:除了启动类加载器,其余加载器都应该有自己的父类加载器,当一个类加载器需要加载某个类时,默认把这个累交给自己的父类去加载,只有当父类无法加载这个类时候(它的搜索范围中没有找到所需的类),自己才去加载,按照这个规则,所有的累加载最终都会到启动类加载器过一遍。
(7)双亲委派实际上保障了Java程序的稳定运作,因为随着这种父类关系自带了一种层级关系,按照层级关系来分别加载,如果不按照顺序各个加载器自行加载,用户如果自己写了一个java. lang.Object的类,系统会出现多个Object类,导致整个java体系无法运转。

4.如何⾃定义⼀个类加载器?你使⽤过哪些或者你在什么场景下需要⼀个⾃定义的类加载器吗?

(1)这问题问了我上面的,我在写一遍,自定义类加载器,有几点注意,TestDemo编译出来class,把class复制到idea或者eclipse生成target目录之外,因为需要删除掉TestDemo.java,这样target下的class可能也自动没有了,另外如果不删除TestDemo.java会导致一直输出默认的应用程序加载器,因为你运行环境里有,双亲委派的应用程序加载器能找TestDemo,所以默认用父类的了,所以必须删除掉。

package test;public class TestDemo {private String name;public TestDemo(){}public TestDemo(String name){this.name = name;}public String getName(){return name;}public void setName(String name){this.name = name;}public String toString(){return "Demo name is " + name;}
}
package test;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;public class TestMyClassLoader extends ClassLoader
{public TestMyClassLoader(){}public TestMyClassLoader(ClassLoader parent){super(parent);}protected Class<?> findClass(String name) throws ClassNotFoundException{File file = getClassFile(name);try{byte[] bytes = getClassBytes(file);Class<?> c = this.defineClass(name, bytes, 0, bytes.length);return c;}catch (Exception e){e.printStackTrace();}return super.findClass(name);}private File getClassFile(String name){//重点是这个路径,在本地编译好TestDemo后,把class放在一个其他路径下//不要默认用idea或者eclipse的target路径//注意运行这个类之前把代码的TestDemo.java删除掉或者注释掉//否则怎么运行都是默认的加载器AppClassLoaderFile file = new File("/Users/buxuesong/TestDemo.class");return file;}private byte[] getClassBytes(File file) throws Exception{// 这里要读入.class的字节,因此要使用字节流FileInputStream fis = new FileInputStream(file);FileChannel fc = fis.getChannel();ByteArrayOutputStream baos = new ByteArrayOutputStream();WritableByteChannel wbc = Channels.newChannel(baos);ByteBuffer by = ByteBuffer.allocate(1024);while (true){int i = fc.read(by);if (i == 0 || i == -1)break;by.flip();wbc.write(by);by.clear();}fis.close();return baos.toByteArray();}public static void main(String[] args) throws Exception{TestMyClassLoader mcl = new TestMyClassLoader();Class<?> c1 = Class.forName("test.TestDemo", true, mcl);Object obj = c1.newInstance();System.out.println(obj);System.out.println(obj.getClass().getClassLoader());}
}
//输出
Demo name is null
test.TestMyClassLoader@5cad8086
//如果没删除TestDemo.java输出
Demo name is null
sun.misc.Launcher$AppClassLoader@18b4aac2

(2)我们之前写的获取数据库连接,通过class.forname去加载数据库驱动。以及热加载这种方式,咱们修改了java文件,但是tomcat没有手动重启,这个时候有一个能够监控到java有变化重新编译了的情况,通过线程出发tomcat重启,就达到了热加载的机制。还有就是apk加密的方式,打包时候,源码-》class-》加密-》打成jar包-》安装-》运行-》classLoader解密-》classLoader加载-》用户使用app,这样只有实现解密方法的classloader才能正常加载,其他的classLoader无法运行。

5.堆内存设置的参数是什么?

(1)-Xms初始堆内存大小
(2)-Xmx最大堆内存大小,生产环境中,JVM的Xms和Xmx建议设置成一样的,能够避免GC时还要调整堆大小。
(3)-XX:NewSize=n,设置年轻代大小-XX:NewRatio=n设置年轻代和年老代的比值。如:-XX:NewRatio=3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4,默认新生代和老年代的比例=1:2
(4)-XX:SurvivorRatio=n,设置年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个,默认是8,表示Eden:S0:S1=8:1:1如:-XX:SurvivorRatio=3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5。
(5)-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath,这两个是设置但程序OOM后,输出Dump文件以供分析原因的,但是对于目前的K8s的情况,这俩没什么用,OOM之后,K8s发现服务没响应,直接kill了,然后重启一个新的,OOM根本就来不及生成,因为生成文件耗时较多,K8s杀的很快。
(6)-Xss128k 设置每个线程的堆栈大小。
(7)-XX:+PrintGCDetails,输出GC日志。

感谢各位的阅读,帮忙点赞,感谢各位。
最后编辑于:2025-06-22 10:05:52


喜欢的朋友记得点赞、收藏、关注哦!!!

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

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

相关文章

Agent中的memory

rag系列文章目录 文章目录rag系列文章目录前言一、Memory机制作用二、memory分类三、langgraph实践总结前言 众所周知&#xff0c;大模型是无状态的。但是基于大模型的agent一般是有状态的&#xff0c;也就是它有记忆功能。在AI Agent框架中&#xff0c;Memory机制是核心组件之…

AI与IT从业者的未来:替代焦虑还是协作革命?

​​引言&#xff1a;技术渗透与核心命题​​2025年&#xff0c;人工智能技术已从实验室走向产业核心。国务院《关于深入实施“人工智能”行动的意见》推动AI在医疗、制造、金融等领域的规模化落地&#xff0c;全球AI应用用户规模突破2.3亿&#xff0c;生成式AI工具渗透率达16.…

手机版碰一碰发视频系统批量剪辑功能开发,支持OEM贴牌

引言在当今短视频盛行的时代&#xff0c;视频内容的快速生产与分享变得愈发重要。手机版碰一碰发视频系统&#xff0c;借助 NFC 等近场通信技术&#xff0c;实现了便捷的数据交互与视频分享&#xff0c;而在此基础上集成的批量剪辑功能&#xff0c;更是为内容创作者和商家带来了…

Spring AMQP如何通过配置文件避免硬编码实现解耦

在使用Spring AMQP基于注解声明监听者时&#xff0c;可通过抽取常量来避免硬编码&#xff1a;RabbitListener(bindings QueueBinding(exchange Exchange(MQConstant.USER_EXCHANGE),value Queue(MQConstant.USER_QUEUE),key MQConstant.USER_REDIS_BINDING))public void de…

解决zabbix图片中文乱码

要把 Zabbix 前端字体替换为 simkai.ttf&#xff08;楷体&#xff0c;解决乱码常用&#xff09;&#xff0c;按以下步骤操作&#xff1a;1. 确认 simkai.ttf 路径 先找到系统里 simkai.ttf 字体文件&#xff0c;若没有&#xff0c;可从 Windows 系统&#xff08;C:\Windows\Fon…

实例分割-动手学计算机视觉13

介绍 实例分割(instance segmentation)的目的是从图像中分割出每个目标实例的掩模(mask)。与语义分割相比&#xff0c;实例分割不但要区分不同的类别&#xff0c;还要区分出同一种类别下的不同目标实例。如图13-1所示 语义分割的结果中&#xff0c;不同的羊对应的标签是一样的…

水环境遥感分析!R语言编程+多源遥感数据预处理;水体指数计算、水深回归分析、水温SVM预测、水质神经网络建模及科研级可视化制图

系统性地整合R语言编程、遥感数据处理及机器学习建模&#xff0c;涵盖水线提取&#xff08;水体指数与阈值法&#xff09;、水深反演&#xff08;多元回归&#xff09;、水温预测&#xff08;支持向量机&#xff09;、水质评估&#xff08;神经网络&#xff09;等核心内容&…

微信公众号/小程序百万级OpenID自动化获取工具

摘要 本报告详细阐述了微信用户列表数据获取与处理工具的设计思路,包括分页处理机制、频率控制策略、断点续传功能和分布式存储方案。针对微信API调用限制和用户数据规模特点,该工具旨在高效、安全地获取和存储微信用户列表数据,同时严格遵守微信API调用频率限制,确保系统…

物联网系统中传感器到网关到物联网平台的传输路径、协议、原理、用途与架构详解

摘要物联网&#xff08;IoT&#xff09;系统通过传感器、网关和物联网平台实现数据的采集、传输、处理和应用。本文详细分析了传感器到网关再到物联网平台的传输路径&#xff0c;涵盖直接连接、网关中继、边缘计算、多级网关和混合路径五种方式&#xff1b;介绍了短距离&#x…

SpringBoot自动注入配置类初步实现

一.SpringBoot自动装配SpringBoot 的 自动装配&#xff08;Auto-Configuration&#xff09; 是它的核心特性之一&#xff0c;它让开发者可以 "开箱即用"&#xff0c;避免手动配置大量的 XML 或 Java Config。它的核心思想是&#xff1a;"约定优于配置"&…

直播预告|鸿蒙生态中的AI新玩法

想知道鸿蒙生态里 AI 能玩出啥新花样&#xff1f; 8 月 14 日&#xff08;周四&#xff09;20:00 &#xff0c;「开发者・面对面 坚果派特辑 —— 鸿蒙生态中的 AI 新玩法」直播来袭&#xff01; &#x1f50d; 直播亮点抢先看 AI赋能鸿蒙产品开发&#xff1a;将分享如何利用AI…

智能合约:区块链时代的“数字契约革命”

一、技术原理与核心特征1. 定义与本质智能合约是运行在区块链上的自动化程序&#xff0c;通过代码定义业务规则&#xff0c;在预设条件满足时自动执行操作&#xff08;如资金转移、信息更新&#xff09;&#xff0c;无需人工干预。其核心特性包括&#xff1a;自动执行&#xff…

【数据分析】比较SparCC、Pearson和Spearman相关性估计方法在合成组学数据上的表现

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍 加载R包 模拟数据 构建网络 RMSE指数计算 画图 总结 系统信息 介绍 在生物信息学和生态学研究中,组学数据的分析越来越依赖于对微生物群落或基因表达数据中物种或基因间相关性的…

Google C++ 风格指南

文章目录背景介绍风格指南的目标C 版本头文件自包含头文件#define 防护包含所需内容前置声明在头文件中定义函数头文件包含顺序与命名规范作用域命名空间内部链接非成员函数、静态成员函数与全局函数局部变量静态与全局变量关于析构的决策关于初始化的决策常见模式thread_local…

安装部署_WVP流媒体

文章目录一、DEV_WVP流媒体开发手册1、搭建流媒体服务clone代码&#xff1a;安装编译器cmake构建和编译项目修改配置文件启动项目2、搭建GB28181协议视频平台安装 jdk, nodejs, maven, git安装redis安装postgresqlclone代码编译前端代码编译后端代码配置文件修改3、设备接入测测…

软件I2C实现(2):I2C协议实现

0 参考资料 I2C 总线规范.pdf 1 I2C协议实现 1.1 SCL、SDA引脚初始化 将SCL、SDA初始化为开漏输出,电平设置为高电平(使用外部上拉电阻拉高)。 /*** @brief 软件I2C初始化** @param sw_i2c_cfg 软件I2C配置指针*/ int sw_i2c_init(sw_i2c_cfg_t *sw_i2c_cfg) {GPIO_InitT…

疯狂星期四文案网第40天运营日记

网站运营第40天&#xff0c;点击观站&#xff1a; 疯狂星期四 crazy-thursday.com 全网最全的疯狂星期四文案网站 运营报告 今日访问量 今日搜索引擎收录情况 必应秒发秒收 百度收录很慢 网站优化点 优化seo 修复已知bug

【大语言模型 01】注意力机制数学推导:从零实现Self-Attention

注意力机制数学推导&#xff1a;从零实现Self-Attention - 开启大语言模型的核心密码 关键词&#xff1a;注意力机制、Self-Attention、Transformer、数学推导、PyTorch实现、大语言模型、深度学习 摘要&#xff1a;本文从数学原理出发&#xff0c;详细推导Self-Attention的完整…

2025 环法战车科技对决!维乐 Angel Glide定义舒适新标

环法赛场不仅是顶尖车手的竞技舞台&#xff0c;更是自行车科技的时尚秀场。然而经常骑行的朋友都知道&#xff0c;当顶级战车遇上专业坐垫&#xff0c;方能成就完美骑行体验。2025 年环法赛场上的新战车们各展神通&#xff0c;而维乐 Angel Glide 坐垫以其独特的科技与设计&…

VS Code配置MinGW64编译ALGLIB库

VS Code用MinGW64编译C代码安装MSYS2软件并配置ALGLIB库和测试引用库代码的完整具体步骤。 1. 安装 MSYS2 下载 MSYS2&#xff1a; 访问 MSYS2 官网下载最新安装包&#xff08;如 msys2-x86_64-latest.exe&#xff09; 安装&#xff1a; 运行安装程序&#xff0c;默认路径为 C…