0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java入門 - 実践編】JVM制御とリフレクション

0
Posted at

はじめに

こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。

今回は第1部 / 第4章「JVM制御とリフレクション」について学びました。
JVM制御とリフレクションの機能によって、実行環境の情報を取得できるため、実行時に動的にプログラムの動作を最適化・調整できるようになります。

この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。

参考書籍について

目次

  1. 本章の要点
  2. 自分なりの解釈

1. 本章の要点

JVMの制御

JVM自体の内部機構にアクセスし、その内部情報を得たり、JVM自体を直接制御したりするAPIがあります。

JVMの終了

実行中のJVMプロセスを明示的に終了させます。

public class Main {
    public static void main(String[] args) {
        System.out.println("処理を開始");
        
        // JVMを終了コード0で終了
        System.exit(0);
        
        System.out.println("この行は実行されない");
    }
}

外部プログラムの実行

ProcessBuilderクラスを使用して、別のプログラムやコマンドを実行できます。

import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // ProcessBuilderで外部コマンドを実行
        ProcessBuilder pb = new ProcessBuilder("java", "-version");
        
        // プロセスを開始
        Process process = pb.start();
        
        // 標準出力を読み込む
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream())
        );
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        
        // プロセスの終了を待つ
        int exitCode = process.waitFor();
        System.out.println("終了コード:" + exitCode);
    }
}

システムプロパティの利用

JVMが管理するシステム情報にアクセスできます。

public class Main {
    public static void main(String[] args) {
        // Javaのバージョン
        System.out.println("Javaバージョン:" + System.getProperty("java.version"));
        
        // OSの情報
        System.out.println("OS名:" + System.getProperty("os.name"));
        System.out.println("OSバージョン:" + System.getProperty("os.version"));
        
        // ユーザー情報
        System.out.println("ユーザー名:" + System.getProperty("user.name"));
        
        // ファイルシステムの情報
        System.out.println("ファイルセパレータ:" + System.getProperty("file.separator"));
    }
}

ロケールと国際化

  • ロケールとは、言語や地域に関する情報をまとめたオブジェクトです。
    JVMはロケール情報やタイムゾーンを管理し、日付や通貨などの表示形式を制御できます。
import java.util.*;
import java.text.*;

public class Main {
    public static void main(String[] args) {
        // デフォルトロケール
        Locale defaultLocale = Locale.getDefault();
        System.out.println("デフォルトロケール:" + defaultLocale); // 出力:ja_JP
        
        // 異なるロケールでの日付表示
        Date now = new Date();
        
        // 日本
        DateFormat jpFormat = DateFormat.getDateInstance(
            DateFormat.LONG, Locale.JAPAN
        );
        System.out.println("日本:" + jpFormat.format(now));
        
        // アメリカ
        DateFormat usFormat = DateFormat.getDateInstance(
            DateFormat.LONG, Locale.US
        );
        System.out.println("アメリカ:" + usFormat.format(now));
        
        // タイムゾーン
        TimeZone jst = TimeZone.getTimeZone("Asia/Tokyo");
        TimeZone utc = TimeZone.getTimeZone("UTC");
        System.out.println("JST:" + jst.getDisplayName());
        System.out.println("UTC:" + utc.getDisplayName());
    }
}

メモリに関する状態の取得

JVMのメモリ使用状況を取得できます。

public class Main {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        // メモリ情報の取得
        long maxMemory = runtime.maxMemory();      // 最大メモリ(バイト)
        long totalMemory = runtime.totalMemory();  // 割り当てられたメモリ
        long freeMemory = runtime.freeMemory();    // 空きメモリ
        long usedMemory = totalMemory - freeMemory; // 使用中メモリ
        
        System.out.println("最大メモリ:" + (maxMemory / 1024 / 1024) + " MB");
        System.out.println("割り当てメモリ:" + (totalMemory / 1024 / 1024) + " MB");
        System.out.println("使用中メモリ:" + (usedMemory / 1024 / 1024) + " MB");
        System.out.println("空きメモリ:" + (freeMemory / 1024 / 1024) + " MB");
    }
}
// 出力例:
// 最大メモリ:256 MB
// 割り当てメモリ:128 MB
// 使用中メモリ:64 MB
// 空きメモリ:64 MB

リフレクション

  • リフレクションとは、実行時にクラスの情報(メソッド、フィールド、コンストラクタなど)を動的に取得・操作する仕組みです。
public class Hero {
    private String name;
    private int hp;
    
    public Hero(String name, int hp) {
        this.name = name;
        this.hp = hp;
    }
    
    public void attack() {
        System.out.println(this.name + "が攻撃した");
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Hero hero = new Hero("ミナト", 100);
        
        // Classオブジェクトを取得(3つの方法)
        Class<?> cls1 = hero.getClass();       // 方法1:オブジェクトから取得
        Class<?> cls2 = Hero.class;            // 方法2:クラスから直接取得
        Class<?> cls3 = Class.forName("Hero"); // 方法3:クラス名の文字列から取得
        
        // クラス情報の表示
        System.out.println("クラス名:" + cls1.getName());
        System.out.println("シンプルクラス名:" + cls1.getSimpleName());
        
        // メソッド情報の取得
        System.out.println("定義されたメソッド:");
        for (java.lang.reflect.Method method : cls1.getDeclaredMethods()) {
            System.out.println("  - " + method.getName());
        }
        
        // フィールド情報の取得
        System.out.println("定義されたフィールド:");
        for (java.lang.reflect.Field field : cls1.getDeclaredFields()) {
            System.out.println("  - " + field.getName());
        }
    }
}
// 出力:
// クラス名:Hero
// シンプルクラス名:Hero
//
// 定義されたメソッド:
//   - attack
//
// 定義されたフィールド:
//   - name
//   - hp

2. 自分なりの解釈

  • JVM制御により、JavaプログラムからOSやJVM自体の情報にアクセスでき、より低レベルの制御が行える。
  • リフレクションは実行時にクラス情報を取得・操作できる機能で、フレームワークやライブラリの開発で重要な役割。
    • プライベートメンバーにもアクセスできるリフレクションは便利だが、パフォーマンスやセキュリティの観点から慎重に使う機能。

最後まで見ていただきありがとうございました。
次回は、第1部 / 第5章「非標準ライブラリの活用」について書く予定です。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?