Java 9で静的VarHandleを作成する方法をわかりやすく解説
VarHandleとは
VarHandleは、変数への参照を表すオブジェクトで、通常の読み書き(plain)、揮発性の読み書き(volatile)、コンペア・アンド・スワップ(CAS)といったさまざまなアクセスモードで変数へアクセスする機能を提供します。この仕組みは、java.util.concurrent.atomicパッケージやsun.misc.Unsafeが従来提供していた機能とよく似ています。
VarHandleの操作対象となるのは、配列の要素、クラスのインスタンスフィールド、あるいはstaticフィールドです。
静的VarHandleの作成例
次の例では、staticフィールドへのVarHandleと、配列要素へのVarHandleを作成し、それぞれに対してアトミックな操作を実行しています。
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class StaticVarHandleTest {
static int field;
static int[] array = new int[20];
static final VarHandle FIELD, ARRAY;
static {
try {
FIELD = MethodHandles.lookup().in(StaticVarHandleTest.class).findStaticVarHandle(StaticVarHandleTest.class, "field", Integer.TYPE);
ARRAY = MethodHandles.arrayElementVarHandle(int[].class);
} catch(Exception e) {
throw new InternalError(e);
}
}
public static void main(String args[]) throws Exception {
int i = (int)FIELD.getVolatile();
System.out.println(i);
FIELD.getAndAdd(5);
System.out.println(field);
System.out.println(ARRAY.getAndAdd(array, 5, 5));
System.out.println(ARRAY.getAndAdd(array, 5, 5));
}
}
実行結果
0 5 0 5
コードのポイント
- MethodHandles.lookup().in(...):ルックアップオブジェクトを特定のクラスに限定し、アクセス権を管理します。
- findStaticVarHandle():指定したクラスのstaticフィールドへのVarHandleを取得します。
- arrayElementVarHandle():配列の各要素にアクセスするためのVarHandleを作成します。
- getVolatile()/getAndAdd():volatileセマンティクスによる読み取りや、アトミックな加算処理を行います。
実行結果を見ると、まずFIELD.getVolatile()で初期値「0」を読み取り、getAndAdd(5)によってfieldが「5」に更新されています。続くARRAY.getAndAdd(array, 5, 5)は、インデックス5の要素を更新すると同時に更新前の値を返すため、1回目は「0」、2回目は「5」が出力されます。このようにVarHandleを使うことで、Unsafeを直接使わずに安全かつ標準的なAPIで低レベルなアトミック操作を実現できます。
-
JavaでJSON配列を作成する方法をわかりやすく解説
JSON配列とは、角括弧で囲まれた値の順序付きコレクションのことです。具体的には「[」で始まり「]」で終わり、配列内の各値はカンマ(,)で区切られます。JSON配列のサンプル{ books: [Java, JavaFX, Hbase, Cassandra, WebGL, JOGL] }json-simpleは、JSONオブジェクトを処理するための軽量ライブラリです。このライブラリを使えば、JavaプログラムからJSONドキュメントの内容を読み取ったり、書き込んだりすることができます。json-simpleのMaven依存関係json-simpleライブラリを使用するには、まずpom.x
-
Javaで一時ファイル(テンポラリファイル)を作成する方法
プログラムの実行中に、一時的な情報を保存するためにその場で一時ファイルを作成し、後から削除したいケースはよくあります。 Javaでは、Files.createTempFile() メソッドを使用することで、簡単に一時ファイルを作成できます。 一時ファイルの作成 次の例では、Files.createTempFile(prefix, suffix) を使って一時ファイルを作成しています。 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class CreateTem