JVM篇--Java内存区域高频面试题

news2024/11/17 3:38:28

java内存区域

1 Java 堆空间及 GC?

首先我们要知道java堆空间的产生过程: 即当通过java命令启动java进程的时候,就会为它分配内存,而分配内存的一部分就会用于创建堆空间,而当程序中创建对象的时候 就会从堆空间来分配内存,所以堆空间存放的主要是对象和数组;
而GC 其实说白了就是java虚拟机回收对象的机制,即回收无效对象的内存用于将来的分配。

2 JVM 的主要组成部分及其作用?

JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。
那么他们分别有啥作用呢?
首先看Class loader:根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area。其实说白了就是类加载器,简单点-作用就是通过类加载器将编译好的class文件加载到运行时数据区
Execution engine(执行引擎): 执行class中的指令
Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。
Runtime data area(运行时数据区域):这就是我们常说的JVM的内存

整体的过程:首先会通过编译器把Java代码转换成字节码源文件,之后类加载器会把字节码文件加载到内存中,即加载到运行时数据区,
但是其实字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统来去执行,因此需要特定的命令解析器即执行引擎,将字节码翻译成底层的系统指令,再交由CPU去执行
同时java代码中 可以调用其他语言的本地库接口,进行一些系统调用或者c函数的调用
在这里插入图片描述

3 说说JVM 运行时数据区? 或:说一下JVM内存模型?

jvm内存模型大致被划分为如下几个区域:
程序计数器:也就是当前线程所执行的字节码指令的行号指示器,说白了就是当前字节码执行到的位置,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令

java虚拟机栈:用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息,也是线程私有的。每个方法在执行时都会创建一个栈帧,栈帧包含了方法的局部变量表、操作数栈等信息。

本地方法栈:与 Java 虚拟机栈类似,只不过虚拟机栈是服务 Java
方法的,而本地方法栈是为虚拟机调用 Native 方法服务的

堆:用于存储对象实例和数组,它也是jvm中最大的一块内存区域,同时也是线程共享的,而堆包括年轻代和老年代,以支持垃圾回收机制。

  1. 年轻代(Young Generation):用于存放新创建的对象。年轻代又分为 Eden 区和两个 Survivor 区(通常是一个 From 区和一个 To 区),对象首先被分配在 Eden 区,经过垃圾回收后存活的对象会被移到 Survivor 区,经过多次回收后仍然存活的对象会晋升到老年代。
  2. 老年代(Old Generation):用于存放存活时间较长的对象。老年代主要存放长时间存活的对象或从年轻代晋升过来的对象。

方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据

4 什么是堆内存?

以Hotspot为例,堆内存主要由GC模块进行管理和分配,可以分为新生代和老年代,而新生代又可以分为eden区,s1区和s2区,并且他们的比例默认为8:1:1, 同时新生代和老年代的占比如下图所示
在这里插入图片描述
在使用堆内内存(on-heap memory)的时候,完全遵守JVM虚拟机的内存管理机制,采用垃圾回收器(GC)统一进行内存管理,
GC会在某些特定的时间点进行一次彻底回收,也就是Full GC,GC会对所有分配的堆内内存进行扫描,在这个过程中会对JAVA应用程序的性能造成一定影响,还可能会产生Stop The World。

5 什么是非堆内存?

通常来说方法区是非堆内存,而jdk1.8之前的方法区实现是永久代,而jdk1.8之后的方法区实现叫元空间

6 什么是堆外内存呢?

堆外内存, 常常又叫做直接内存。 和堆内内存相对应,堆外内存就是把内存对象分配在Java虚拟机的堆以外的内存
这些内存直接受操作系统管理(而不是虚拟机),这样做的结果就是能够在一定程度上减少垃圾回收对应用程序造成的影响。
具体实现 可以 用java.nio.DirectByteBuffer对象进行堆外内存的管理和使用
那么堆外内存的优点是什么?
减少垃圾回收:因为垃圾回收会暂停其他的工作。
加快复制速度:堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作。

7 永久代和方法区又有什么区别呢?

方法区是《Java虚拟机规范》中定义的内存区域,用于存储类的结构信息(如类的字节码、常量池、字段和方法信息等),
而 Java 默认虚拟机 HotSpot 中,在 JDK 1.8 之前的版本中,是通过永久代来实现方法区的,但 JDK 1.8 之后,永久代被元空间(Metaspace)取代。
所以,总结来看,方法区是规范,而永久代(和元空间)是具体实现。

8 那么为啥用元空间来取代永久代呢?

主要原因有以下几点,

  1. 兼容JRockit --首先java官方要收购JRocket,而JRockit 中没有“永久代”的概念 所以为了更好的融合JRockit和Hotspot源码,因此取消了永久代。
  2. 其次可以提高稳定性,降低OOM的风险-因为对于永久代来说是需要设置PermSize 和 MaxPermSize 参数的,而一旦这两个值设置的不合理或者设置的过小就会频繁触发FullGC 和导致 OOM(Out of Memory,内存溢出),但是当使用元空间来替代永久代后 出现OOM的风险就大大降低了,因为元空间使用的是本地内存,也就是只和本地内存大小有关。
  3. 降低运维成本–因为用了元空间后就不在需要运维或者开发人员手动的来去设置和调整元空间的大小

9 为什么调整字符串常量池的位置?

其实主要是为了提高回收效率,便于及时的回收常量池内存,同时也是会缓解永久代空间不足的问题
首先我们要知道字符串常量池在1.7之前是放到永久代的,而永久代的回收效率是很低的,只有在fullGC的时候才会触发,而fullGC的触发也是需要再老年代的空间不足,或者永久代不足时才会进行触发,这样就导致了字符串常量池的回收效率并不高。但其实在真正的开发中,我们一般会有大量的字符串常量被创建,回收效率低反过来也会导致永久代空间不足
因此在jdk1.7之后字符串常量池被放到了堆空间中,便于及时的回收内存

10成员变量、局部变量、类变量分别存储在内存的什么地方?

  1. 类变量
    类变量是用static修饰符修饰,定义在方法外的变量,随着java进程产生和销毁。在java8之前把静态变量存放于方法区,在java8时存放在堆中

  2. 成员变量
    成员变量是定义在类中,但是没有static修饰符修饰的变量,随着类的实例产生和销毁,是类实例的一部分
    由于是实例的一部分,在类初始化的时候,从运行时常量池取出直接引用或者值,与初始化的对象一起放入堆中

  3. 局部变量
    局部变量是定义在类的方法中的变量
    在所在方法被调用时放入虚拟机栈的栈帧中,方法执行结束后从虚拟机栈中弹出,所以存放在虚拟机栈中

11 堆和栈有什么区别?

具体区别可以看以下几点
1 存放的内容
堆存放的是对象的实例和数组,而栈存放的是局部变量,操作数栈
2 再从是否私有来看
堆对于整个应用程序来说都是共享的,而栈是线程独享,所以也是线程私有。他的生命周期和线程相同
3 物理结构
堆的物理地址分配对对象是不连续的。因此性能慢些。在GC的时候也要考虑到不连续的分配,所以有各种算法。
栈使用的是数据结构中的栈,先进后出的原则,物理地址分配是连续的。所以性能快。

12 什么是双亲委派模式?

说到双亲委派模式 我们先聊下什么是类加载器 以及类加载器的分类
类加载器(Class Loader)是 Java 虚拟机(JVM)的重要组成部分,负责将字节码文件加载到内存中并转换为可执行的类
而类加载器大致可以分为四种
启动类加载器:加载 JDK 中 lib 目录中 Java 的核心类库,即$JAVA_HOME/lib目录。
扩展类加载器:加载 lib/ext 目录下的类;
应用程序类加载器:加载我们写的应用程序;
自定义类加载器:根据自己的需求定制类加载器。

而 双亲委派模型是 Java 类加载器的一种工作机制。
它是指当一个类加载器需要加载一个类时,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最 终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无 法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
双亲委派模型的优点是啥?
避免重复加载类:比如 A 类和 B 类都有一个父类 C 类,那么当 A 启动时就会将 C 类加载起来,那么在 B 类进行加载时就不需要在重复加载 C 类了。
提高安全性使用双亲委派模型也可以保证了 Java 的核心 API 不被篡改,如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类,而有些 Object 类又是用户自己提供的因此安全性就不能得到保证了。

那么如何打破双亲委派机制呢?
1.自定义类加载,重写loadclass方法
因为双亲委派的机制都是通过这个方法实现的,这个方法可以指定类通过什么类加载器来进行加载,所有如果改写他的加载规则,相当于打破双亲委派机制

2.使用线程上下文类
双亲委派模型的第二次“破坏”是由这个模型自身的缺陷所导致的,双亲委派很好的解决了各个类加载器的基础类统一问题,基础类之所以“基础”,是因为他们总被用户代码所调用,但是如果基础类又要重新调用用户代码,那咋办?
比如说JNDI是java的标准服务,它的代码是由启动类加载器进行加载的,但是jndi的作用就是进行资源的集中管理和查找,它需要调用由开发人员开发在classpath下的类代码,但是启动类加载器不会进行加载。
所以引入线程上下类加载器,通过java.lang.Thread类的setContextClassLoader()方法进行设置。如果创建线程是还未设置,它会从父线程继承一个,如果在应用程序全局范围内没有设置,那么这个线程上下类加载器就是应用程序类加载器。
那么这样JNDI服务使用这个线程上下类加载器去加载所需的spi代码,也就是父类加载器请求子类加载器去完成类加载的动作,这个实际是打通了双亲委派的逆向层次结构。

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

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

相关文章

图像处理-像素位置的一阶导数和二阶导数

图像处理-像素位置的一阶导数和二阶导数 空间卷积是一种图像处理中常用的技术,用于计算图像中每个像素位置的一阶导数和二阶导数。在这里将解释如何使用卷积操作来实现这些导数的计算。 一阶导数和二阶导数的性质: 一阶导数通常产生粗边缘&#xff1b…

redis原理(二)数据结构

redis可以存储键与5种不同数据结构类型之间的映射: String类型的底层实现只有一种数据结构,也就是动态字符串。而List、Hash、Set、ZSet都由两种底层数据结构实现。通常我们把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据…

小程序系列--6.全局配置

一. 全局配置文件及常用的配置项 二、window 1. 小程序窗口的组成部分 2. 了解 window 节点常用的配置项 3. 设置导航栏的标题 4. 设置导航栏的背景色 5. 设置导航栏的标题颜色 6. 全局开启下拉刷新功能 7. 设置下拉刷新时窗口的背景色 8. 设置下拉刷新时 loading 的样…

【Python数据可视化】matplotlib之绘制高级图形:散点图、热力图、等值线图、极坐标图

文章传送门 Python 数据可视化matplotlib之绘制常用图形:折线图、柱状图(条形图)、饼图和直方图matplotlib之设置坐标:添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值matplotlib之增加图形内容&#x…

超声波清洗机真有用吗?眼镜党需注意!别被错误洗眼镜方法误导

超声波清洗机洗眼镜真的有用吗?眼镜党朋友一定要注意了,眼镜清洗可不能有一点马虎的哈! 眼镜是很多人日常生活中不可或缺的用品,然而清洁眼镜却是一个让人头疼的问题。随着科技的发展,超声波清洗机作为一种新兴的清洁…

《WebKit 技术内幕》之二: HTML 网页和结构

第二章 HTML 网页和结构 HTML网页是利用HTML语言编写的文档,HTML是半结构化的数据表现方式,它的结构特征可以归纳为:树状结构、层次结构和框结构。 1.网页构成 1.1 基本元素和树状结构 HTML网页使用HTML语言撰写的文档,发展到今…

实战 | 某电商平台类目SKU数获取与可视化展示

一、项目背景 最近又及年底,各类分析与规划报告纷至沓来,于是接到了公司平台类目商品增长方向的分析需求,其中需要结合外部电商平台做对比。我选择了国内某电商平台作为比较对象,通过获取最细层级前台类目下的SKU数以及结构占比&…

免费分享一套PyQt6图书管理系统(附带完整开发视频教程) Python入门项目实战,果断收藏了~~

大家好,我是python222_小锋老师,最近写了一套PyQt6图书管理系统源码,附带完整开发视频教程,作为Python学习者的入门实战项目,带大家一起入门学习Python技术,感谢大家支持,特来分享下哈。 项目实…

java小游戏——动漫美女拼图

1:继承 1.1 继承概述 首先,我们来说一下,什么是继承: 继承是面向对象三大特征之一(封装,继承和多态) 可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法 也就是说&…

生日视频模板-试试这样制作

视频制作已经成为表达情感、记录生活的重要方式。尤其在生日这样的特殊日子,一份个性化的视频祝福不仅能让人感到温馨,还能成为长久珍藏的回忆。那么,如何快速制作出精美的生日模版视频呢?下面就给大家介绍几种可以制作生日模版的…

论文阅读:Attention is all you need

【最近课堂上Transformer之前的DL基础知识储备差不多了,但学校里一般讲到Transformer课程也接近了尾声;之前参与的一些科研打杂训练了我阅读论文的能力和阅读源码的能力,也让我有能力有兴趣对最最源头的论文一探究竟;我最近也想按…

300块成本从零开始搭建自己的家庭版NAS还可以自动备份,懂点代码有手就行!

前言 300块成本从零开始搭建自己的家庭版NAS,还可以手机上文件照片音乐自动备份,完全实现了自己的网盘效果,可以设置用户权限分配,目录上传、断点续传、并行上传、拖拽文件上传等日常操作。 为什么要搭建NAS? 现在的手…

【数据库】间隙锁Gap Lock

什么是间隙锁 间隙锁(Gap Lock):间隙锁是(RR级别下)一个在索引记录之间的间隙上的锁,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。间隙锁(Gap Lo…

失踪人员信息发布与管理系统:计算机毕设课题的研究与实践 springboot+java+vue+mysql

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

Cesium 模型压平

最近整理了下手上的代码,以下是对模型压平的说明。 原理是使用了customShader来重新设置了模型的着色器,通过修改模型顶点的坐标来实现了压平。 废话不多说,下面上代码: /*** class* description 3dtiles模型压平*/ class Flat…

docker-ce 安装与国内源配置 | Ubuntu 20.04

博客原文 文章目录 让apt可以支持HTTPS将官方Docker库的GPG公钥添加到系统中将Docker库添加到APT里更新包列表为了确保修改生效,让新的安装从Docker库里获取,而不是从Ubuntu自己的库里获取,执行:安装 docker-ce配置 docker 阿里源…

Java多线程并发篇----第十四篇

系列文章目录 文章目录 系列文章目录前言一、ReadWriteLock 读写锁二、共享锁和独占锁三、重量级锁(Mutex Lock)四、轻量级锁前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给…

【图解数据结构】深入剖析时间复杂度与空间复杂度的奥秘

🌈个人主页:聆风吟 🔥系列专栏:图解数据结构、算法模板 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 一. ⛳️算法的定义二. ⛳️算法的特性2.1 🔔输入输出2.2 🔔输入输出2.3 &…

Multimodal Prototypical Networks for Few-shot Learning

tcGAN is provided with an embedding ϕ T \phi_T ϕT​() of the textual description 辅助信息 作者未提供代码

大模型中的显卡优化与分布式训练策略

目录 前言1 大模型训练优化的目标1.1 简单性1.2. 高效性1.3 廉价性 2 显存的组成与利用2.1 参数存储2.2 梯度计算与存储2.3 中间计算结果2.4 优化器信息 3 优化方法3.1 数据并行3.2 模型并行3.3 零冗余优化器(Zero Redundancy Optimizer)3.4 Pipeline并行…