Java 内存管理

原文:https://www.geeksforgeeks.org/java-memory-management/

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

为什么要学习 Java 内存管理? 我们都知道 Java 本身管理内存,不需要程序员的明确干预。垃圾收集器本身确保未使用的空间得到清理,并且可以在不需要时释放内存。那么程序员的角色是什么,为什么程序员需要学习 Java 内存管理?作为一名程序员,你不需要为销毁对象之类的问题而烦恼,这些都归功于垃圾收集器。然而,自动垃圾收集并不能保证一切。如果我们不知道内存管理是如何工作的,我们经常会陷入不由 JVM (Java 虚拟机)管理的事情中。有些对象不适合自动垃圾收集。

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

导言:

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

Java 内存管理的主要概念:

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

Java 内存结构:

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

JVM Memory area parts

内存区域部分

让我们详细研究一下记忆区的这些部分:

堆:

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

扫描仪 sc =新扫描仪(system . in);

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

注意:堆区垃圾收集是强制的。

方法区域:

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

注意:虽然方法区在逻辑上是堆的一部分,但即使堆区强制垃圾收集,也可能是垃圾收集,也可能不是垃圾收集。

JVM 堆栈:

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

本机方法堆栈:

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

程序计数器寄存器:

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

垃圾收集器的工作:

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

注意: System.gc()Runtime.gc() 是明确向 JVM 请求垃圾收集的方法,但并不能保证垃圾收集,因为垃圾收集的最终决定只属于 JVM。

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