はじめに
こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。
今回は第1部 / 第4章「JVM制御とリフレクション」について学びました。
JVM制御とリフレクションの機能によって、実行環境の情報を取得できるため、実行時に動的にプログラムの動作を最適化・調整できるようになります。
この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。
参考書籍について
- 書籍名:スッキリわかるJava入門 実践編
- 著者:中山清喬
- 出版社:インプレス
目次
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章「非標準ライブラリの活用」について書く予定です。