当前位置: 首页 > article >正文

JVM面试真题总结(十二)

文章收录在网站:http://hardyfish.top/

文章收录在网站:http://hardyfish.top/

文章收录在网站:http://hardyfish.top/

文章收录在网站:http://hardyfish.top/

在这里插入图片描述

对比Java内存模型与JVM内存模型的不同点

Java内存模型(Java Memory Model,简称JMM)和JVM内存模型是两个不同的概念

  • 它们关注的问题和解决的问题是不同的。

Java内存模型:

  • Java内存模型主要关注的是多线程环境下,如何以线程安全的方式对共享变量进行操作。
  • 它定义了变量的读取、写入等操作的规则,并规定了在并发环境下
    • 如何通过volatile、synchronized等关键字来保证共享变量的可见性和有序性。
  • Java内存模型解决的是在多线程编程中,如何保证内存的可见性、原子性和有序性,以防止出现数据不一致的问题。

JVM内存模型:

  • JVM内存模型主要关注的是JVM的内存区域划分和内存管理。
    • 它将JVM内存划分为堆内存、栈内存、方法区、程序计数器等区域,并定义了每个区域的使用方式和作用。
    • 比如,堆内存主要用于存储对象实例,栈内存用于存储局部变量,方法区用于存储已被加载的类信息等。
      • JVM内存模型主要解决的是内存的分配和回收问题。

总的来说,Java内存模型主要是为了解决多线程编程中的内存可见性和有序性问题

  • 而JVM内存模型则是关注JVM如何管理和分配内存。

Java 8的内存结构有哪些显著变化?

在Java 8中,内存结构相较于之前的版本有一些变化。

主要的变化在于永久代(PermGen)被移除,取而代之的是元空间(Metaspace)。

以下是关于这两者的详细解释:

永久代(PermGen):

  • 在Java 7及其之前的版本中,永久代主要用于存储类的元数据、静态变量以及方法区等。
  • 永久代的内存大小是有限的,当加载的类过多时
    • 可能会导致永久代内存溢出(java.lang.OutOfMemoryError: PermGen space
      • 这在实际应用中是一个常见的问题。

元空间(Metaspace):

  • 在Java 8中,永久代被移除,取而代之的是元空间。
  • 元空间与永久代的主要区别在于它的内存分配。
    • 元空间并不位于Java堆内存中,而是使用本地内存(Native Memory)。
    • 这意味着元空间的大小不再受到Java堆内存的限制,而是受到本地内存的限制,这有助于减少永久代内存溢出的问题。
    • 当然,元空间也并非无限大,当元空间的内存分配超出限制时
      • 仍然会抛出内存溢出异常(java.lang.OutOfMemoryError: Metaspace)。

除了上述变化外,Java 8中的内存结构大致保持不变,包括Java堆、栈、程序计数器、本地方法栈等。

Java堆主要用于存储对象实例,栈用于存储局部变量、方法调用等,程序计数器用于存储当前线程的执行位置

  • 本地方法栈用于支持本地方法的调用。

总结一下,Java 8中的内存结构变化主要是将永久代替换为元空间

  • 这有助于解决永久代内存溢出的问题,同时使得内存分配更加灵活。

在实际应用中,我们需要关注元空间的内存使用情况,以便在需要时进行调整。

为什么Java 8要移除永久代(PermGen)?

永久代(PermGen)在Java 8中被移除,主要是因为以下几个原因:

简化垃圾收集:

  • 在Java 7及其之前的版本中,永久代存储了大量的类的元数据
    • 这使得垃圾收集器需要处理这部分内存,增加了垃圾收集的复杂性。
  • 移除永久代后,垃圾收集器只需要关注Java堆内存,从而简化了垃圾收集的过程。

避免内存溢出:

  • 永久代的内存大小是有限的,当加载的类过多时,可能会导致永久代内存溢出。
    • 而元空间使用的是本地内存,其大小只受限于本地内存的大小,因此更不容易出现内存溢出。

提高性能:

  • 永久代的内存管理需要消耗一定的性能。
    • 移除永久代后,可以减少内存管理的开销,从而提高系统的性能。

更好的内存控制和监控:

  • 永久代的内存分配和回收策略与Java堆不同,这使得对其进行控制和监控比较困难。
    • 而元空间使用的是本地内存,可以借助于本地内存管理工具进行更好的控制和监控。

总的来说,永久代被移除是为了简化垃圾收集,避免内存溢出,提高性能,以及实现更好的内存控制和监控。

对比堆内存和栈内存的特点和使用场景

堆和栈是Java内存中的两个重要区域,它们在内存分配、数据存储和生命周期等方面有以下主要区别:

内存分配:

  • 堆(Heap)是Java内存中用于存储对象实例的区域,它是一个运行时数据区,大小可动态扩展。
    • 堆内存由所有线程共享,因此在堆中分配的内存可以被所有线程访问。
  • 栈(Stack)是Java内存中用于存储局部变量、方法调用等的区域。
    • 每个线程都有一个独立的栈,栈内存由线程私有。
    • 栈的大小是固定的,当栈内存不足时,会导致栈溢出错误(java.lang.StackOverflowError)。

数据存储:

  • 堆中主要存储对象实例及其相关数据。
    • 当我们使用new关键字创建对象时,对象实例被分配到堆内存中。
  • 栈中主要存储基本数据类型(如int、float、boolean等)
    • 对象引用变量以及方法调用相关信息(如方法调用的顺序、局部变量等)。

生命周期:

  • 堆内存中的对象实例的生命周期较长。
    • 它们会在垃圾收集器运行时被回收,具体回收时机取决于垃圾收集器的策略。
  • 栈内存中的数据随着方法的调用和返回而创建和销毁。
    • 当一个方法执行结束后,该方法在栈中的局部变量和相关信息会被自动销毁。

访问速度:

  • 访问堆内存中的对象实例相对较慢,因为它涉及到查找对象引用以及处理垃圾收集等过程。
  • 访问栈内存中的数据相对较快,因为栈内存由线程私有,且其数据结构简单,方便存取。

总之,堆和栈的主要区别在于内存分配、数据存储和生命周期。

堆用于存储对象实例,大小可扩展,生命周期较长,访问相对较慢

而栈用于存储基本数据类型、对象引用变量和方法调用相关信息,大小固定,生命周期较短,访问相对较快。


http://www.kler.cn/a/308779.html

相关文章:

  • Systemd: disable和mask的区别
  • fastapi 查询参数支持 Pydantic Model:参数校验与配置技巧
  • SpringSecurity源码中核心类
  • 如何查看电脑关机时间
  • 动态规划 —— 子数组系列-最大子数组和
  • 常见的噪声模型+图像中噪声模型的估计+常见的滤波方法(C++)
  • Nginx 跨域 + 无法设置 Cookie 解决办法
  • 计算机网络17——IM聊天系统——客户端核心处理类框架搭建
  • 基于web的 BBS论坛管理系统设计与实现
  • 【AI学习笔记】初学机器学习西瓜书概要记录(一)机器学习基础知识篇
  • 苍穹外卖Day01-2
  • 机器人的静力分析与动力学
  • vue中解决上个路由的el-dialog遮罩层未关闭问题
  • mqtt整体了解
  • python实现多个pdf文件合并
  • 二十三种设计模式之适配器模式
  • 单调队列,LeetCode 2398. 预算内的最多机器人数目
  • ai 回答HFS是什么 HTTP的文件服务器是什么
  • 数据结构之排序算法的分析和应用
  • 【数据结构篇】~链表算法题3(环形链表)
  • C# net跨平台上位机开发(avalonia)附demo源码
  • 牛客背包问题练习 xinjun与阴阳师
  • 苍穹外卖学习笔记(八)
  • 【案例71】配置https之后 IE打不开登陆页面 Uclient没有问题
  • 《微信小程序实战(2) · 组件封装》
  • 【重学 MySQL】二十七、七种 join 连接