面试篇:JVM虚拟机

news2024/11/27 4:36:58

一、JVM介绍,JVM运行流程

1、什么是JVM

Java Virtual Machine:Java程序的运行环境 (java二进制字节码的运行环境)

好处:

  • 一次编写,到处运行
  • 自动内存管理,垃圾回收机制

2、JVM运行流程

 

二、什么是程序计数器?

程序计数器:线程私有的,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。

对于每个方法,都会将代码转换为字节码,字节码中的行号就是代码的执行顺序,而每个线程根据自己的程序计数器来确定执行的行号

 

 如上图,对于线程1,从第1行开始执行,执行到第10行之后切换到了线程2。线程2从第1行开始执行,执行到了第9行,然后又切换到了线程1,但是此刻线程1不是从第1行开始执行的,而是根据自己的程序计数器来确定继续从第10行往下执行。

1、概括

什么是程序计数器?

  • 线程私有的,每个线程一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。

三、详细介绍一下堆

1、介绍

Java堆是一个线程共享的区域:主要用来保存对象实例,数组等,当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。

如上图是Java7和Java8的内存结构

首先说Java8,Java8中有年轻代和老年代。年轻代分为伊甸园(Eden)和两个幸存区(Survivor )。新产生的对象就会存放在伊甸园区,当进行Minor GC的时候就会将伊甸园中的部分垃圾回收,存留下来的会保存到幸存区。当幸存区的对象年龄超过15次时候没被垃圾回收就会进入老年代。详细步骤后面会进行讲解。

方法区保存的是Class类。Java8将方法区/永久代取消了,转到了本地内存。因为Java7中的方法区/永久代如果空间设置少了,就会造成堆空间内存溢出出现OOM,空间设置大了,就会造成堆空间浪费。所以移动到了本地内存。

2、概括

你能给我详细的介绍Java堆吗?

  • 线程共享的区域:主要用来保存对象实例,数组等,内存不够则抛出OutOfMemoryError异常。
  • 组成:年轻代+老年代
    • 年轻代被划分为三部分,Eden区和两个大小严格相同的Survivor区
    • 老年代主要保存生命周期长的对象,一般是一些老的对象

Jdk1.7和1.8的区别

  • 1.7中有有一个永久代,存储的是类信息、静态变量、常量、编译后的代码。
  • 1.8移除了永久代,把数据存储到了本地内存的元空间中,防止内存溢出。

四、什么是虚拟机栈 ?

Java Virtual machine Stacks (java 虚拟机栈)

  • 每个线程运行时所需要的内存,称为虚拟机栈,先进后出。
  • 每个栈由多个栈帧(frame) 组成,对应着每次方法调用时所占用的内存,栈帧保存的是当前方法的参数、局部变量、返回地址等。
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。

在这里插入图片描述

1、垃圾回收是否涉及栈内存?

垃圾回收主要指就是堆内存,当栈帧弹栈以后,内存就会释放

2、栈内存分配越大越好吗?

未必,默认的栈内存通常为1024k栈帧过大会导致线程数变少,例如,机器总内存为512m,目前能活动的线程数则为512个,如果把栈内存改为2048k,那么能活动的栈帧就会减半

3、方法内的局部变量是否线程安全?

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的。
  • 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全。

如上图:

  • 对于方法m1,它是线程安全的,因为方法没有局部变量和返回值,所以不存在被其他线程修改的情况。
  • 对于方法m2,它是线程不安全的,因为方法有局部变量,存在着被其他线程修改的情况。
  • 对于方法m3,它是线程不安全的,因为方法有返回值,这个返回值可能存在被其他线程修改的情况。

4、栈内存溢出情况

  • 栈帧过多导致栈内存溢出,典型问题:递归调用
  • 栈帧过大导致栈内存溢出

5、概括

什么是虚拟机栈?

  • 每个线程运行时所需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

垃圾回收是否涉及栈内存?

  • 垃圾回收主要指就是堆内存,当栈帧弹栈以后,内存就会释放

栈内存分配越大越好吗?

  • 未必,默认的栈内存通常为1024k,栈帧过大会导致线程数变少

方法内的局部变量是否线程安全?

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
  • 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全

什么情况下会导致栈内存溢出?

  • 栈帧过多导致栈内存溢出,典型问题:递归调用
  • 栈帧过大导致栈内存溢出

堆栈的区别是什么?

  • 栈内存一般会用来存储局部变量方法调用,但堆内存是用来存储Java对象和数组的的。堆会GC垃圾回收,而栈不会
  • 栈内存是线程私有的,而堆内存是线程共有的
  • 两者异常错误不同,但如果栈内存或者堆内存不足都会抛出异常
  • 栈空间不足: java.lang.StackOverFlowError。
  • 堆空间不足:java.lang.OutOfMemoryError。

五、请解释下方法区

1、介绍方法区

  • 方法区(Method Area)是各个线程共享的内存区域。
  • 主要存储类的信息、运行时常量池。
  • 虚拟机启动的时候创建,关闭虚拟机时释放。
  • 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError: Metaspace。

JDK1.8中将方法区移动到了直接内存的元空间中

2、 常量池

可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息。

首先如左图,里面有方法的机器指令,当执行行号为0的字节码指令的时候,就会根据该行字节码#2然后到常量池表中找到#2所在的位置,然后进行翻译,这样才能执行该行的指令,知道该行指令的作用。

3、运行时常量池

常量池是*.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址

如上图,运行时常量池将符号改为内存地址。因为只有获得真正的内存地址才能执行代码指令

4、概括

能不能解释一下方法区?

  • 方法区(Method Area)是各个线程共享的内存区域
  • 主要存储类的信息、运行时常量池
  • 虚拟机启动的时候创建,关闭虚拟机时释放
  • 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError:Metaspace

介绍一下运行时常量池

  • 常量池:可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名方法名、参数类型、字面量等信息
  • 当类被加载,T它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址 

 

六、堆,虚拟机栈,方法区分别存储的是什么?

1、堆

堆存储的是使用new关键字创建的类(对象或者类的实例)或者数组的(含成员变量)

2、栈

栈存放的是基本类型的变量数据对象的引用

对象的声明引用解释:

对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中),在Java中,当我们使用new关键字创建一个对象时,这个对象会被存储在堆中,并返回一个引用,这个引用会被存储在栈中。这个引用指向了堆中的对象,我们可以通过这个引用来访问和操作这个对象 。

public class StackExample {
    public static void main(String[] args) {
        // 声明一个int类型的变量num,存储在栈中
        int num = 10;
        // 声明一个String类型的变量name,存储在栈中
        String name = "Bing";
        // 输出num和name的值
        System.out.println(num + " " + name);
    }
}

3、方法区

Java方法区(Method Area)用于存储已被虚拟机加载的类信息、常量、静态变量、动态生成的类等数据。方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。

七、请解释直接内存

直接内存:并不属于JM中的内存结构,不由JVM进行管理。是虚拟机的系统内存,常见于 NIO 操作时,用于数据缓冲区,它分配回收成本较高,但读写性能高。

Java代码完成文件拷贝

1、常规IO数据拷贝流程

 java本身不具备磁盘的读写功能,如果调用磁盘读写,必须调用操作系统所提供的函数。

当调用操作系统所提供的IO方法的时候,就会设计CPU的状态切换,首先从用户态切换到内核态,当切换到内核态的时候,就通过系统提供的函数读取磁盘中的文件,读取的文件会分批次保存在操作系统内存划出的一片系统缓存区。但是系统缓存区java无法去获取,所以java会在堆中分配一片内存名为java缓冲区,将系统缓存区读到java缓冲区中。

读到java缓冲区后CPU切换到用户态,通过输出流写出操作,反复读取,然后将文件读到目标位置。

但是有个问题就是两个缓冲区会对性能产生巨大的影响

2、NIO数据拷贝过程

 NIO不在使用两个缓冲区,而是直接使用直接内存来代替缓冲区,因此性能大幅提高

3、概括

你听过直接内存吗?

  • 并不属于JVM中的内存结构,不由JVM进行管理。是虚拟机的系统内存
  • 常见于 NIO操作时,用于数据缓冲区,分配回收成本较高,但读写性能高,不受JVM内存回收管理

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

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

相关文章

Rufus v4.0.2035 开源USB引导启动盘制作工具单文件版

Rufus 是一个可以帮助格式化和创建可引导USB闪存盘的工具,比如 USB 随身碟,记忆棒等等。在如下场景中会非常有用:你需要把一些可引导的ISO格式的镜像(Windows,Linux,UEFI等)创建成USB安装盘的时…

Selenium自动化测试之使用真实用户Chrome环境

Selenium每次打开Chrome浏览器时,每次都是一个初始的全新环境,有时候,我们需要一些当前用户的一些设置和插件等,便可以通过ChromeOptions参数,通过指定用户数据目录--user-data-dir来设置成真实用户目录来实现。 浏览…

【剑指offer】学习计划day2

目录 一. 前言 二. 从尾到头打印链表 a.题目 b.题解分析 c.AC代码 二. 反转链表 a.题目 b.题解分析 c.AC代码 三. 复杂链表的复制 a.题目 b.题解分析 c.AC代码 一. 前言 本系列是针对Leetcode中剑指offer学习计划的记录与思路讲解。详情查看以下链接: 剑指of…

KF-GINS开源代码讲解直播课PPT和学习资源

KF-GINS开源代码讲解直播课PPT和学习资源 文章目录 KF-GINS开源代码讲解直播课PPT和学习资源KF-GINS 组合导航算法原理KF-GINS 代码设计KF-GINS 代码实现KF-GINS 常见问题KF-GINS 扩展直播的部分问题 武汉大学i2Nav团队开源的基于卡尔曼滤波的GNSS/INS组合导航系统(…

【UmiJS项目】react-monaco-editor代码编辑器的安装与使用

一、git地址 monaco-editorreact-monaco-editor 二、安装 yarn add monaco-editor yarn add react-monaco-editor yarn add monaco-editor-webpack-plugin注意: monaco-editor 和 monaco-editor-webpack-plugin 需要按照以下对应版本来安装 本人使用的版本如下&a…

西门子PLC加减速时间的算法

1、新建工艺对象,在“动态”中可以设置最大转速(30.0)和启动/停止转速(2.0)以及加减速时间(也可以计算得出)。 加速度的计算方法为:(最大转速-启动/停止速度)…

ChatGPT、Midjourney不香了吗,New Bing 已向全球个人开放

文章目录 1. 前言2. 教程3. 开始 Bing AI 以上图片均由Bing AI生成。(后文给出第一幅图的关键字) 本文没有任何广告,放心食用,并且手把手教你怎么配置new bing,有需要的耐心看完哦,不懂的可私信我~ 1. 前…

Yarn安装及配置一件启停

Yarn安装及配置一件启停 数据、程序、运算资源(内存、CPU)三者组在一起,才能完成数据的计算处理过程。在单机环境下,三者之间协调配合不是太大问题。为了应对海量数据的处理场景,Hadoop软件出现并提供了分布式处理思想。但是在分…

数据结构——双向链表(保姆级教程,包学包会)

1.双向链表的概念 双向链表就是带头双向循环链表 我们在学完单链表之后,就感觉这个非常简单了,他的主要表现就是拥有头节点,链表永不为空,不需要二级指针;可以通过一个节点找到上一个或者下一个节点;头尾…

MySQL基础-事务详解

本文主要介绍MySQL事务 文章目录 前言事务定义事务四大特性(ACID) 事务操作事务并发问题事务隔离级别 前言 参考链接: 链接1链接2 事务定义 事务是一组操作的集合,他是一个不可分割的工作单位,事务会把所有的操作作…

微服务入门SpringCloud

一、微服务的组成 注册中心:记录每个微服务调用地址、ip 配置中心:管理每个服务的配置 服务网关:身份校验, 分布式缓存:提升访问数据库的速度。 分布式搜索:海量缓存 消息队列:异步消息&#x…

【C++】还new不出对象?看看C++怎么做~(C++内存管理)

🧑‍🎓个人主页:简 料 🏆所属专栏:C 🏆个人社区:越努力越幸运社区 🏆简 介:简料简料,简单有料~在校大学生一枚,专注C/C/GO的干货分…

Redis---订阅和发布

目录 消息系统命令 消息系统 ​ 发布/订阅,即 pub/sub,是一种消息通信模式:发布者也称为消息生产者,生产和发送消息到存储系统;订阅者也称为消息消费者,从存储系统接收和消费消息。这个存储系统可以是文件系…

安全多方计算:安全定义

参考文献:《密码协议》课程 PPT 文章目录 UM & AM安全定义编译器 Semi-honest & Malicious安全定义半诚实模型恶意模型 编译器Input-CommitmentAugmented Coin-TossingAuthenticated Computation编译器框架 UM & AM 安全定义 异步网络下的多方协议&am…

关于 Kafka 分区程序的关键细节

Apache Kafka 是当今事件流的事实标准。Kafka 如此成功的部分原因是它能够处理大量数据,每秒吞吐量达到数百万条记录,这在生产环境中并非闻所未闻。Kafka设计的一部分使这成为可能,那就是分区。 Kafka 使用分区将数据负载分散到集群中的代理…

UFT描述性编程及综合练习

1、录制登录操作改描述性编程。 登录的用户名、密码在global表中给出。有2组:自己的学号/mercury,自己的学号/123456。将登录的本地对象库清空。 要求: 分别采用直接描述性编程和Description描述性编程实现2组数据登录测试,用repo…

pikvm系统主要软件包解析备忘

PI-KVM让普通家用PC也有能够像数据中心机房里面的IP-KVM一样的功能。 详细信息参考官网:PiKVM HandbookOpen and cheap DIY IP-KVM on Raspberry Pihttps://docs.pikvm.org/ nullOpen and inexpensive DIY IP-KVM based on Raspberry Pi - GitHub - pikvm/pikvm: O…

LeetCode - 34 在排序数组中查找元素的第一个和最后一个位置

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode) 题目描述 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在…

【项目笔记】若干基本社团发现算法介绍

两个衡量指标:边介数 & 模块度 边介数计算: 以下用图来自:https://blog.csdn.net/weixin_44704845/article/details/102686597 选择S为源节点对图搜索,画出S到其他节点的最短路径树 2.给边标数字 1) 所有邻近叶…

【YOLO系列】--YOLOv4超详细解读/总结(网络结构)

YOLOv4(YOLOv4: Optimal Speed and Accuracy of Object Detection)(原文+解读/总结+翻译) 系列文章: YOLOv1论文解读/总结_yolo论文原文_耿鬼喝椰汁的博客-CSDN博客 YOLOv2论文解读/总结_耿鬼…