読者です 読者をやめる 読者になる 読者になる

Java: メモリ使用量のチェックをする

まずJavaVMのメモリ関連の値を取得するメソッドを紹介します。

// JavaVMが利用できるメモリの上限値
Runtime.getRuntime().maxMemory();

// JavaVMが確保済みのメモリ領域のうち、未使用領域のサイズ
Runtime.getRuntime().freeMemory();

// JavaVMが確保済みのメモリ領域のサイズ
Runtime.getRuntime().totalMemory();

実行中のJavaアプリケーションのメモリ使用量は、確保済みメモリ領域から未使用領域を減算することで計算します。

// Javaアプリケーションのメモリ使用量
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

メモリチェックツールを作る

メモリの使用量を一定間隔でチェックし、使用量が指定した最大値を超えた場合に処理を終了するプログラムのサンプルです。

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

public class Main {

    // メモリが最大値を超えた場合の処理のクラス
    private static class Alert {

        private boolean exit = false;

        // メモリが最大値を超えた場合の処理
        // ここでは終了フラグを立てる
        public void exec() {
            exit = true;
        }

        public boolean isExit() {
            return exit;
        }
    }

    // 一定間隔にメモリをチェックするクラス
    // TimerTaskを継承し、一定間隔毎に処理を実行する
    private static class MemoryCheck extends TimerTask {

        private Alert alert = null;
        private long alertSize = 0L;

        MemoryCheck(Alert alert, long alertSize) {
            this.alert = alert;
            this.alertSize = alertSize;
        }

        public void run() {
            long size = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
            if (size >= this.alertSize) {
                // メモリが最大値を超える
                this.alert.exec();
            }
        }
    }

    public static void main(String[] args) {

        // メモリチェック用のタイマーの設定
        long mb = 1024 * 1024;
        Alert alert = new Alert();
        TimerTask tt = new MemoryCheck(alert, 100 * mb);
        Timer timer = new Timer();
        timer.schedule(tt, 0, 1000);

        // 5秒ごとに1000万のint型配列のメモリを確保する
        ArrayList<int[]> list = new ArrayList<>();
        for (;;) {
            System.out.println((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / mb);
            if (alert.isExit()) {
                // メモリが最大値100MBを超え終了フラグがtrueのため、処理を終了する
                System.out.println("Alert");
                break;
            }
            try {
                list.add(new int[10000000]);
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        timer.cancel();
    }
}

実行結果

3
41
80
118
Alert