【Java面试】二十、JVM篇(上):JVM结构

2024-06-19 07:12
文章标签 java jvm 面试 结构 二十

本文主要是介绍【Java面试】二十、JVM篇(上):JVM结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1、JVM
  • 2、程序计数器
  • 3、堆
  • 4、栈
    • 4.1 垃圾回收是否涉及栈内存
    • 4.2 栈内存分配越大越好吗
    • 4.3 方法内的局部变量是否线程安全吗
    • 4.4 栈内存溢出的情况
    • 4.5 堆和栈的区别是什么
  • 5、方法区
    • 5.1 常量池
    • 5.2 运行时常量池
  • 6、直接内存

1、JVM

Java源码编译成class字节码后,JVM负责class字节码的处理。不同操作系统下的JVM,将字节码处理成对应操作系统下的二进制文件,从而实现一次编译,到处运行。能到处运行,是因为不同操作系统有不同的JVM,也即编译后的class字节码和操作系统之间,隔着一个JVM在干活儿。

简单的理解,JVM就是Java二进制字节码的运行环境,是JDK包下包含的一些代码,像一个虚拟的计算机一样处理着class字节码。
在这里插入图片描述

JVM有两个最大的亮点:

  • 处理class字节码,实现一次编译,到处运行
  • 自动内存管理,垃圾回收机制,创建的对象,用完后不用手动回收

JVM的组成:

在这里插入图片描述

2、程序计数器

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

在这里插入图片描述

如上,线程1 执行字节码从第0行到第10行后,CPU时间片用完,线程1的程序计数器记录下当前行号。CPU的时间片分给了线程2 ,线程2执行到第9行后,CPU时间片用完。线程1再次抢到时间片,继续执行,此时,根据线程1的程序计数器,CPU就知道该从第10行继续往下执行。

3、堆

  • 堆区,线程共享
  • 保存着创建出来的对象
  • use、total、max,use == max 后,无法再分配空间,堆内存溢出

堆中有年轻代和老年代。年轻代有三部分,伊甸园区和两块大小相同的幸存者区。根据JVM策略,新创建的对象在伊甸园区,伊甸园区满了以后,触发Young GC,GC后或者的对象,复制到幸存者区,后面每GC一次,活着的对象年龄加一(对象头里存着年龄),对象GC年龄到达阈值(如15)后,晋升到老年代。

在这里插入图片描述

元空间里存类的信息、静态变量、常量、编译后的字节码信息(InstanceKlass对象(c++))。对JDK7和8,其位置变化:

  • JDK7及以前,方法区在堆区的永久代空间里
  • JDK8及以后,永久代被移除,用元空间代替,方法区在元空间,而元空间在操作系统的直接内存里,理论上可以一直分配

在这里插入图片描述

因为永久代/方法区或者说后来的元空间,存储的主要是一些类信息和常量,需求开发,加载的类越来越多,这个空间不可控,移除永久代,在本地内存放个元空间,可以防止OOM

4、栈

栈,即每个线程运行时需要的内存空间,保存着该线程方法调用的基本数据,先进后出,其中,每一个调用的方法用一个叫栈帧的东西存。

在这里插入图片描述

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

垃圾回收处理的主要是堆内存,对于栈内存,栈帧弹栈后,内存就会释放

4.2 栈内存分配越大越好吗

默认1024k,栈帧过大会导致线程数变少,机器总内存为512m,目前能活动的线程数则为512个,如果把内存改为2048k,则可活动的线程数上限在栈内存方面就会减半

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

在方法的作用范围之内,是线程安全的。出了方法,被怎么使用就不一定了。如下:

在这里插入图片描述

每个线程过来,都会在自己的栈里创建一个m1方法对应的栈帧,栈帧里存着局部变量sb,因此线程安全。

对m2方法来说,局部变量sb是传过来的,那可能就有线程安全问题,如上面main线程中在操作sb,新开的一个线程也在操作sb。同理,m3方法,将局部变量sb return,后面可能被一个成员变量接收,但后面本质上也不关局部变量的事了

4.4 栈内存溢出的情况

  • 栈帧过多导致栈内存溢出,如递归调用
public static void m1() {m1();
}
  • 栈帧过大导致栈内存溢出

4.5 堆和栈的区别是什么

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

5、方法区

  • 方法区和堆一样,各个线程共享
  • 主要存储类的信息(InstanceKclass对象)、运行时常量池
  • 虚拟机启动的时候创建,虚拟机关闭的时候释放
  • 方法区的内存空间不够时,抛异常OutOfMemoryError:Metaspace
  • 方法区是一个概念,不同版本的JDK有不同的实现,对JDK7来说,永久代是其对方法区的落地实现(且此时永久代在堆区),对JDK8来说,则给方法区换了一种实现:元空间(元空间在本地内存)

在这里插入图片描述

5.1 常量池

javap查看一个类是字节码的结构信息:可以看到类的基本信息、常量池、方法的定义:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
常量池可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息

在这里插入图片描述

5.2 运行时常量池

上面提到,常量池是class文件中的,当这个类被加载,它的常量池信息就会放入到运行时常量池,并发里面的符号地址变为真实地址

在这里插入图片描述

常量池和运行时常量池的区别:

在这里插入图片描述

【区别】

6、直接内存

直接内存(操作系统分给JVM进程的内存之外的内存),不属于JVM内存,不由JVM进行管理。在进行NIO操作时,用于数据缓冲区,其分配回收成本高,但读写性能好。常规IO复制文件流程:

在这里插入图片描述

NIO复制文件流程:这块直接内存系统和Java代码都可以直接访问,少了一次缓冲区的复制操作

在这里插入图片描述

直接内存主要通过 java.nio 包下的 ByteBuffer 类来进行分配和使用。

ByteBuffer.allocateDirect(int capacity)

直接内存可以减少数据在 Java 堆和操作系统内存之间的拷贝次数,从而提高 I/O 的效率,常用于文件读写

【相关】

这篇关于【Java面试】二十、JVM篇(上):JVM结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1074351

相关文章

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.