Java Heap17 Mar 2025 | 5 分钟阅读 在 Java 中,堆是所有线程共享的一块内存区域。堆中会分配所有类的实例和数组。它在 JVM 启动时创建。一个自动存储管理系统会回收堆。它的大小可以是固定的,也可以是可变的。它不需要是连续的。 堆结构 ![]() 堆分为两个部分(或代)
年轻代它是堆的一部分。它保留用于分配对象。当它填满时,Minor GC 会从 Eden 收集垃圾到其中一个幸存者空间。在其中一个幸存者空间中可用于垃圾回收的对象被清除,其余对象移至另一个幸存者空间。因此,总有一个空的幸存者空间。所有在年轻代中存活时间较长的对象都会被转移到老年代。 Java 近期版本中,新生代的一部分称为保留区。它包含新生代中最近分配的对象。它不会收集垃圾,直到下一个年轻代。
年轻代(Eden 空间 + 幸存者from 空间)中的所有活动对象都会被移至幸存者to 空间。完成此过程后,幸存者from 空间为空。在幸存者空间之间复制活动对象的过程会重复几次,直到一些对象被认为已经成熟且足够老。这样的对象可以移至老年代,而不是移至另一个幸存者空间。为了确定对象是否准备好移至老年代,GC 会计算对象幸存的总回收次数。如果对象未被回收,则其生命周期会增加。 老年代空间它包含生命周期较长的对象。这个过程称为老年代回收。长生命周期的对象在多次 Minor GC 后幸存下来。当老年代空间接近其极限时,大部分老年代内存会被清除。通常,当老年代空间达到其极限时,垃圾收集器会被执行。老年代垃圾收集器称为 Major GC。它需要很长时间来移除对象。 这里有一个问题:“如果老年代中的对象需要引用年轻代中的对象,会发生什么?” 为了处理这类情况,JVM 在老年代中维护一个称为卡片表(card table)的表。它是一个 512 字节的内存块。当老年代中的对象引用年轻代中的对象时,它会记录在卡片表中。当 Minor GC 为年轻代执行时,GC 只会搜索此表。它会确定该对象是否应被 GC,而不是检查老年代中所有对象的引用。写屏障(write barrier)管理卡片表。它是一种能够提高 Minor GC 性能的机制。 非堆内存它包括一个所有线程共享的方法区。它存储每个类的结构。它的大小可以是固定的,也可以是可变的。它不需要是连续的。 永久代(PermGen) JVM 在运行时生成它。它包含 JVM 所需的应用程序元数据。元数据包括应用程序使用的类和方法。它还包括 Java SE 库类和方法。 在 Java 8 中,Metaspace 取代了它。这意味着在 Java 8 中不会出现 java.lang.OutOfMemoryError。Metaspace 中引入了两个新标志:-XXMetasapceSize 和 ?XXMaxMetaspaceSize。Metaspace 的主要目的是,只要类加载器存在,元数据就在 Metaspace 中存在。 PermGen 和 Metaspace 的主要区别在于:PermGen 是堆的一部分,而 Metaspace 是本地内存的一部分。 ![]() 代码缓存 (Code Cache):它是一个独立于堆的内存区域。它用于编译和存储本地代码。它是一个固定大小的空间。如果它填满,JVM 将不会编译任何其他代码。为了避免这种情况,您可以使用以下大小选项来调整代码缓存:
JVM 使用 Use Code Cache Flushing 选项来控制代码缓存区域的刷新。其默认值为 false。即时编译器(JIT)是代码缓存区域的最大用户。 java.lang.OutOfMemoryError 的原因当应用程序尝试向堆空间区域添加更多数据但没有足够空间时,会触发此错误。每当达到堆大小限制时,JVM 就会抛出 Java 堆空间错误。
![]() 示例 输出 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at MemoryLeaksDemo.main(MemoryLeaksDemo.java:5) |
在本节中,我们将学习什么是贝尔数,并创建 Java 程序来检查给定的数字是否为贝尔数。贝尔数程序经常在 Java 编码面试和学术界中出现。贝尔数 贝尔数是一系列...
阅读 4 分钟
Java 8 与 Java 11 Java 被程序员使用了几代人,然而,它通过不同的版本有了很大的发展。自 1996 年 Java 1.0 发布以来,它现在构成了平台独立编程的基础。J2SE 1.2(也称为 Java 2)引入了...
阅读 6 分钟
在 Java 中,就像金字塔和三角形模式一样,大多数面试官也会让开发人员编写字母模式。字母模式,如 A、B、C... 是基于用户给定的模式高度设计的。宽度...
阅读 8 分钟
在本教程中,我们将学习 Java 中的半素数。如果一个数 n 可以写成两个素数的乘积,则称 n 为半素数。在本教程中,我们将探讨如何...
5 分钟阅读
基于哈希的消息认证码 (HMAC) 是一种在通信网络中确保消息完整性和真实性的方法。在 Java 中实现 HMAC 加密使用加密哈希函数来生成特殊代码,该代码可以验证消息的完整性并认证发送者...
阅读 6 分钟
由三个不同直径的圆盘和一对钉子组成的著名数学谜题是汉诺塔。该谜题的目标是在遵守以下规则的情况下,在钉子之间移动每个圆盘:一次只能移动一个圆盘...
阅读 4 分钟
在本节中,我们将学习什么是太阳数,以及如何创建一个 Java 程序来查找太阳数。我们还将创建一个 Java 程序来查找指定范围内的所有太阳数。太阳数 一个数称为太阳数...
阅读 3 分钟
Java 8 为编程语言带来了一些新功能,其中最重要的一项是 lambda 表达式。Lambda 表达式提供了一种简洁的方式来表达可以作为参数传递给另一个方法的函数,从而实现了函数式编程范式...
阅读 4 分钟
随着多线程和异步编程的出现,Java 提供了一种执行并行任务的强大方法,称为 ExecutorService。但是,在管理多个线程和处理任务执行过程中出现的错误时,您可能会遇到 ExecutionException。在本节中,我们将探讨…
5 分钟阅读
在 Java 中生成随机字符串是一个简单的概念,通常用于构建 ID、临时密码、会话令牌或其他需要字母数字字符串的场景。有几种方法可以使用不同的类和...
阅读 13 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India