面试 Java 基础八股文十问十答第二十四期

2024-04-13 12:52

本文主要是介绍面试 Java 基础八股文十问十答第二十四期,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

面试 Java 基础八股文十问十答第二十四期

作者:程序员小白条,个人博客

相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新!

⭐点赞⭐收藏⭐不迷路!⭐

1)类加载与卸载

在Java中,类加载是指将类的字节码加载到内存中,并生成对应的Class对象的过程。类加载器负责加载类文件的任务,Java虚拟机(JVM)在运行时动态加载类,使得程序可以在运行时引用这些类。

类加载的过程包括加载、链接和初始化三个阶段:

  • 加载(Loading): 将类的字节码从磁盘或网络加载到内存中。
  • 链接(Linking): 将类与其他类连接起来,包括验证、准备(为静态变量分配内存并初始化为默认值)和解析(将符号引用转换为直接引用)。
  • 初始化(Initialization): 执行类的初始化代码,包括静态变量赋值和静态代码块的执行。

类卸载是指当类在运行时不再需要时,由垃圾回收器将其从内存中删除的过程。类被卸载的条件是类加载器加载的类实例被回收,且该类所有的实例都已经被回收。类卸载是Java虚拟机的一个重要功能,可以避免内存泄漏和资源浪费。

2)JVM的内存模型

JVM的内存模型主要包括以下几个部分:

  • 方法区(Method Area): 存放类的元信息、常量、静态变量等数据。方法区是线程共享的内存区域,用于存储被虚拟机加载的类信息。
  • 堆(Heap): 存放对象实例。堆是线程共享的内存区域,用于存储所有被new出来的对象和数组。在堆中分为新生代和老年代,新生代又分为Eden区、Survivor From区和Survivor To区。
  • 虚拟机栈(Java Virtual Machine Stacks): 每个线程在创建时会创建一个栈,用于存放局部变量、方法参数、返回值和部分结果。栈帧包含了方法的运行过程,包括局部变量表、操作数栈、动态链接、方法出口等信息。
  • 本地方法栈(Native Method Stack): 与虚拟机栈类似,但是用于执行本地方法的部分。
  • 程序计数器(Program Counter): 每个线程都有一个程序计数器,用于存储当前线程正在执行的字节码指令地址。

3)堆和栈的区别

堆和栈是Java中两种不同的内存分配方式,主要区别如下:

  • 存放内容: 堆用于存放对象实例,包括由new创建的对象和数组。栈用于存放基本数据类型的变量和对象的引用(即对象的地址)。
  • 生命周期: 堆中的对象的生命周期由虚拟机的垃圾回收器管理,当对象不再被引用时,会被垃圾回收器回收。栈中的变量生命周期与方法的调用周期相同,当方法执行结束时,栈中的局部变量会被销毁。
  • 空间大小和管理: 堆的空间通常较大,可以动态地分配和回收内存。栈的空间相对较小,大小在编译时就已确定,并且由系统自动管理。
  • 访问速度: 栈的访问速度比堆要快,因为栈是按照“先进后出”的原则管理数据,访问和存储速度更快。堆的访问速度相对较慢,因为要通过引用来访问对象。

总的来说,堆和栈在Java中扮演着不同的角色,理解它们的区别有助于更好地理解Java程序的运行机制和内存管理。

4)什么时候会触发 Full GC

Full GC(Full Garbage Collection)是Java虚拟机执行的一种垃圾回收操作,它会清理整个堆内存,包括新生代和老年代。Full GC通常在以下情况下触发:

  • 老年代空间不足: 当老年代的空间不足以存放新分配的对象时,会触发Full GC来清理老年代,并尽量回收内存。
  • 永久代(在Java 8之前)或元空间(在Java 8及以后)空间不足: 如果永久代或元空间的空间不足以存放类的元数据、常量池等信息时,会触发Full GC来进行清理。
  • 手动触发: 开发人员可以通过调用System.gc()方法来建议虚拟机执行垃圾回收操作,有时候会触发Full GC。

Full GC是一种开销较大的操作,因为它会暂停所有的应用线程,直到垃圾回收完成。因此,应尽量避免Full GC的频繁发生,可以通过优化程序代码和合理设置堆内存大小来减少Full GC的次数。

5)什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?

Java虚拟机(Java Virtual Machine,JVM)是Java程序运行的环境,它负责将Java字节码解释或编译成特定平台上的机器指令,并管理程序的内存、线程等资源。JVM实现了Java语言规范,是Java跨平台特性的关键。

Java被称作“平台无关的编程语言”,主要是因为Java程序在编译时生成的是字节码(Bytecode),而不是特定平台上的机器码。这些字节码可以在任何支持Java虚拟机的平台上运行,而无需重新编译。Java虚拟机负责将字节码解释或编译成特定平台上的机器指令,从而实现了跨平台的能力。

6)Java内存结构

Java内存结构包括以下几个部分:

  • 程序计数器(Program Counter Register): 每个线程都有一个程序计数器,用于存储当前线程正在执行的字节码指令地址。
  • Java虚拟机栈(Java Virtual Machine Stacks): 每个线程在创建时都会创建一个栈,用于存放方法的局部变量、方法参数、返回值和部分结果。每个方法在执行时会创建一个栈帧,栈帧包含了方法的运行过程中所需的信息。
  • 本地方法栈(Native Method Stack): 与虚拟机栈类似,但用于执行本地方法(Native Method)的部分。
  • 堆(Heap): 存放对象实例,包括由new创建的对象和数组。堆是所有线程共享的内存区域,用于存储动态分配的对象。
  • 方法区(Method Area): 存放类的元信息、常量、静态变量等数据。方法区是所有线程共享的内存区域,用于存储被虚拟机加载的类信息。
  • 运行时常量池(Runtime Constant Pool): 方法区的一部分,用于存放编译期生成的字面量和符号引用。在运行时,还可以将新的常量池符号引用存放到运行时常量池中。

这些内存区域在Java程序的运行过程中起着不同的作用,相互配合来支持程序的执行。

7)对象分配规则

Java中的对象分配规则主要包括以下几个方面:

  • 堆分配: Java中的对象实例都在堆(Heap)中分配内存。当我们使用new关键字创建一个对象时,内存会在堆上动态分配。
  • 栈上分配: 对于一些不逃逸的局部变量,编译器可以选择将它们分配在栈上,这样可以提高对象的访问速度。
  • 寄存器分配: 一些简单的对象可以直接存储在CPU的寄存器中,而不必分配在堆或栈上。
  • 常量池中的分配: 字符串常量和基本类型的常量(如intfloat等)可以在常量池中分配内存。
  • 线程本地分配缓冲区(TLAB): 为了提高多线程环境下的对象分配效率,JVM会为每个线程预先分配一块小的内存空间,称为线程本地分配缓冲区。

8)Java对象创建过程

Java对象的创建过程主要包括以下几个步骤:

  1. 类加载: 当我们第一次使用某个类时,Java虚拟机会加载并初始化该类。
  2. 内存分配: 一旦类被加载,JVM会在堆中分配内存给该对象。如果对象需要的内存大小在TLAB(线程本地分配缓冲区)中无法分配,则会在堆中进行分配。
  3. 初始化: 在分配内存后,JVM会对对象进行初始化,包括设置对象的默认值和调用构造方法。
  4. 构造方法执行: 构造方法会执行对象的初始化过程,初始化对象的各个字段。
  5. 对象引用: 最后,将对象的引用返回给调用方,调用方可以使用该引用来操作对象。

9)类的生命周期

类的生命周期包括以下几个阶段:

  1. 加载(Loading): 加载是指将类的字节码加载到内存中,并生成对应的Class对象的过程。加载阶段由类加载器完成,包括查找类的字节码文件、创建Class对象等。
  2. 链接(Linking): 链接阶段包括验证、准备和解析三个阶段:
    • 验证(Verification): 确保加载的字节码符合Java虚拟机规范,并且不会危害虚拟机的安全。
    • 准备(Preparation): 为类的静态变量分配内存,并设置默认初始值。
    • 解析(Resolution): 将类中的符号引用转换为直接引用。
  3. 初始化(Initialization): 初始化阶段是类加载的最后一步,它会执行类的初始化代码,包括静态变量赋值和静态代码块的执行。类的初始化是在必要时才进行的,例如当访问类的静态成员或调用静态方法时。
  4. 使用(Usage): 类初始化完成后,可以通过创建对象、访问静态成员等方式来使用类。
  5. 卸载(Unloading): 类卸载是指当类不再被引用且满足垃圾回收条件时,由垃圾回收器将其从内存中删除的过程。类的卸载是Java虚拟机的一个重要功能,可以避免内存泄漏和资源浪费。

10)简述Java的对象结构

Java的对象结构主要包括对象头(Object Header)、实例数据(Instance Data)和对齐填充(Padding)三部分:

  • 对象头(Object Header): 对象头存储了对象的元数据信息,包括对象的哈希码、GC分代年龄、锁状态标志、线程持有的锁信息等。对象头的大小在不同的JVM实现中可能有所不同。
  • 实例数据(Instance Data): 实例数据存储了对象的各个字段的值,包括实例变量和从父类继承的变量。
  • 对齐填充(Padding): 对齐填充是为了保证对象在内存中的地址是8字节对齐的,以提高访问速度。对齐填充会在对象的实例数据和对象头之间插入一些无意义的填充数据,使得对象的大小为8字节的整数倍。

Java对象的结构在不同的JVM实现中可能有所不同,但通常都包括上述三部分。对象的大小取决于对象头的大小、实例数据的大小和对齐填充的大小。

开源项目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system

前后端总计已经 900+ Star,1.5W+ 访问!

⭐点赞⭐收藏⭐不迷路!⭐

这篇关于面试 Java 基础八股文十问十答第二十四期的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

springboot整合 xxl-job及使用步骤

《springboot整合xxl-job及使用步骤》XXL-JOB是一个分布式任务调度平台,用于解决分布式系统中的任务调度和管理问题,文章详细介绍了XXL-JOB的架构,包括调度中心、执行器和Web... 目录一、xxl-job是什么二、使用步骤1. 下载并运行管理端代码2. 访问管理页面,确认是否启动成功

Java中的密码加密方式

《Java中的密码加密方式》文章介绍了Java中使用MD5算法对密码进行加密的方法,以及如何通过加盐和多重加密来提高密码的安全性,MD5是一种不可逆的哈希算法,适合用于存储密码,因为其输出的摘要长度固... 目录Java的密码加密方式密码加密一般的应用方式是总结Java的密码加密方式密码加密【这里采用的

Java中ArrayList的8种浅拷贝方式示例代码

《Java中ArrayList的8种浅拷贝方式示例代码》:本文主要介绍Java中ArrayList的8种浅拷贝方式的相关资料,讲解了Java中ArrayList的浅拷贝概念,并详细分享了八种实现浅... 目录引言什么是浅拷贝?ArrayList 浅拷贝的重要性方法一:使用构造函数方法二:使用 addAll(

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b