JVM面试题

  1. JVM理论

#JVM内存模型#

  • Java内存模型(JMM)?

Java的内存模型决定了线程间的通信方式,JMM的模型是由主存和工作内存构成,两个线程想要正常通信需要将工作内存中的变量刷到主存中,另一个线程才能正确读取得到,这个也是volitile关键词的原理所在。

JVM内存结构和Java内存模型的参考资料:JVM内存结构和Java内存模型 - 知乎

  • JVM内存结构?

JVM主要由堆(JVM heap)、方法区(Method Area)、虚拟机栈(JVM stack)、本地方法区(Native Method area)、程序计数器(PCR),其中堆、方法区是线程共享的,和JVM的启动停止同步,虚拟机栈、本地方法栈、程序计数器(PCR)是线程不共享的,是线程私有的,和线程的创建停止同步。每个结构的用途如下: 

  1. 堆主要存储的是对象和数组,他是JVM内存模型中最大的一个区域,其中又能分为年轻代和老年代,年轻代又能分为Eden区和Survivor区,Survivor区又能分为S0,S1区,这是JVM中发生GC最频繁的区域。
  2. 虚拟机栈是Java方法执行的内存区域,他的基本单位是栈帧,每发生一次方法调用,就将一个栈桢入栈,方法的执行都在这个帧里面。这个帧里面包括:局部数据表,操作栈,动态链接,方法返回地址,局部变量表主要存储局部变量和方法参数,操作栈是方法执行的各种指令就放在操作栈里面的,返回地址是记录方法调用的返回地址。
  3. 本地方法区类似于虚拟机栈,只是他是为了保存通过JNI方式操作本地方法的相关信息。
  4. 方法区是保存类Class元信息、静态变量、常量等信息,其中还包括运行时常量池,其中会保存字符串常量等信息。
  5. 程序计数器则保存了每个线程执行到的字节码的指令地址。

运行时内存结构:

JVM的堆中包括新生代(Young)和老年代(Old)区域,其中新生代包括Eden和Survivor区域,其中Survivor区域包括S0和S1区域。其中新创建的对象会首先发到新生代的Eden区,但是如果对象太大也会直接放到老年代,其中新生代的GC是Minor GC,Minor GC后存活对象会被移至Survivor区,在这里会进行Major GC,每一次GC都会在S0和S1中移动复制对象,每次移动都会将该对象的年龄+1,等到满足一定的阈值就会移动到老年代中,这个阈值的默认值是15。

  1. Minor GC:是在新生代发生的GC,准确来说是在Eden区发生的GC。触发条件是Eden的空间不够,会触发异常Minor GC。
  2. Major GC:是老年代空间不够触发的GC。或者从新生代进入老年代的对象空间大于空闲空间了。
  3. Full GC:是新生代和老年代共同GC。

对象内存分配的流程图:

  • JVM堆内存分配如何保障分配对象时候的线程安全?

JVM堆在创建对象时候过程:

  1. 如果JIT分析判断该对象是逃逸对象,就直接在栈上分配,就不存在线程安全问题;
  2. 如果判断需要在JVM栈上分配,会针对该线程在TLAB上申请一块区域,该线程分配的对象登记在该区域,用以解决多线程下可能发生的线程不安全问题;
  3. 如果该对象被判断为大对象,这直接进入老年代,不会在年轻代分配空间;

#GC垃圾回收器#

  • 判断对象是否可以被回收

判断对象是否可回收的方法:

  1. 引用计数法:每个对象有一个引用计数器,每次被引用就+1,释放引用就-1,等到为0的时候就可以被回收;他的缺陷是可能存在循环引用的问题。
  2. 可达性分析:就是利用GC root到达对象的可达性来分析对象是否被引用,如果被引用就在这条引用链中,就不能回收;

GC root可以由一下对象充当:

  1. 虚拟机栈(方法)中引用的对象;

  1. 类变量(静态变量)引用的对象;

  1. 常量引用的对象;

  1. JNI引用的对象;

GC Roots 是什么?哪些对象可以作为 GC Root?看完秒懂!

GC Roots 是什么?哪些对象可以作为 GC Root?看完秒懂!_一直Tom猫的博客-CSDN博客

  • GC垃圾回收算法?

GC算法分为分代算法和分区算法,以下1,2,3是分区回收算法,4为分代回收算法:

  1. 标记-清除(Mark-Sweep)算法:就是将失效的对象做标记,等要回收的时候再清空这个对象,这个算法是分代算法的基础。缺点是标记和清除的效率都不高,并且可能存在较多的内存碎片。
  2. 标记-整理(Mark-Compact)算法:为了更充分的利用内存区域,就是将失效的对象先标记,再整理到内存区域的一侧,这样整理下来的也就是一块完整的区域,可以存放大对象,这个是在老年代中使用的GC算法,原因是老年代中对象需要回收的少,触发GC的频率低。
  3. 复制Copying算法:为了弥补标记-清除算法可能造成内存碎片的问题,就是将内存区域划分为两块,每次就只用一块,等到一块要满了,再将有效的复制到另一块,这样就能保证一块永远是空的,这个在新生代中使用的GC算法,原因是新生代中对象需要回收的多,并且触发GC的频率高。
  4. 现代的GC都分为老年代和新生代了,针对各自的特征,选中不同的GC算法。针对新生代,他们的对象生存周期短,可以选择复制这样的GC算法,这样可以留出一大片空闲空间,而老年代的内存中对象由于更新的慢,可以选择标记-整理这样的单点清理GC算法,同时也能避免内存碎片的产生。

JVM之GC算法:https://www.cnblogs.com/BlueStarWei/p/9577388.html

  • GC垃圾回收器?

GC回收器的种类:(1)serial回收器:就是在GC回收的时候停掉工作线程,他是一个串行的回收器;(2)parallel回收器:就是GC回收器是并发执行的;(3)CMS,他的全程是concurrent mark sweep,他的主要优势是在GC回收的时候不需要stop the world;(4)G1:这个是从JDK7后推出的新的GC;

CMS GC垃圾回收器

  1. CMS是并发标记清除GC回收器件,其目标是获取最短GC停顿时间,比较符合大型web server项目的使用场景。其GC阶段经过4个阶段:
  1. 初始标记:初始标记又GC root引用的对象,该过程会引发STW;
  2. 并发标记:这个是不需要STW,并发标记要回收的对象;
  3. 重新标记:这个节点重新标记并发阶段产生的新的要回收的对象;
  4. 并发清除;并发清除标记的要回收的对象;

 

CMS总结

  1. 优点:(1)并发处理效率高;(2)GC的时候不会整体停顿STW,有效降低处理时延。
  2. 缺点:(1)并发清理时会降低CPU性能;(2)标记-清理可能会造成大量内存碎片;(3)并发清理阶段还会产生垃圾,这种垃圾称为浮动垃圾,需要下一次GC时才能清理掉。

G1 GC垃圾回收器:

G1回收器会将区域划分为region,每个region可以是新生代也可以是老年代,通过控制对region的回收,做到对垃圾回收导致的STW可控。垃圾回收的阶段前3个阶段和CMS一致,只是最后一个节点需要通过混合清除来回收新生代和老年代所有的对象:

  1. 初始标记;标记GC root对象,需要暂停所有用户线程,该过程会引发STW;
  2. 并发标记;标记GC root可达的对象。
  3. 最终标记;标记在并发标记阶段产生的需回收对象。
  4. 筛选回收:对各个Region的回收成本和价值进行排序,根据用心要求的GC停顿时间来选择需要GC的Region。


G1总结:

  1. 优点:(1)并发处理效率高;(2)整体停顿STW的时间可控;(3)新生掉和老年代都分为逻辑上的region,通过GC的复制算法解决内存碎片的问题;
  2. 缺点:引入了Remembered Set来保存内存引用信息,所以增加了内存占用,所以G1一般在大内存的服务端环境使用,起步内存大小为6G。

GC回收器总结:

  1. 选择GC主要考虑的是使用场景,一般嵌入式、内存较小的选择串行GC回收器;
  2. 对于需求吞吐量大的常见可以选择并行GC回收器;
  3. 对于需要时延少的场景可以选择CMS或者G1回收器;

#JMV加载机制#

  • 双亲委派模型是什么

双亲委派模型的定义

当前ClassLoader加载的class,先调用双亲ClassLoader,如果他们加载不了,当前ClassLoader才加载,所以所有的类都会被请求到Bootstrap ClassLoader,简单理解就是能双亲做的事,就双亲来做,双亲做不了的事情就自己来做;

双亲委派模型的作用:

  1. 保障类的唯一性:ClassLoader的双亲委派模型保障一个类在类加载器的唯一性,父类已经加载了该类,子类就不再加载。
  2. 保障按需加载由于ClassLoader只有在需要某个类的时候才会加载某个类,这样避免一次性将类全部加载进入内存引发OOM。并且当ClassLoader加载一个类时,该类依赖的其他类也会由这个ClassLoader加载进来。
  • 类加载器ClassLoader原理?
  1. ClassLoader是做什么的?他是通过类的全限定名该类的字节码转化为内存中Class对象
  2. 为什么会有ClassLoader这种东西?这是由于JVM对类的加载是按需延迟加载的,并不是一次将所有类加载到内存空间里,所以需要类加载器在内存中等待需要加载的类; 
  3. ClassLoader的常用组件?最顶层的Bootstrap ClassLoader,主要负责加载rt.jar包里面的class,Extension ClassLoader主要负责加载javax里面的java ext等类,Application ClassLoader负责加载classpath里面的class文件,还有Customer ClassLoader,这个可以加载用户自定义的ClassLoader;

老大难的 Java ClassLoader 再不理解就老了:

老大难的 Java ClassLoader 再不理解就老了 - 掘金

  • ClassLoader进行加载过程?

类加载的过程是将类的字节码加载到内存中的过程,主要包括:加载-->链接-->初始化,其中链接还包括验证、准备、解析3个步骤。

  1. 加载:将class文件加载到内存,在方法区生成一个java.lang.Class对象放到方法区;
  2. 验证:验证这个class文件是否合法,包括文件格式的校验,元数据类型的校验等;
  3. 准备:为类变量分配内存空间,但此时只是初始化为默认值而非真实值,但对于final变量此时会初始化为真实值;
  4. 解析:将符号引用(相对引用)转换为直接引用,符号引用是class文件的相对表达方式,直接引用就是在该系统里地址指针,比如hello()方法为符号引用,0x12345678为直接引用;
  5. 初始化:初始化类变量成真实值,初始化静态代码段,实际执行的是类构造器<clinit>方法。

 

注意:类的初始化过程是懒加载的策略,只有当该类被使用了才会被初始化,实际就是调用<clinit>方法执行的过程;会触发类的初始化操作条件为:(1)需要创建新的对象,执行了new操作;(2)调用了类的静态变量或静态方法;(3)通过反射机制来获取某个类的时候;

  • Java 对象实例化(new)的过程?

Java的对象实例化的过程是调用<init>方法,在进行new操作的时候会执行实例化操作,实例化的过程主要是调用构造方法的过程。在进行对象实例化之前,会初始化静态变量和静态代码段,然后初始化变量和代码块,最后调用构造方法进行实例化。对象实例化过程:

 

有父子关系的初始化过程:先初始化父类,再初始化子类。

 

  • 如何判断JVM中两个类相等?

同一个类的class文件被同一个classloader加载,在JVM中才能判断这两个类对象相等。

  • Java对象(Object)在内存中的结构?

这个是指保存在JVM堆区的的java.lang.Object对象,主要包括对象头,实例数据和对齐填充数据组成。

  1. 对象头:包括(1)Mark Word,这个字段包括GC标志位,锁状态,hashcode等数据,其中锁状态包括能表征对象加锁是无锁、偏性锁、轻量级锁、重量级锁。(2)Klass Pointer(类型指针),指向方法区的类信息的指针。还有Array Length,这个当对象是数组时会存在。
  2. 实例数据:这个保存实例变量,存储对象真正的数据。
  3. 对齐填充数据由于JVM规定对象数据必须为8字节的整数,这个部分用来做数据填充。

 

Java对象在内存的结构:Java对象在内存的结构 - 掘金

Java 对象结构:Java 对象结构 - 掘金

  1. JVM应用
  • JVM调优的主要参数和工具

JVM常用参数:

  1. -Xms设置堆的最小空间大小。
  2. -Xmx设置堆的最大空间大小。
  3. -XX:NewSize设置新生代最小空间大小。
  4. -XX:MaxNewSize设置新生代最大空间大小。
  5. -XX:PermSize设置永久代最小空间大小。
  6. -XX:MaxPermSize设置永久代最大空间大小。
  7. -Xss设置每个线程的堆栈大小。 

JVM常用命令和工具:

  1. jps:java线程查看工具
  2. jstack:java线程栈的查看工具
  3. jmap:java中堆的查看工具
  4. jstat:java内置的资源和性能监控工具
  5. jinfo:实时查看和调整jvm参数

【JVM进阶之路】十:JVM调优总结:【JVM进阶之路】十:JVM调优总结 - 知乎

  • GC优化的思路?
  1. GC优化的重要指标看GC频次和GC时长,可以通过命令:jstat查看;
  2. GC优化的重要指标看CPU和内存的占用率,一般在不高于70%的利用率比较合适;
  3. 可以调整young/old分区大小和分区比例;
  4. 可以调整进入永久代的年龄阈值,默认是15次;
  5. 可以调整是否使用偏向锁;

一次简单的 JVM 调优,拿去写到简历里:

一次简单的 JVM 调优,拿去写到简历里

  • JVM问题排障的思路
  1. top查询得到哪个进程id出现问题,进而得到哪个线程id出问题,jps查询哪个线程id出现了问题;
  2. jmap查看堆内存,可以dump下来;
  3. jstack查看线程堆栈问题;
  4. jstat进行资源监控,可以查看GC数据;
  5. 其他
  • 怎么制造OOM?
  1. 对于堆中的OOM,只需要一直创建对象;
  2. 对于栈中的OOM,只需要一直创建线程或者进行递归调用就好;
  3. 对于方法区的OOM,只需要一直通过反射的方法创建类就好了;

注意:创建之前要设置堆栈的大小;

  • 对象的强引用软引用弱引用虚引用的区别?
  1. 强引用:只要引用存在,在gc root的引用链中,即可一直存在,gc不掉。最常见的一种形式:Object obj = new Object();   
  2. 软引用:gc不掉,但是当oom时,再次gc就会被gc掉,常用来做内存敏感的缓存;
  3. 弱引用:gc一次就会被gc掉,常用来做weakHashMap来做缓存;
  4. 虚引用:是无法使用的引用,一般用来通知某对象被gc了。

引用类型:强软弱虚

剖析 JDK:强引用、软引用、弱引用、虚引用有何区别?:

剖析JDK:强引用、软引用、弱引用、虚引用有何区别?_28天写作_后台技术汇_InfoQ写作社区

  • 如何对JVM进行设置,让其不发生Full GC?

这道题考察的关键是:如果不想要发生Full GC,则让对象只在新生代中进行GC,尽量不要转移至老年代,所以应该调整的是新生代的空间大小和比例。

  • Java是编译型还是解释型语言?
  1. 编译型语言是通过编译器将源码编译成机器能识别的机器码,在机器上能直接执行,比如C/C++;
  2. 解释型语言是不需要进过编译,直接通过解释器就能执行,比如JavaScript;
  3. Java的执行过程是先通过javac编译器,编译成class字节码文件,再在不同平台的JVM上解释执行,针对其中的热点代码,还会使用JIT技术直接编译成机器码,所以客观来说Java既不是编译型也不是解释型语言,是结合了他们两者的混合执行方式。
  • JVM中JIT技术的一些常见优化策略?
  1. 逃逸分析:逃逸分析的基本行为是分析对象的作用于,一个对象如果在方法中创建,但是在方法外也会被引用,这就称为该对象方法逃逸,反之如果该对象只在该方法内使用则该对象未发生方法逃逸,针对对象的逃逸分析后续可以进行一系列的优化策略。
  2. 栈上分配:一般对象存放在JVM的堆上,针对未发生方法逃逸的对象,即他的作用域只在该方法内,所以可以在JVM栈上分配对象。

标量替换:标量在程序中是指无法再分解成更小数据单元的对象,比如Java中的基础数据类型就是标量,而聚合量是指可以再分解成更小数据单元的对象,比如Java中的类对象,其至少能分解成成员变量和方法。针对未发生方法逃逸的对象,则可以直接在方法内进行标量替换,这样就不用分配到JVM的堆上。

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

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

相关文章

SpringBoot 升级内嵌Tomcat

SpringBoot 更新 Tomcat 最近公司的一个老项目需要升级下Tomcat&#xff0c;由于这个项目我完全没有参与&#xff0c;所以一开始我以为是一个老的Tomcat项目&#xff0c;升级它的Tomcat依赖或者是Tomcat容器镜像&#xff0c;后面发现是一个SpringBoot项目&#xff0c;升级的是…

基于SpringBoot+LayUI的宿舍管理系统 001

项目简介 源码来源于网络&#xff0c;项目文档仅用于参考&#xff0c;请自行二次完善哦。 系统以MySQL 8.0.23为数据库&#xff0c;在Spring Boot SpringMVC MyBatis Layui框架下基于B/S架构设计开发而成。 系统中的用户分为三类&#xff0c;分别为学生、宿管、后勤。这三…

SQL ASNI where from group order 顺序 where和having,SQL底层执行原理

SQL语句执行顺序&#xff1a; from–>where–>group by -->having — >select --> order 第一步&#xff1a;from语句&#xff0c;选择要操作的表。 第二步&#xff1a;where语句&#xff0c;在from后的表中设置筛选条件&#xff0c;筛选出符合条件的记录。 …

STM32--EXTI外部中断

前文回顾---STM32--GPIO 相关回顾--有关中断系统简介 目录 STM32中断 NVIC EXTI外部中断 AFIO EXTI框图 旋转编码器简介 对射式红外传感器工程 代码&#xff1a; 旋转编码器工程 代码&#xff1a; STM32中断 先说一下基本原理&#xff1a; 1.中断请求发生&#xff1a…

Profibus-DP转modbus RTU网关modbus rtu和tcp的区别

捷米JM-DPM-RTU网关在Profibus总线侧实现主站功能&#xff0c;在Modbus串口侧实现从站功能。可将ProfibusDP协议的设备&#xff08;如&#xff1a;EH流量计、倍福编码器等&#xff09;接入到Modbus网络中&#xff1b;通过增加DP/PA耦合器&#xff0c;也可将Profibus PA从站接入…

MyBatis操作数据库常见用法总结2

文章目录 1.动态SQL使用什么是动态sql为什么用动态sql标签拼接标签拼接标签拼接标签拼接标签拼接 补充1&#xff1a;resultType和resultMap补充2&#xff1a;后端开发中单元测试工具使用&#xff08;Junit框架&#xff09; 1.动态SQL使用 以insert标签为例 什么是动态sql 是…

golang协程池(goroutine池)ants库实践

golang中goroutine由运行时管理&#xff0c;使用go关键字就可以方便快捷的创建一个goroutine,受限于服务器硬件内存大小&#xff0c;如果不对goroutine数量进行限制&#xff0c;会出现Out of Memory错误。但是goroutine泄漏引发的血案&#xff0c;想必各位gopher都经历过&#…

易服客工作室:初学者的终极WordPress SEO教程(入门指导)

改善WordPress SEO对于获得更多网站流量至关重要。可悲的是&#xff0c;大多数WordPress SEO指南对于新用户来说太技术性了。 如果您认真考虑增加网站流量&#xff0c;则需要注意WordPress SEO最佳做法。 在本WordPress SEO教程中&#xff0c;我们将分享WordPress SEO的主要技…

创建Springboot+vue3项目

项目概述创建springboot项目加入mybatis-plus支持1.加入依赖代码2.创建数据库实例3.yml文件的配置4.编写测试代码5.测试结果 创建vue项目报错错误一错误二错误三 项目概述 后端&#xff1a;Springboot、mybatis-plus、java 前端&#xff1a;nodejs、vue脚手架、element-ui 数据…

【Spring Boot 源码学习】自动装配流程源码解析(上)

自动装配流程源码解析&#xff08;上&#xff09; 引言往期内容主要内容1. 自动配置开关2. 加载自动配置组件3. 自动配置组件去重 总结 引言 上篇博文&#xff0c;笔者带大家从整体上了解了AutoConfigurationImportSelector 自动装配逻辑的核心功能及流程&#xff0c;由于篇幅…

HCIP-linux和kvm(ks配置文件自动化安装及console连虚拟机有问题)

1、linux linux安装教程参考&#xff0c;https://blog.51cto.com/cloudcs/5245337 yum源配置 本地yum源配置&#xff1a; 8版本配置&#xff1a;将光盘iso挂载到某个目录&#xff0c;/dev/cdrom是/dev/sr0软链接&#xff0c;# mount /dev/cdrom /mnt&#xff0c;# ls /mnt Ap…

C#导入数据使用Task异步处理耗时任务

C#多线程中&#xff0c;我们可以使用async和await来异步处理耗时任务。 现在我们打开一个Excel表格&#xff0c;将Excel表格的每一行数据进行处理&#xff0c;并存储到数据库中 新建Windows应用程序DataImportDemo&#xff0c;.net framework 4.6.1 将默认的Form1重命名为Fo…

数组slice、splice字符串substr、split

一、定义 这篇文章主要对数组操作的两种方法进行介绍和使用&#xff0c;包括&#xff1a;slice、splice。对字符串操作的两种方法进行介绍和使用&#xff0c;包括&#xff1a;substr、split (一)、数组 slice:可以操作的数据类型有&#xff1a;数组字符串 splice:数组 操作数组…

小程序wx:else提示 Bad attr `wx

问题&#xff1a;以下wx:for里的wx:if &#xff0c; wx:else 会报这个错&#xff1a;Bad attr wx <scroll-view class"scroll1" scroll-x enable-flex"true"><view wx:if"{{playlist.length>0}}" class"item" wx:for"…

SonarQube安装与Java、PHP代码质量分析扫描

文章目录 1、下载安装1.1、SonarQube下载1.2、SonarQube安装1.3、SonarQube中文汉化1.4、SonarScanner扫描器 2、扫描项目2.1、java代码扫描2.2、php代码扫描 1、下载安装 SonarQube负责存储代码数据、收集数据、分析代码和生成报告等。 1.1、SonarQube下载 下载地址&#x…

MPP架构和Hadoop架构的区别

1. 架构的介绍 mpp架构是将许多数据库通过网络连接起来&#xff0c;相当于将一个个垂直系统横向连接&#xff0c;形成一个统一对外的服务的分布式数据库系统。每个节点由一个单机数据库系统独立管理和操作该物理机上的的所有资源&#xff08;CPU&#xff0c;内存等&#xff09…

【QT】 QT开发PDF阅读器

很高兴在雪易的CSDN遇见你 &#xff0c;给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享QT开发PDF阅读器技术&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xff0c;一起进步&#xff01; 你的点…

使用chatGPT-4 畅聊量子物理学

与chatGPT深入研究起源、基本概念&#xff0c;以及海森堡、德布罗意、薛定谔、玻尔、爱因斯坦和狄拉克如何得出他们的想法和方程。 1965 年&#xff0c;费曼&#xff08;左&#xff09;与朱利安施温格&#xff08;未显示&#xff09;和朝永信一郎&#xff08;右&#xff09;分享…

数据分析-python学习 (1)numpy相关

内容为&#xff1a;https://juejin.cn/book/7240731597035864121的学习笔记 导包 import numpy as np numpy数组创建 创建全0数组&#xff0c;正态分布、随机数组等就不说了&#xff0c;提供了相应的方法通过已有数据创建有两种 arr1np.array([1,2,3,4,5]) 或者datanp.loadt…

当我准备出门时,发现了......我可以用Python实现12306自动买票

前言 不知道大家有没有之前碰到这样的情况&#xff0c;打算去某一个地方当你规划好了时间准备去买票的时候&#xff0c;你想要的那一列往往没有你想要的票了&#xff0c;尤其是国庆七天假和春节半月假&#xff0c;有时候甚至买不到规定计划时间内的票&#xff0c;真的是太烦躁…