Java ヒープメモリエラー

JavaJavaBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Java ヒープメモリを効果的に使用して Java ヒープメモリエラーを回避する方法を学びます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) 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 ヒープメモリにオブジェクトを割り当てる際に Java 仮想マシン (JVM) がメモリ不足になった場合、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

ファイナライザの過度な使用

ファイナライザを過度に使用すると、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 コマンドを使用して制限を増やしました。