【JavaEE初阶】——JVM介绍(面试高频)

文章目录

  • 前言
  • 一、进程和线程
  • 二、JVM进程
  • 三、JVM介绍
  •       3.1 JVM内存区域划分
  •       3.2 JVM类加载
  •       3.3 JVM垃圾回收(CG)
  • 四、JVM常见选择题
  • 总结


前言


一、进程和线程

在谈JVM的这些问题前,我们先来复习一下有关线程和进程的关系

进程:

进程可以看作是程序的执行过程。

一个程序的运行需要CPU时间、内存空间、文件以及I/O等资源。

操作系统就是以进程为单位来分配这些资源的,所以说进程是分配资源的基本单位。


线程:
线程从属于进程,只能在进程的内部活动,多个线程共享进程所拥有的的资源。

如果把进程看作是完成许多功能的任务的集合,那么线程就是集合中的一个任务元素,负责具体的功能。

虽然CPU、内存、I/O等资源分配给了进程,但实际上真正利用这些资源并在CPU上执行的却是线程,即真正完成程序功能的是线程。


因为进程作为这些资源的拥有者,它的负载很重,在进程的创建、切换、删除过程中的时间和空间开销都很大。

所以目前主流的操作系统都只将进程作为资源的拥有者,而把CPU调度和运行的属性赋予了线程。


比如打开浏览器程序,会产生相应的进程,浏览器进程中包含有许多线程,如HTTP请求线程,I/O线程,渲染线程,事件响应线程等。

浏览器进程拥有着内存和I/O资源等,但当我们在浏览器中输入文字时,真正使用I/O资源接收我们输入的文字,并在CPU处理文字的却是浏览器进程中的I/O线程。

即真正完成浏览器文字输入功能的是线程。


图示说明解析:

现代很多操作系统支持让一个进程包含多个线程,从而提高程序的并行程度和资源的利用率。


二、JVM进程

我们知道Java语言是需要运行在JVM上的。

实际上,JVM也是一个软件程序,这就意味着它执行起来也会在操作系统中创建进程,即JVM进程,通常又叫JVM实例。

而我们所写的main方法,实际上就是JVM进程中主线程的所在。


从操作系统的角度来看,我们常说的Java程序,应该包括JVM和我们编写的Java代码。

当我们写完Java代码,并编译成class文件后,使用Java命令执行main方法;或者直接在IDE启动main方法时,JVM程序就会执行,操作系统会将其从磁盘中装入内存,并创建一个JVM进程,随后启动主线程,主线程会去调用某个类的 main 方法,因此这个主线程就是我们写的main方法所在。


实际上,JVM本身就是一个多线程应用,即使我们在代码中并没有手动的创建线程,JVM进程也并不是只有一个主线程,而是也会有其他线程。

这些线程完成着JVM的功能,如GC线程负责回收JVM使用过程中的垃圾对象。

JVM进程启动完成后,必然会有的线程如下:


至此,我们知道了,启动一个Java程序,本质上就是启动JVM程序,并在操作系统中创建一个JVM进程。

这个JVM进程会由操作系统分配许多资源,如内存、I/O等。JVM进程中包含有许多线程,这些线程共享JVM进程分配到的资源,同时这些线程也是CPU核心上执行的实体,它们完成着JVM所具有的功能。


同时我们通过实验也能发现,启动多少个java程序,就会创建多少个JVM进程(JVM实例)。

每个实例都是独立的,互不影响,即一个程序(一个JVM软件程序)可以被多个进程共用(创建多个JVM进程或者说JVM实例)


三、JVM介绍

3.1 JVM内存区域划分

总的来说,JVM大致可以分为四部分:

  • 方法区
  • 程序计数器

大家对java中的变量应该都不陌生吧!变量分为全局变量、局部变量、静态变量;

注意:

我们这里说的是JVM中的栈和堆,和操作系统的栈和堆、数据结构中的栈和堆是不同的。

大家以后再被问到栈和堆的时候,一定要搞清楚是哪里面的栈和堆。

举例说明:

代码示例:

public class test {public int a; // 全局变量(也可叫做test这个类的成员变量)public static int b; // 静态变量public void method() {int c = 0; // 局部变量System.out.println("这是test这个类的一个普通成员方法");}public static void run() {System.out.println("这是一个静态方法!"); // 静态方法不需要借助实例化对象}public static void main(String[] args) {test test1 = new test(); // test1 是test类的一个实例化对象test test2 = new test(); // test2 是另一个实例化对象}
}

局部变量就是存储在栈上的,

全局变量属于我们new出来的实例化对象的一部分,储存在堆上,

静态变量就比较特殊了,他存储在方法区中。

那么我们栈上还有什么东西呢?

还有我们类中各个方法间的调用关系。


在回到堆中,我们到我们new出来的实例化对象是存储在堆上的,我们的实例化出来的每个对象都有他对应的变量和方法(即我们的成员方法和成员变量),他们自然和对象一起都储存在堆上。


那静态变量和静态方法呢?

他们不属于我们实例化出来的对象,他们是在我们我们这个类创建出来的时候就存在了,不依托实例化对象。他们属于类对象,我们方法区里放到就是类对象。


那么类对象里有啥呢?

包括类是啥名字

继承自谁,实现了那些接口

有啥属性,属性名是啥,类型是啥,访问权限是啥

有什么方法,方法名是?参数是?返回值?访问权限?方法内部的指令是?方法里面干了什么?


总之类对象对我们这个类做了一个整体的描述,

一个类可以有多个实例化对象,但只有一个类对象

(即每个静态变量和静态方法在不同的实例化对象中也只有一个)。


总结一下

  • 栈(方法之间的调用关系、局部变量)
  • 堆(实例化出来的对象:全局变量(也叫成员变量)、成员方法)
  • 方法区(类对象:静态变量、静态方法....)

程序计数器:
占地最小的区域:只是单纯的保存当前代码执行到哪个指令了(存储了下一个要执行的指令地址)

写好的代码,是被加载到内存里的(类对象中),既然是在内存中,每个指令都有对应的"地址"

程序计数器就是记录了当前执行到哪条指令了相当于一个"书签"这个也是和线程调度是有关系


就像我们上面说的,当我们启动一个java,启动main方法的时候,我们JVM程序就会执行,就会创建出来一个JVM进程,同时还会有多个线程来负责完成JVM的工作。

那么我想问,是每个线程都有上面这四个区域吗?


不是的,我们的方法区 和 堆是整个JAVA进程中只有一份的(该进程内的多个线程共享这一份资源),但程序计数器和栈,则是每个线程都有一份。


为啥呢??

操作系统cpu等相关资源分配给进程,该进程内的所有线程共享该进程的所有资源,线程是执行的基本单位。

每个线程在执行各自执行各自的代码,各自是一个执行流,所有说每个线程都需要知道接下来要执行的指令是什么(程序计数器的功能)?每个线程也需要记录下当前的调用栈(存在方法区)


图示说明:


3.2 JVM类加载

Java程序启动的时候,就需要让JVM把class文件给读进内存并进行一系列后续的工作。

类加载流程:

1、加载  找到class文件,打开文件,读文件,创建空的类对象


2、链接

  • 验证 —— 检查.class文件格式是否符合规范要求(JVM规范中明确描述了)
  • 准备 —— 给静态变量分配内存空间,空间里填充0值。
  • 解析 —— 把字符串常量进行初始化,把“符合引用替换成直接引用”


3、初始化

针对类的静态成员进行初始化,执行静态代码块,如果这个类的父类还没加载,也要去加载父类。


面试官最爱考的就是

——“双亲委派模型”(描述了是类加载中的加载阶段,去那些目录里找.class文件)

为了理解所谓的双亲委派模型,我们需要知道:

类加载器——JVM中特殊的模块,功能就是负责把类给加载起来,完成类加载的工作。


图示说明:


3.3 JVM垃圾回收(CG)

大家还记得吗?在C语言中,我们通过malloc动态申请内存(申请的内存是在堆中),每次申请完后都要我们手动释放内存(free)。

如果不释放就回造成内存泄漏等严重问题。但是如果光指望我们程序员手动释放内存,那显然是不靠谱的。

为在Java中就由机器负责回收不再使用的内存空间——这种机制就被称为内存回收机制(garbage collection简称GC)

高频面试题目


1、垃圾回收中,回收的是什么?


2、如何确定该对象是需要回收的?

那么我们知道了回收的单位是对象,那么我们如何具体确定某个对象就是垃圾(不再使用了呢)呢?


确定是不是垃圾,有很多种办法。其中Java里主要使用的是“可达行分析”这种办法,

在别的编程语言中(比如Python)中使用的是“引用计数这种方法”。


注意:

在《深入理解Java虚拟机》这本书中,这两种办法都有提到。

  • 那么如果我们在面试中被问到:在垃圾回收机制中,如何判断对象是不是垃圾?你可以两个都说。
  • ​​​​如果问的是:在JVM中,如何判断对象是不是垃圾,你只需回答“可达性分析”就行。

 引用计数法

使用额外的计数器,来记录对于某个对象来说,有多少引用指向他。

要想使用对象,就需要有引用指向他,如果没用引用了——引用计数为0了,说明该对象无法被使用了,也就是需要回收的垃圾了。



可达性分析(Java真正采取的方法)

可达性,什么意思呢?

就是以代码中的一些特殊变量为起点,然后以起点触发,看看那些对象都能被访问到。

只要对象能访问到,就标记为“可达”,当完成一圈标记后,剩下的就是“不可达“的了,也就是要回收的垃圾了!!!


我们对上面的一些名词做一些解释

一、什么样的变量可以可以称为起点(GCRoot)呢?

1、局部变量表中的对对象的引用(栈里面的局部变量,栈有多个,每个线程一个,每个栈里面又有很多的栈帧,每个栈帧里有一个自己的局部变量表。)

意思就是:所有线程的所有栈的所有栈帧的所有的局部变量表中的全部的变量,都可视为GCRoot.

2、常量池中对应的对象

3、方法区中,静态引用类型的成员


二、什么叫做”能够被访问到?

图示说明:

可达性分析相比于引用计数来说,不会占用额外的内存空间;

也不会涉及到循环引用的问题;


3、确定要回收的对象后,如何具体进行垃圾回收?

有以下几个笔记经典的垃圾回收算法(策略)

1、标记-清除


2、复制算法(为了解决内存碎片化问题)


3、标记整理(类似于顺序表删除元素)


 4、分代回收


分代回收总结:

  1. 在伊甸区,新生的对象,如果活过了一轮GC(一轮GC以及把大部分对象给回收了,活过一轮GC的是少数),就把这些幸存的对象放到幸存区(因为对象少,所以幸存区的空间不大)
  2. 幸存区的对象使用复制算法,因为数量较少,即使浪费了一半的内存也没关系。
  3. 老年代的对象使用标记整理算法,因为老年代对象他被回收的频率不高,就可以接收标记整理带来的开销

图示总结说明:

1.堆内存为两个区:新生代和老年代;

2.新生代默认占堆内存的1/3,老年代默认占堆内存的2/3;

3.新生代又分为Eden区、Survivor From区、Survivor To区默认比例是8:1:1 ;

4.工作过程:

  1. 所有新创建的对象都在Eden区,当Eden区内存满后将Eden区+Survivor From区存活的对象复制到Survivor To区;
  2. 清空Eden区与Survivor From区;
  3. 同时Survivor From与Survivor To分区进行交换;
  4. 每次Minor Gc存活对象年龄加1,当年龄达到15(默认值)岁时,被移到老年代;
  5. 当Eden的空间无法容纳新创建的对象时,这些对象直接被移至老年代;
  6. 当老年代空间占用达到阈值时,触发Major GC;
  7. 以上流程循环执行。

四、JVM常见选择题

GC Roots的判断

题目:


解析:


JVM的实现

题目:

属于JVM在Java中的实现的是


解析:


类加载器

题目:


解析:


垃圾回收器和垃圾回收算法的区别

题目:


解析:


JVM内存划分

题目:


解析:

总结

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

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

相关文章

在Springboot中将数据渲染到前端页面1.0

前端数据代码&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <emps><emp><name>金毛狮王</name><age>55</age><image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/1.jpg</image…

RK3568 android 13 内置 google GMS服务

需求&#xff1a;Android 系统在国外使用安装app很多需要gms服务&#xff0c;否则无法正常使用&#xff0c;所以出厂前必须要把GMS包集成进系统 1.下载gms包https://download.csdn.net/download/qq_46524402/88136401 2.解压gms包 并放到Android SDK根目录的vender文件夹下 3…

NSSCTF第14页(1)

[suctf 2019]checkin 利用了几种方式&#xff0c;发现都不行 1是修改mime类型&#xff0c;2是修改php标签为js标签&#xff0c;3是修改文件后缀 在试试用配置文件来上传 发现上传.user.ini文件成功 发现上传成功 上传的png图片 访问上传路径发现可以访问&#xff0c;上马成…

【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目

解决idea至少创建jdk17项目 问题idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗?解决 问题 idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗? 我本来以为是 IDEA 版本更新导致的 Bug&#xff0c;开始还没在意。 直到我今天自己初始化项目时才发现&…

解决VS2019无法正常显示XAML设计界面问题

问题描述 当VS2019配置工程为x64模式时&#xff0c;打开工程中XAML页面可能出现如下错误提示&#xff0c;进而无法正常显示XAML设计界面。 There was an exception when loading the design time assembly C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\16.0_…

某60物联网安全之IoT漏洞利用实操2学习记录

物联网安全 文章目录 物联网安全IoT漏洞利用实操2&#xff08;内存破坏漏洞&#xff09;实验目的实验环境实验工具实验原理实验内容实验步骤ARM ROP构造与调试MIPS栈溢出漏洞逆向分析 IoT漏洞利用实操2&#xff08;内存破坏漏洞&#xff09; 实验目的 学会ARM栈溢出漏洞的原理…

二.运算符

运算符 1.算术运算符2.比较运算符3.逻辑运算符 1.算术运算符 算数运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达式&#xff0c;对数值或表达式进行 - * / 和 取模%运算 1.加减法运算符 mysql> SELECT 100,100 0,100 - 0,100 50,100 50 - …

输入通道数 和 输出通道数 的理解

输入通道数&#xff08;in_channels&#xff09;输出通道数&#xff08;out_channels&#xff09; 在卷积神经网络中通常需要输入 in_channels 和 out_channels &#xff0c;即输入通道数和输出通道数&#xff0c;它们代表什么意思呢&#xff1f; 输入通道数&#xff08;in_c…

nexus

一、nexus介绍二、nexus部署部署java环境安装配置nexus浏览器访问 三、创建一个内网yum源四、创建一个代理yum仓库五、jenkins 使用 nexus插件jenkins部署maven-proxy配置 maven 工程查看构建和上传 一、nexus介绍 Nexus 是一个强大的仓库管理工具&#xff0c;用于管理和分发 …

linux用户组管理_创建删除密码修改

2.2 用户/组管理 2.2.1 用户 2.2.1.1 useradd&#xff1a;创建用户 添加用户账号就是在系统中创建一个新账号&#xff0c;然后为新账号分配用户号、用户组、主目录和登录Shell等资源。 useradd命令的基本语法如下&#xff1a; useradd 选项 用户名 常见选项参数&#xff…

瑞云科技参与《数字孪生世界白皮书》编写,实时云渲染助力数字孪生

为了促进数字孪生技术的发展和应用&#xff0c;易知微与数字孪生世界企业联盟联合众多行业专家以及多家业内企业共同编写了《数字孪生世界白皮书&#xff08;2023&#xff09;》。该白皮书从数字孪生的综述、应用架构、核心技术、新型技术成果和重点行业应用等方面&#xff0c;…

【算法刷题】Day9

文章目录 611. 有效三角形的个数![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d627e680e9144a2b67474a1d80aa030.png)题解&#xff1a;代码&#xff1a; LCR 179. 查找总价格为目标值的两个商品题解&#xff1a;代码&#xff1a; 611. 有效三角形的个数 原题链…

端口隔离度

端口隔离度 隔离度为&#xff08;本振或射频信号&#xff09;泄漏到其他端口的功率与输入功率之比&#xff0c;单位是dB。 比如 RF to LO Isolation 表示 射频输入信号的功率 与 泄漏到LO端口的功率 之比。 而 LO to RF Isolation 则表示 本振输入信号的功率 与 泄漏到RF端口的…

Ubuntu部署jmeter与ant

为了整合接口自动化的持续集成工具&#xff0c;我将jmeter与ant都部署在了Jenkins容器中&#xff0c;并配置了build.xml 一、ubuntu部署jdk 1&#xff1a;先下载jdk-8u74-linux-x64.tar.gz&#xff0c;上传到服务器&#xff0c;这里上传文件用到了ubuntu 下的 lrzsz。 ubunt…

Spring-AOP与声明式事务

为什么要用AOP ①现有代码缺陷 针对带日志功能的实现类&#xff0c;我们发现有如下缺陷&#xff1a; 对核心业务功能有干扰&#xff0c;导致程序员在开发核心业务功能时分散了精力 附加功能分散在各个业务功能方法中&#xff0c;不利于统一维护 ②解决思路 解决这两个问题&…

TOUGH系列软件解读

TOUGH系列软件是由美国劳伦斯伯克利实验室开发的&#xff0c;旨在解决非饱和带中地下水、热运移的通用模拟软件。和传统地下水模拟软件Feflow和Modflow不同&#xff0c;TOUGH系列软件采用模块化设计和有限积分差网格剖分方法&#xff0c;通过配合不同状态方程&#xff08;EOS模…

同旺科技 分布式数字温度传感器

内附链接 1、数字温度传感器 主要特性有&#xff1a; ● 支持PT100 / PT1000 两种铂电阻&#xff1b; ● 支持 2线 / 3线 / 4线 制接线方式&#xff1b; ● 支持5V&#xff5e;17V DC电源供电&#xff1b; ● 支持电源反接保护&#xff1b; ● 支持通讯波特率1200bps、2…

使用Java对yaml和properties互转,保证顺序、实测无BUG版本

使用Java对yaml和properties互转 一、 前言1.1 顺序错乱的原因1.2 遗漏子节点的原因 二、优化措施三、源码 一、 前言 浏览了一圈网上的版本&#xff0c;大多存在以下问题&#xff1a; 转换后顺序错乱遗漏子节点 基于此进行了优化&#xff0c;如果只是想直接转换&#xff0c…

1.3 排序算法

1.1 冒泡排序 public class BubbleSort {public static void main(String[] args) {int[] arr {133,322,13,444,54,621,174,18,19,2};System.out.println(Arrays.toString(arr));BubSort(arr);System.out.println(Arrays.toString(arr));}//冒泡排序public static void BubSo…

21.Oracle的程序包(Package)

Oracle的程序包Package 一、Package的概述1、什么是Oracle11g的Package2、Package的作用是什么3、常见的系统内置Package 二、创建Package的相关语法1、Package的创建语法2、Package的删除3、具体案例4、Package的使用5、与Package相关的其他语法 三、常见内置程序包的使用1、…