Java 堆内存错误

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,你将学习如何有效使用 Java 堆内存(Java Heap Memory),以避免 Java 堆内存错误。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("`Java`")) -.-> java/DataStructuresGroup(["`Data Structures`"]) java(("`Java`")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["`Object-Oriented and Advanced Concepts`"]) java(("`Java`")) -.-> java/SystemandDataProcessingGroup(["`System and Data Processing`"]) java/DataStructuresGroup -.-> java/arrays("`Arrays`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("`Classes/Objects`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("`Exceptions`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("`ArrayList`") java/SystemandDataProcessingGroup -.-> java/system_methods("`System Methods`") subgraph Lab Skills java/arrays -.-> lab-117690{{"`Java 堆内存错误`"}} java/classes_objects -.-> lab-117690{{"`Java 堆内存错误`"}} java/exceptions -.-> lab-117690{{"`Java 堆内存错误`"}} java/arraylist -.-> lab-117690{{"`Java 堆内存错误`"}} java/system_methods -.-> lab-117690{{"`Java 堆内存错误`"}} end

Java 堆内存错误

当 Java 虚拟机(JVM)在将对象分配到 Java 堆内存(Java Heap Memory)时耗尽内存,就会发生 Java 堆内存错误。不良的编程实践、内存泄漏以及第三方库都可能导致此错误。

代码:

import java.util.ArrayList;

public class JavaHeapMemoryError {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        while (true) {
            Object o = new Object();
            list.add(o);
        }
    }
}

要查看此错误的具体表现,请在终端中编译并运行代码:

javac JavaHeapMemoryError.java
java -Xmx512m JavaHeapMemoryError

该程序通过不断创建对象并将其添加到 ArrayList 中,尝试分配尽可能多的内存,直到 JVM 抛出 OutOfMemoryError。-Xmx 参数用于设置 JVM 的最大堆内存分配。

Java 堆内存错误的原因

Java 堆内存错误主要是由于不良的编程实践、内存泄漏以及第三方库引起的。为了避免此类错误,我们必须避免无限循环、长时间持有未清理的未使用对象,并确保未使用的对象可以被垃圾回收器回收。

代码:

public class JavaHeapMemoryError {
    public static void main(String[] args) {
        int[] arr = new int[100000000];
        for(int i=0; i<arr.length; i++){
            arr[i] = i;
        }
        System.out.println("Memory allocated");
    }
}

要查看代码的实际运行效果,请在终端中编译并运行代码:

javac JavaHeapMemoryError.java
java -Xmx256m JavaHeapMemoryError

内存泄漏

当堆内存中的未使用对象仍然持有有效引用,导致垃圾回收器无法将其移除时,就会发生内存泄漏。为了避免内存泄漏,必须使用 finally 块关闭所有打开的资源。

代码:

public class MemoryLeak {
    static ArrayList<String> arrList = new ArrayList<String>(500);
    public static void main(String args[]) {
        for (int i = 0; i < 500; i++) {
            arrList.add("Element " + i);
        }
        arrList = null;
    }
}

要查看代码的实际运行效果,请在终端中编译并运行代码:

javac MemoryLeak.java
java -Xmx256m MemoryLeak

过度使用 finalizers

过度使用 finalizers 可能导致 Java 堆内存错误,因为包含 finalize 方法的类在垃圾回收期间不会回收其对象空间。

代码:

public class ExcessiveFinalizer {
    public void finalize() {
        //Do some cleanup
    }

    public static void main(String[] args) {
        ArrayList<ExcessiveFinalizer> list = new ArrayList<ExcessiveFinalizer>();
        while (true) {
            list.add(new ExcessiveFinalizer());
        }
    }
}

要查看代码的实际运行效果,请在终端中编译并运行代码:

javac ExcessiveFinalizer.java
java -Xmx256m ExcessiveFinalizer

增加堆内存

如果错误是由于分配给 JVM 的内存不足引起的,我们可以通过增加 -Xmx 命令设置的限制来增加 JVM 可用的堆空间。

代码:

public class IncreaseHeapMemory {
    public static void main(String[] args) {
        Integer[] outOfMemoryArray = new Integer[Integer.MAX_VALUE];
    }
}

要查看代码的实际运行效果,请在终端中编译并运行代码:

javac IncreaseHeapMemory.java
java -Xmx8g IncreaseHeapMemory

总结

在本实验中,你学习了如何为 Java 应用程序有效管理堆内存,以避免 Java 堆内存错误。我们探讨了多种预防错误的技术,例如避免低效循环、关闭未使用的资源,以及尽早让未使用的对象可被垃圾回收器回收。最后,如果错误是由于堆内存不足引起的,我们使用 -Xmx 命令增加了内存限制。

您可能感兴趣的其他 Java 教程