📜  Java内存管理

📅  最后修改于: 2022-05-13 01:54:37.413000             🧑  作者: Mango

Java内存管理

本文将重点介绍Java内存管理、堆的工作原理、引用类型、垃圾收集以及相关概念。

为什么要学习Java内存管理?
我们都知道, Java自己管理内存,不需要程序员的显式干预。垃圾收集器本身可确保清理未使用的空间,并在不需要时释放内存。那么程序员的角色是什么,为什么程序员需要学习Java内存管理?作为一名程序员,您不需要为诸如销毁对象之类的问题而烦恼,这一切都归功于垃圾收集器。然而,自动垃圾收集并不能保证一切。如果我们不知道内存管理是如何工作的,那么我们通常会遇到一些不受 JVM(Java虚拟机)管理的东西。有些对象不符合自动垃圾回收的条件。

因此,了解内存管理是必不可少的,因为它将有利于程序员编写不会崩溃的基于高性能的程序,或者如果这样做,程序员将知道如何调试或克服崩溃。

介绍:

在每种编程语言中,内存都是至关重要的资源,而且在本质上也是稀缺资源。因此,必须彻底管理内存而没有任何泄漏。内存的分配和释放是一项关键任务,需要非常小心和考虑。然而,在Java中,与其他编程语言不同,JVM 以及特定的垃圾收集器具有管理内存分配的作用,因此程序员不需要这样做。而在其他编程语言(例如 C)中,程序员可以直接访问在其代码中分配内存的内存,从而为泄漏创造了很大的空间。

Java内存管理中的主要概念:

  • JVM内存结构
  • 垃圾收集器的工作

Java内存结构:

JVM 定义了在程序执行期间使用的各种运行时数据区域。有些区域是由 JVM 创建的,而有些是由程序中使用的线程创建的。但是,JVM 创建的内存区域只有在 JVM 退出时才会被销毁。线程的数据区在实例化时创建,在线程退出时销毁。

JVM内存区域部分

JVM内存区域部分

让我们详细研究一下内存区域的这些部分:

堆:

  • 它是一个共享的运行时数据区,并将实际对象存储在内存中。它在虚拟机启动期间被实例化。
  • 此内存分配给所有类实例和数组。堆可以是固定大小或动态大小,具体取决于系统的配置。
  • JVM 提供用户控制来根据需要初始化或改变堆的大小。当使用新关键字时,对象在堆中被分配一个空间,但相同的引用存在于堆栈中。
  • 对于一个正在运行的 JVM 进程,只有一个堆。

上面的语句创建了 Scanner 类的对象,该对象被分配到堆中,而引用“sc”被推送到堆栈中。

方法区:

  • 它是堆区域的逻辑部分,在虚拟机启动时创建。
  • 该内存分配给类结构、方法数据和构造函数字段数据,以及类中使用的接口或特殊方法。堆可以是固定大小或动态大小,具体取决于系统的配置。
  • 可以是固定大小或根据计算需要扩展。不需要是连续的。

JVM 堆栈:

  • 堆栈在创建线程的同时创建,用于存储在返回方法值和执行动态链接时需要的数据和部分结果。
  • 堆栈可以是固定大小或动态大小。堆栈的大小可以在创建时独立选择。
  • 堆栈的内存不需要是连续的。

本机方法堆栈:

也称为 C 堆栈,本机方法堆栈不是用Java语言编写的。该内存是在创建时为每个线程分配的。它可以是固定的或动态的。

程序计数器 (PC) 寄存器:

每个执行特定方法任务的 JVM 线程都有一个与之关联的程序计数器寄存器。非本地方法具有存储可用 JVM 指令地址的 PC,而在本地方法中,程序计数器的值是未定义的。 PC 寄存器能够在某些特定平台上存储返回地址或本机指针。

垃圾收集器的工作:

  • JVM 触发此过程,并根据 JVM 垃圾收集过程完成或保留。它通过自动执行内存的分配或释放来减轻程序员的负担。
  • 垃圾收集过程会导致其余进程或线程暂停,因此本质上是昂贵的。这个问题对于客户端来说是不可接受的,但可以通过应用几种基于垃圾收集器的算法来消除。这个应用算法的过程通常被称为垃圾收集器调整,对于提高程序的性能很重要。
  • 另一种解决方案是分代垃圾收集器,它向分配了内存的对象添加年龄字段。随着越来越多的对象被创建,垃圾列表增加,从而增加了垃圾收集时间。根据对象存活了多少时钟周期,对象被分组并相应地分配一个“年龄”。这样垃圾收集工作就会被分配。
  • 在当前场景中,所有垃圾收集器都是分代的,因此是最优的。

了解程序及其数据的存储或组织方式至关重要,因为当程序员打算根据资源和消耗编写优化的代码时,它会有所帮助。它还有助于发现内存泄漏或不一致,并有助于调试与内存相关的错误。但是,内存管理的概念非常广泛,因此必须尽最大努力尽可能地研究它以提高相同的知识。