JVMの終了
Systemクラスのexit()メソッドを用いてJVMを終了し、OSに終了コード(exit code)を渡すことができる。
定義
void System.exit(int status)
// パラメータ
// status: 終了コード(0は「正常終了」、0以外は「異常終了」を表す)
外部プログラムの実行
ProcessBuilderクラスを通じてシェルスクリプト(bashスクリプト)を実行することができる。
また、Processクラスを通じて結果を受け取り、BufferedReaderを介して結果を読み込むこともできる。
サンプルコード
import java.io.BufferedReader;
import java.io.InputStreamReader;
class ShellScript {
public static void main(String[] args){
System.out.println("Make and Run .sh");
// ProcessBuilderオブジェクトを用いてシェルスクリプトを作成
ProcessBuilder pb = new ProcessBuilder("sh", "-c", "echo 'Hello!'");
try {
// シェルスクリプトの実行
Process pc = pb.start();
// 実行結果を格納するStringBuilderオブジェクト
StringBuilder output = new StringBuilder();
// 実行結果を読み込むBufferedReaderオブジェクト
BufferedReader reader = new BufferedReader(new InputStreamReader(pc.getInputStream()));
// 実行結果の読み込み
String line;
while ((line = reader.readLine()) != null) {
output.append(line);
}
// 実行結果をコンソールに出力
System.out.println(output.toString());
}
catch (Exception e) {
// 例外発生時は標準エラーストリームに出力
e.printStackTrace();
// プログラムを終了
System.exit(1);
}
}
}
Make and Run .sh
Hello!
システムプロパティ(system property)
システムプロパティは、JVMによって管理されるJVMやOSに関するデータを、
Set<String>型のキーとProperties型の値で保持するグローバルなプロパティであり、
Systemクラスのメソッドを通じてシステムプロパティの取得・追加・変更ができる。
システムプロパティがもつ主なデータは、以下の通り。
キー (=Iterator<String>型) |
内容 |
|---|---|
java.version |
実行中のJREバージョン
|
java.home |
実行中のJavaのインストール先ディレクトリ
|
os.name |
動作中のOS
|
line.separator |
動作中のOSの改行コード(newline code)
|
user.name |
実行ユーザ |
定義
// 現在の「システムプロパティ一覧」の取得
Properties System.getProperties();
// システムプロパティのキー群の取得
Set<String> Properties.stringPropertyNames()
// Set型 -> Iterator型 への変換
// -> Set型は要素の抽出や走査が不可能であるため、抽出・走査が可能なIterator型に変換
Iterator<String> Set<String>.iterator()
// 「要素を走査」してキーを取得
String Iterator<String>.next()
// キーを指定してシステムプロパティを取得
String System.getProperty(String key)
// パラメータ
// key: システムプロパティを特定するキー
サンプルコード
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
class SystemProperties {
public static void main(String[] args) {
// システムプロパティ一覧の取得
Properties p = System.getProperties();
// システムプロパティのキー群の取得
Set<String> keySet = p.stringPropertyNames();
// Set<String>型 -> Iterator<String>型 への変換
// -> Iterator<E>型は要素の走査が可能
Iterator<String> keyItr = keySet.iterator();
// システムプロパティ一覧の表示
System.out.println("-- System Properties --");
while (keyItr.hasNext()) {
// キーの抽出
String key = keyItr.next();
System.out.println(key + ": " + System.getProperty(key));
}
}
}
-- System Properties --
user.name: b150005
path.separator: :
os.version: 11.4
java.runtime.name: OpenJDK Runtime Environment
os.name: Mac OS X
java.vm.name: OpenJDK 64-Bit Server VM
user.country: JP
sun.java.command: SystemProperties
java.version: 16.0.1
user.home: /Users/b150005
user.dir: /Users/b150005/Library/Mobile Documents/com~apple~CloudDocs/Java研修/advance/Advance
user.language: ja
os.arch: x86_64
file.separator: /
line.separator:
java.vendor: AdoptOpenJDK
ロケール(locale)
参考: Localeクラス
Localeクラスを通じて参照・変更が可能な、OSがもつユーザの国コードや言語コードに関する情報。
定義
// デフォルトロケールの取得
Locale Locale.getDefault()
// デフォルトロケールの設定
void Locale.setDefault(Locale newLocale)
// パラメータ
// newLocale: 「デフォルトロケール」を表すLocaleオブジェクト
// 国コードの取得
String Locale.getCountry()
// 国名の取得
String Locale.getDisplayLanguage()
// 言語コードの取得
String Locale.getLanguage()
// 言語名の取得
String Locale.getDisplayLanguage()
タイムゾーン(time zone)
TimeZoneクラスを通じて参照・変更が可能な、OSがもつユーザのタイムゾーンに関する情報。
定義
// デフォルトタイムゾーンの取得
TimeZone TimeZone.getDefault()
// デフォルトタイムゾーンの設定
void TimeZone.setDefault(TimeZone zone)
// パラメータ
// zone: 「デフォルトタイムゾーン」を表すTimeZoneオブジェクト
// タイムゾーンの表示名を取得
String TimeZone.getDisplayName()
// タイムゾーンがサマータイムを採用している場合はtrueを返却
boolean TimeZone.useDaylightTime()
// サマータイムを考慮せず世界標準時との時差[ms]を取得
abstract int TimeZone.getRawOffset()
// サマータイムを考慮して世界標準時との時差[ms]を取得
int TimeZone.getOffset(long date)
// パラメータ
// date: 「1970年1月1日00:00:00 GMT」との差[ms]
サンプルコード
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
public class LocaleAndTimeZone {
public static void main(String[] args) {
// デフォルトロケールの取得
Locale loc = Locale.getDefault();
// ロケール情報の表示
System.out.println("Locale: " + loc.getDisplayName());
System.out.println("Country Code: " + loc.getCountry());
System.out.println("Country Name: " + loc.getDisplayCountry());
System.out.println("Language Code: " + loc.getLanguage());
System.out.println("Language Name: " + loc.getDisplayLanguage());
// デフォルトタイムゾーンの取得
TimeZone tz = TimeZone.getDefault();
// カレンダーの取得
Calendar cal = Calendar.getInstance();
// カレンダー情報の時間値[ms]
long calDate = cal.getTimeInMillis();
// タイムゾーン情報の表示
System.out.println("TimeZone: " + tz.getDisplayName());
// サマータイムの採用情報をもとに分岐処理
if (tz.useDaylightTime()) {
System.out.println("DST is adopted.");
// サマータイムを考慮して世界標準時(UTC)との時差を表示
System.out.print("time difference from UTC: ");
System.out.println(tz.getOffset(calDate) / 3600000 + "[hrs.]");
}
else {
System.out.println("DST is not adopted.");
// サマータイムを考慮せず世界標準時(UTC)との時差を表示
System.out.print("time difference from UTC: ");
System.out.println(tz.getRawOffset() / 3600000 + "[hrs.]");
}
}
}
Locale: 日本語 (日本)
Country Code: JP
Country Name: 日本
Language Code: ja
Language Name: 日本語
TimeZone: 日本標準時
DST is not adopted.
time difference from UTC: 9[hrs.]
メモリ状態
Runtimeクラスを利用することで、JVMの現在のメモリ状態を取得することができる。
定義
// 現在のメモリの「空き容量」[byte]を取得
long Runtime.freeMemory()
// 「現在利用可能」なメモリの「総容量」[byte]を取得
long Runtime.totalMemory()
// 利用可能なメモリの「総容量の最大値」[byte]を取得
long Runtime.maxMemory()
サンプルコード
import java.math.BigDecimal;
import java.math.RoundingMode;
public class JVMMemory {
public static void main(String[] args) {
// Runtimeインスタンスの取得
Runtime rt = Runtime.getRuntime();
System.out.println("-- Information of JVM Memory --");
// 空きメモリ容量[byte]
long freeL = rt.freeMemory();
double freeD = (double) freeL;
// 総容量[byte]
long totalL = rt.totalMemory();
double totalD = (double) totalL;
// 最大容量[byte]
long maxL = rt.maxMemory();
double maxD = (double) maxL;
// BigDecimalを用いたメモリデータ表示
System.out.println("Free: " + new BigDecimal(freeD / 1024 / 1024 / 1024).setScale(2, RoundingMode.HALF_UP) + "[GB]");
System.out.println("Total: " + new BigDecimal(totalD / 1024 / 1024 / 1024).setScale(2, RoundingMode.HALF_UP) + "[GB]");
System.out.println("Use: " + new BigDecimal((totalD - freeD) / 1024 / 1024 / 1024).setScale(2, RoundingMode.HALF_UP) + "[GB]");
System.out.println("Maximum: " + new BigDecimal(maxD / 1024 / 1024 / 1024).setScale(2, RoundingMode.HALF_UP) + "[GB]");
}
}
-- Information of JVM Memory --
Free: 1.01[GB]
Total: 1.02[GB]
Use: 0.01[GB]
Maximum: 16.00[GB]
リフレクション(reflection API)
JVMがもつ実行時型情報(RTTI; run-time type information)を取得するメソッドを提供するAPI。
リフレクションAPIのClass<T>クラスを通じて、実行時型情報を取得することができる。
なお、実行時型情報のうち、クラス(=配列・インタフェース・列挙型を含む)情報はClass<T>インスタンス、
メンバ情報(フィールド・メソッド・コンストラクタ・修飾子)はそれぞれField・Method・Constructor・Modifierインスタンスが保持する。
ただし、修飾子情報の実体はModifierクラスのint型クラス定数で表される。
定義(クラス情報の取得)
// クラス名を「FQCN(fully-qualified class name; 完全限定名)」で指定してクラス情報を取得
Class<?> Class<T>.forName(String className)
// パラメータ
// className: FQCN
// 「クラス名」を指定してクラス情報を取得
Class<?> <クラス名>.class
// 「オブジェクト名」を指定してクラス情報を取得
Class<?> Object.getClass()
定義(クラス情報の取得)
// 「FQCN」の取得
String Class<T>.getName()
// 「クラス名」の取得
String Class<T>.getSimpleName()
// 「所属パッケージ名」の取得
Package Class<T>.getPackage()
// 「所属モジュール名」の取得
Module Class<T>.getModule()
// 「親クラス情報」を取得
Class<? super T> Class<T>.getSuperclass()
// 「配列」であればtrueを返却
boolean Class<T>.isArray()
// 「インタフェース」であればtrueを返却
boolean Class<T>.isInterface()
// 「列挙型」であればtrueを返却
boolean Class<T>.isEnum()
定義(各メンバ情報の取得)
getDeclared*()メソッドはクラスが保持する「全てのメンバ情報」を返却するのに対し、
get*()メソッドは「publicなメンバ情報のみ」を返却する。
// 「フィールド情報」の一覧を取得
Field[] Class<T>.getDeclaredFields()
// 「フィールド情報」を指定して取得
Field Class<T>.getDeclaredField(String name)
// パラメータ
// name: フィールド名
// 「メソッド情報」の一覧を取得
Method[] Class<T>.getDeclaredMethods()
// 「メソッド情報」を指定して取得
// -> 多重定義されている場合があるため、「メソッド名」と「引数の型」を指定
Method Class<T>.getDeclaredMethod(String name, Class<?>... parameterTypes)
// パラメータ
// name: メソッド名
// parameterTypes: メソッドの引数の型
// 「コンストラクタ情報」の一覧を取得
Constructor<?>[] Class<T>.getDeclaredConstructors()
// 「コンストラクタ情報」を指定して取得
Constructor<T> Class<T>.getDeclaredConstructor(Class<?>... parameterTypes)
// パラメータ
// parameterTypes: コンストラクタの引数の型
// 「修飾子情報」を取得
int getModifiers()
サンプルコード
import java.lang.reflect.*;
public class Reflection {
public static void main(String[] args) throws Exception {
// 「クラス」からクラス情報を取得
Class<?> cStatic = ReflectionTest.class;
// 「クラス情報」から引数を指定してコンストラクタ情報を取得
// -> NoSuchMethodException(検査例外)が発生する可能性があるため、
// 以下の方法でエラーハンドリングを行う必要がある
// 1. 呼び出すメソッド(=main())に"throws文"を付与
// 2. "try-catch文"で例外発生時の処理を記述
Constructor<?> con = cStatic.getConstructor(String.class, int.class);
// 「コンストラクタ情報」からオブジェクトの生成
// -> Constructor<?>型 -> 外部クラス型 へのキャストが必要
ReflectionTest ref = (ReflectionTest) con.newInstance("A", 5);
System.out.println("-- Before --");
System.out.println(ref);
System.out.println();
// 「オブジェクト」からクラス情報を取得
Class<?> cDynamic = ref.getClass();
// 「クラス情報」からフィールド情報を取得
// -> privateなメンバを取得する場合は"getDeclared*()"メソッドを利用
Field fStr = cStatic.getDeclaredField("str");
Field fInt = cDynamic.getDeclaredField("i");
// privateなフィールドのアクセス権限を変更
fStr.setAccessible(true);
fInt.setAccessible(true);
// 「フィールド情報」からオブジェクトの動的フィールドの値を変更
fStr.set(ref, "Changed");
fInt.set(ref, 13);
System.out.println("-- After --");
System.out.println(ref);
System.out.println();
// 「クラス情報」や各「メンバ情報」の修飾子を特定
// -> Modifierクラスの「クラス定数」を利用する場合
switch (cStatic.getModifiers()) {
case Modifier.PUBLIC:
System.out.println("Class " + cStatic.getSimpleName() + " is declared as public."); break;
case Modifier.PROTECTED:
System.out.println("Class " + cStatic.getSimpleName() + " is declared as protected."); break;
case Modifier.PRIVATE:
System.out.println("Class " + cStatic.getSimpleName() + " is declared as private."); break;
default:
System.out.println("Class " + cStatic.getSimpleName() + " is declared as default."); break;
}
Field fREF_S = cDynamic.getDeclaredField("REF_STATIC");
int modfREF_S = fREF_S.getModifiers();
// Modifierクラスの「クラスメソッド」を利用する場合
if (Modifier.isPrivate(modfREF_S)) {
System.out.print("Field " + fREF_S.getName() + " is declared as private");
if (Modifier.isStatic(modfREF_S)) {
System.out.print(", static");
if (Modifier.isFinal(modfREF_S)) {
System.out.println(", final.");
}
}
}
}
}
class ReflectionTest {
private String str = "";
private int i = 0;
// 動的final変数(利用しない)
private final String REF = "Final String(dynamic)";
// 静的final変数
private static final String REF_STATIC = "Final String(static)";
// デフォルトコンストラクタ
public ReflectionTest() {}
// オーバーロードしたコンストラクタ
public ReflectionTest(String str) {
this.str = str;
}
public ReflectionTest(int i) {
this.i = i;
}
public ReflectionTest(String str, int i) {
this.str = str;
this.i = i;
}
// オーバーロードした動的メソッド
public void add(String addStr) {
this.str += addStr;
}
public void add(int j) {
this.i += j;
}
public void add(String addStr, int j) {
this.str += addStr;
this.i += j;
}
@Override
public String toString() {
return "ReflectionTest(" + this.str + ", " + this.i + ") " + "[" + REF + ", " + REF_STATIC + "]";
}
}
-- Before --
ReflectionTest(A, 5) [Final String(dynamic), Final String(static)]
-- After --
ReflectionTest(Changed, 13) [Final String(dynamic), Final String(static)]
Class ReflectionTest is declared as default.
Field REF_STATIC is declared as private, static, final.
用語集
| 用語 | 内容 |
|---|---|
| システムプロパティ(system property) |
JVMが管理する、JVMやOSに関するデータを保持するプロパティ。 |
| 環境変数(environment variable) |
OSが管理する、OSに関するデータを保持する変数。 |
| 実行時型情報(RTTI; Run-Time Type Information) |
型がもつパッケージ・親クラス・メンバ・修飾子などの情報。 |