サーチ…


備考

Unsafeクラスは、プログラムがJavaコンパイラで許可されていない処理を行うことを許可します。通常のプログラムでは、 Unsafeを使わないでください。

警告

  1. Unsafe APIを使用して間違えた場合、アプリケーションはJVMをクラッシュさせたり、診断しにくい症状を呈したりする可能性があります。

  2. Unsafe APIは予告なしに変更されることがあります。コードで使用する場合は、Javaバージョンを変更するときにコードを書き直す必要があります。

反射によるsun.misc.Unsafeのインスタンス化

public static Unsafe getUnsafe() {
    try {
        Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
        unsafe.setAccessible(true);
        return (Unsafe) unsafe.get(null);
    } catch (IllegalAccessException e) {
        // Handle
    } catch (IllegalArgumentException e) {
        // Handle
    } catch (NoSuchFieldException e) {
        // Handle
    } catch (SecurityException e) {
        // Handle
    }
}

sun.misc.Unsafeにはプライベートコンストラクタがあり、静的なgetUnsafe()メソッドは、コードがプライマリクラスローダでロードされていることを確認するためにクラスローダのチェックで保護されています。したがって、インスタンスを読み込む1つの方法は、反射を使用して静的フィールドを取得することです。

bootclasspath経由でsun.misc.Unsafeをインスタンス化する

public class UnsafeLoader {
    public static Unsafe loadUnsafe() {
        return Unsafe.getUnsafe();
    }
}

この例はコンパイルされますが、Unsafeクラスにプライマリクラスローダがロードされていない限り、実行時に失敗する可能性があります。これを確実にするために、JVMには次のような適切な引数をロードする必要があります。

java -Xbootclasspath:$JAVA_HOME/jre/lib/rt.jar:./UnsafeLoader.jar foo.bar.MyApp

foo.bar.MyAppクラスはUnsafeLoader.loadUnsafe()使用できます。

不安全のインスタンスを取得する

安全でないのは、直接アクセスできないプライベートフィールドとして格納されます。コンストラクタはprivateであり、 public static Unsafe getUnsafe()にアクセスする唯一のメソッドは特権アクセスです。リフレクションを使用すると、プライベートフィールドをアクセス可能にするための回避策があります。

public static final Unsafe UNSAFE;

static {
    Unsafe unsafe = null;

    try {
        final PrivilegedExceptionAction<Unsafe> action = () -> {
            final Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);

            return (Unsafe) f.get(null);
        };

        unsafe = AccessController.doPrivileged(action);
    } catch (final Throwable t) {
        throw new RuntimeException("Exception accessing Unsafe", t);
    }

    UNSAFE = unsafe;
}

不安全の使用

安全でないものの使用例は次のとおりです。

つかいます API
ヒープ/ダイレクトメモリ割り当てのオフ、再割り当ておよび割り当て解除 allocateMemory(bytes)reallocateMemory(address, bytes)およびfreeMemory(address)
メモリフェンス loadFence()storeFence()fullFence()
現在のスレッドを駐車する park(isAbsolute, time)unpark(thread)
直接フィールドおよび/またはメモリアクセスメソッドをget*してput*する
チェックされていない例外のスロー throwException(e)
CASおよびアトミックオペレーション compareAndSwap*メソッドのファミリー
メモリの設定 setMemory
揮発性または並行操作 get*Volatileput*VolatileputOrdered*

メソッドのgetおよびputファミリは、指定されたオブジェクトに関連しています。オブジェクトがnullの場合、絶対アドレスとして扱われます。

// Putting a value to a field
protected static long fieldOffset = UNSAFE.objectFieldOffset(getClass().getField("theField"));
UNSAFE.putLong(this, fieldOffset , newValue);

// Puting an absolute value
 UNSAFE.putLong(null, address, newValue);
 UNSAFE.putLong(address, newValue);

いくつかのメソッドは、intとlongsに対してのみ定義されます。あなたは山車と使用ダブルスでこれらのメソッドを使用することができますfloatToRawIntBitsintBitsToFloat, doubleToRawLongBits , longBitsToDouble`を



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow