JVM核心知识点梳理以及JVM面试题总结

【Flink】关于jvm元空间溢出,mysql binlog冲突的问题解决 :原理就是我们把原来7张在一个数据库的表放到一个flink source中读取,在指定传输到那个starrocks表时,官方已经实现了代码支持,我们只需要增加一个flink算子转换成sink支持的对象即可,(关联一个source对应多个sink解决思路)可以看官方的issues: https://issues.apache.org/jira/browse/FLINK-11205 https://issues.apache.org/jira/browse/FLINK-16408这里需要注意和以前的jar会造成 阅读详情

前言

关于JVM系列面试知识点总结了一个思维导图,分享给大家

 

内存结构

线程共享区域

堆(用于存放对象实例)

1、新生代

(1)Eden区

(2)Survivor(from)区(设置Survivor是为了减少送到老年代的对象 )

(3)Survivor(to)区 (设置两个Survivor区是为了解决碎片化的问题)

(4)eden:survivor:survivor = 8:1:1

2、老年代

老年代:新生代=2:1

方法区

1、运行时常量池

(1)Class 文件中的常量池(编译器生成的各种字面量和符号引用)会在类加载后被放入这个区域。

(2)存储信息

符号引用

1)符号引用包含的常量

  • 类符号引用

  • 方法符号引用

  • 字段符号引用

2)概念解释

一个java类(假设为People类)被编译成一个class文件时,如果People类引用了Tool类,但是在编译时People类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址。 即在编译时用符号引用来代替引用类,在加载时再通过虚拟机获取该引用类的实际地址。以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局是无关的,引用的目标不一定已经加载到内存中。

字面量

  • 文本字符串(String a = "abc",这个abc就是字面量)

  • 八种基本类型(int a = 1; 这个1就是字面量)

  • 声明为final的常量

2、静态变量

3、final类型常量

4、类信息

  • 类的完整有效名

  • 返回值类型

  • 修饰符(public,private...)

  • 变量名

  • 方法名

  • 方法代码

  • 这个类型直接父类的完整有效名(除非这个类型是interface或是 java.lang.Object,两种情况下都没有父类)

  • 类的直接接口的一个有序列表

线程私有区域

虚拟机栈

1、栈帧

(1)动态链接

  • 符号引用和直接引用在运行时进行解析和链接的过程,叫动态链接。

  • 前提是每一个栈帧内部都要包含一个指向运行时常量池的引用,来支持动态链接的实现。

(2)操作数栈

保存着Java 虚拟机执行过程中的数据

(3)局部变量表

1)局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

2)存放的信息

  • 基本数据类型

  • 对象引用

  • returnAddress类型

(4)方法返回地址

1)方法被调用的位置

2)方法退出的过程实际上就等同于把当前栈帧出栈

3)方法退出可能包含的操作

  • 恢复上层方法的局部变量表和操作数栈

  • 把返回值(如果有的话)压入调用者栈帧的操作数栈中

  • 调整PC计数器的值以指向方法调用指令后面的一条指令

2、异常

线程请求的栈深度大于虚拟机所允许的深度(StackOverflowError )

JVM动态扩展时无法申请到足够的内存时(OutOfMemoryError )

在编译程序代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的Code属性之中,因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

本地方法栈

和虚拟机栈类似,区别是本地方法栈为使用到的Native方法服务

程序计数器

1、如果线程正在执行的是一个Java方法,则指明当前线程执行的代字节码行数

2、此内存区域是唯一一个不会出现OutOfMemoryError情况的区域。

3、如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)

上述三个区域的生命周期和线程相同

直接内存

1、使用Native函数库直接分配堆外内存

2、并不是JVM运行时数据区域的一部分,但是会被频繁使用

3、避免了在Java 堆和Native 堆中来回复制数据,能够提高效率

内存分配

对象优先在Eden区分配

大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间分配时,虚拟机将发起一次Minor GC。

大对象直接进入老年代

最典型的大对象是那种很长的字符串以及数组。

长期存活对象进入老年区

如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将对象年龄设为1,对象在Survivor区中每熬过一次 Minor GC,年龄就增加1,当它的年龄增加到一定程度(默认为15)_时,就会被晋升到老年代中。

对象年龄动态判定

如果在 Survivor空间中相同年龄所有对象大小的综合大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代

空间分配担保

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的,如果担保失败则会进行一次Full GC;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。

内存回收

Minor GC

特点

发生在新生代上,发生的较频繁,执行速度较快

触发条件

  • Eden区空间不足

  • 空间分配担保

Full GC

特点

发生在老年代上,较少发生,执行速度较慢

触发条件

  • 调用 System.gc()

  • 老年代区域空间不足

  • 空间分配担保失败

  • JDK 1.7 及以前的永久代(方法区)空间不足

  • CMS GC处理浮动垃圾时,如果新生代空间不足,则采用空间分配担保机制,如果老年代空间不足,则触发Full GC

内存溢出

程序在申请内存时,没有足够的内存空间

内存溢出的构造方式

堆溢出

OutOfMemoryError:不断创建对象

栈溢出

StackOverflowError: 增大本地变量表,例如不合理的递归

OutOfMemoryError:不断建立线程

方法区和运行时常量池溢出

OutOfMemoryError:通过String.intern()方法不断向常量池中添加常量,例如String.valueOf(i++).intern()

本机内存直接溢出

内存泄漏

程序在申请内存后,无法释放已申请的内存空间

原因

长生命周期的对象持有短生命周期对象的引用

例如将ArrayList设置为静态变量,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏

连接未关闭

如数据库连接、网络连接和IO连接等,只有连接被关闭后,垃圾回收器才会回收对应的对象。

变量作用域不合理

例如,1.一个变量的定义的作用范围大于其使用范围,2.如果没有及时地把对象设置为null

内部类持有外部类

Java的非静态内部类的这种创建方式,会隐式地持有外部类的引用,而且默认情况下这个引用是强引用,因此,如果内部类的生命周期长于外部类的生命周期,程序很容易就产生内存泄漏

解决方法

  • 将内部类定义为static

  • 用static的变量引用匿名内部类的实例

  • 或将匿名内部类的实例化操作放到外部类的静态方法中

Hash值改变

在集合中,如果修改了对象中的那些参与计算哈希值的字段,会导致无法从集合中单独删除当前对象,造成内存泄露

常见面试题

1、java中会存在内存泄漏吗,请简单描述。

会。自己实现堆载的数据结构时有可能会出现内存泄露。

2、64 位 JVM 中,int 的长度是多数?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。

3、Serial 与 Parallel GC 之间的不同之处?

Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行。

4、32 位和 64 位的 JVM,int 类型变量的长度是多数?

32 位和 64 位的 JVM 中,int 类型变量的长度是相同的,都是 32 位或者 4个字节。

5、Java 中 WeakReference 与 SoftReference 的区别?

虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。

6、JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用

当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM主要动机在于可以指定最大堆大小,通过压缩OOP 可以节省一定的内存。通过-XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。

7、怎样通过 Java 程序来判断 JVM 是 32 位 还是 64位?

你可以检查某些系统属性如 sun.arch.data.model 或 os.arch 来获取该信息。

8、32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?

理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5GB,Solaris 大约3GB。64 位 JVM 允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

Java 中各种内存溢出的问题剖析 在Java开发领域,内存溢出(OutOfMemory,简称OOM)犹如一颗隐藏的“定时炸弹”,随时可能让程序崩溃,给用户带来糟糕的体验。今天,就让我们深入探究Java中各类内存溢出问题,了解其根源、排查方法以及有效的修改策略。 阅读详情

相关推荐

AstrBot插件开发全攻略:从零编写一个天气查询插件(Python实战)

本文提供了一份详细的AstrBot插件开发实战指南,手把手教你使用Python从零编写一个智能天气查询插件。内容涵盖插件系统核心设计、开发环境搭建、API调用与数据处理、自然语言交互实现以及插件打包发布全流程,帮助你快速掌握基于AstrBot框架的聊天机器人功能扩展技能。

weixin_29212867的博客 1084

微生物测序分析LEfSe

LEfse分析定义 LEfse分析即LDA Effect Size分析,可以实现多个分组之间的比较,还进行分组比较的内部进行亚组比较分析,从而找到组间在丰度上有显著差异的物种(即biomaker);

宁生信 5万+

【Mac+CLion+STM32+JLink】从零到一:在macOS上构建高效STM32开发与调试工作流

本文详细介绍了在macOS上使用CLion、STM32CubeMX和JLink搭建高效STM32开发与调试工作流的完整指南。从环境准备、CLion深度配置到STM32CubeMX工程实战,再到JLink烧录避坑和串口调试技巧,帮助开发者快速掌握Mac平台下的嵌入式开发全流程。

weixin_28278377的博客 254

GN算法边介数计算优化指南:如何提升大规模社交网络分析效率

本文深入探讨了GN算法在大规模社交网络分析中的核心瓶颈——边介数计算,并提供了从算法优化到工程部署的完整性能提升方案。通过引入Brandes算法、并行计算、增量更新及分布式处理等策略,有效解决了传统GN算法在处理百万级网络时效率低下的问题,为社交网络社区划分等实际应用提供了高效解决方案。

weixin_29196613的博客 486

HTML5+CSS3+JS小实例:扇形展开折叠菜单

你肯定见过那种圆形浮动按钮(FAB),点一下弹出几个选项。大部分实现就是菜单项从底下往上"弹"出来,排成一列——能用,但没啥记忆点。后来我看到 Path 那个经典的扇形菜单,点一下,五个按钮像花瓣一样从中心散开,每个带不同的延迟和弹性曲线。当时就觉得:这才对嘛,交互就该有点"戏剧性"。今天拆一个纯手写版本,HTML + CSS + JS,不依赖任何库。六菜单项、扇形 144° 展开、弹性过渡、点击关闭、键盘可达——该有的都有。

艾恩小灰灰的博客 164

MIKE水动力笔记4_制作网格

建立水动力模型前的重要一步就是制作网格,本文所讲内容就是如何在MIKE中制作网格。

晏长街的博客 2万+

嵌入式开发工程师笔试面试指南-Linux驱动

linux驱动

weixin_43491077的博客 473

Python之afdx包语法、参数和实际应用案例

Python 的 afdx 包是针对 AFDX 协议的轻量级开发工具,专注于 AFDX 数据帧的解析、构造、发送/接收、协议合规性校验等核心能力,广泛应用于航空电子设备测试、仿真、数据监控等场景。

王国平的博客 983

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 2万字JVM面试题含答案解析(2020年78道JVM面试题总结)
下一篇: Spring Boot已成为面试必备技能,学 Spring Boot,事不宜迟!
程序员追风
程序员追风 优质创作者: Java技术领域 优质创作者: Java技术领域
博客等级 码龄7年 9635粉丝 237原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值