序文
この記事では、主にJavaの安全でないクラスに関する関連コンテンツを紹介します。参照と学習のために共有されます。以下ではあまり言いません。詳細な紹介を一緒に見てみましょう。
1。安全でないクラスの紹介
安全でないクラスはsun.miscパッケージの下にあり、Java標準に属していません。ただし、いくつかの広く使用されている高性能開発ライブラリを含む多くのJava基本クラスライブラリは、Netty、Hadoop、Kafkaなどの安全でないクラスに基づいて開発されています。
Unsafeを使用して、システムメモリリソースに直接アクセスし、独立して管理できます。危険なクラスは、Javaの運用効率を改善し、Java言語の基礎となる操作能力を高める上で大きな役割を果たします。
安全でないことは、Javaに残されたバックドアと見なすことができ、直接メモリアクセス、スレッドスケジューリングなどの低レベルの操作を提供します。
安全でないことはお勧めしません。
以下は、安全でないものを使用する例をいくつか紹介します。
1.1プライベートクラスをインスタンス化します
java.lang.reflect.fieldをインポートします。 sun.misc.unsafeをインポートします。 public class unsafeplayer {public static void main(string [] args)スロー例外{// instantiate unsafe field f = unsafe.class.getDeclaredfield( "theunsafe"); f.setAccessible(true);安全でないUnsafe =(安全でない)F.get(null); //インスタンス化プレーヤープレーヤー=(プレーヤー)Unsafe.AllocateInstance(player.class); player.setname( "li lei"); System.out.println(player.getName()); }} class player {private string name; private player(){} public string getname(){return name; } public void setName(string name){this.name = name; }} 1.2CAS操作、メモリオフセットアドレスの変更によりメーターの値を変更する
CASを使用して、Java ConcurrencyパッケージのSynchronousqueueでトランスフルストックのスタックの上部を更新します。
/ Unsafe MechanicsPrivate Static Final Sun.misc.unsafe Unsafe; private static final long Headset; static {try {unsafe = sun.misc.unsafe.getunsafe(); class <?> k = transferstack.class; headoffset = unsafe.objectfieldoffset(k.getdeclaredfield( "head")); } catch(Exception E){新しいエラー(e); }} //揮発性スノードヘッド; //スタックブールキャッシュヘッドの上部を更新(Snode H、Snode NH){return h == head && unsafe.compareandswapobject(this、headoffset、h、nh);} 1.3直接メモリアクセス
Unsafeの直接メモリアクセス:Unsafeで開かれたメモリスペースは、ヒープスペースを占有しません。もちろん、自動メモリ回復機能はありません。 Cのようにシステムメモリリソースを自由に使用できるようにします
2。安全でないクラスソースコード分析
UnsafeのAPIのほとんどは、主に次のカテゴリを含むネイティブ方法です。
1)クラス関連。主にクラスとその静的フィールドの動作方法を提供します。
2)オブジェクト関連。主にオブジェクトの動作方法とそのフィールドを提供します。
3)Arrray関連。主に、それらの配列と要素の動作方法を提供します。
4)同時相関。主に、CAS、スレッドスケジューリング、揮発性、メモリバリアなどの低レベルの同期プリミティブを提供します。
5)メモリ関連。直接的なメモリアクセス方法(Javaヒープをバイパスし、ローカルメモリを直接操作する)を提供します。これは、Cなどのシステムメモリリソースを自由に利用できます
6)システム関連。主に、アドレスサイズやメモリページのサイズなど、いくつかの低レベルのメモリ情報を返します。
2.1クラス関連
//静的属性のオフセットは、対応するクラスオブジェクトパブリックネイティブLong StaticFieldOffset(フィールドF)の静的属性の読み取りおよび書き込みに使用されます。パブリティネイティブオブジェクトStaticFieldBase(フィールドF); //クラスを初期化する必要があるかどうかを判断する公開ネイティブブール値を使用する必要があります(クラス<?> c);ローダー、ProtectionDomain ProtectionDomain); //クラスを動的に作成するために使用できる匿名クラスを定義しますパブリティネイティブクラス<?
2.2オブジェクト関連
Javaには、基本的なタイプ(Boolean、Byte、Char、short、int、long、long、float、double)およびオブジェクト参照タイプには次の方法があります。
//オブジェクトのフィールドオフセットを取得しますパブリックネイティブLong ObjectFieldOffset(フィールドF); //指定されたオブジェクトアドレスのint値を取得しますオフセットパブリックネイティブint getInt(オブジェクトO、ロングオフセット); //指定されたオブジェクトのint値を設定しますオフセットオフセットパブリックネイティブボイドプティント(オブジェクトO、ロングオフセット、int x);
//オブジェクトを作成しますが、そのコンストラクターは呼び出されません。クラスが初期化されていない場合、クラスは初期化されます。パブリックネイティブオブジェクトAllocateInstance(class <?> cls)がインスタンス化エクセプトをスローします。
2.3アレイ関連
/** * a *指定された配列クラスのストレージ割り当ての最初の要素のオフセットを報告します。 {@link #arrayindexscale}が同じクラスのゼロ以外の値 *を返す場合、この *ベースオフセットとともにそのスケール係数を使用して、新しいオフセットを形成して *指定されたクラスの配列の要素にアクセスできます。 * * @see #getint(object、long、int) * ///配列のパブリックネイティブint arraybaseoffset(class <?> arrayclass)の最初の要素のオフセットアドレスを返します(class <? array_boolean_base_offset = theunsafe.arraybaseoffset(boolean []。class); /** *ストレージの要素にアドレス指定するスケール係数を報告 *特定の配列クラスの割り当て。ただし、「狭い」タイプ *の配列は、通常、{@link * #getByte(object、int)}などのアクセサに適切に動作しないため、そのようなクラスのスケール係数はゼロとして報告されます。 * * @see #arraybaseoffset * @see#getint(object、long) * @see #putint(object、long、int) * ///配列の各要素が占めているサイズを返しますpublic Native int arrayindexscale(class <?> arrayclass); // boolean、byte、short、char、int、long、float、double、and object型には次の方法があります/** {@code arrayindexscale(boolean []。class)}*/public static final int array_boolean_index_scale = theunsafe.arrayindexscale(boolean []。クラス);メモリ内の配列内の各要素の位置は、ArrayBaseOffsetとArrayIndexscaleを介して配置できます。
2.4並行性関連
2.4.1CAS関連
CAS:CompareAndSwap、メモリオフセットアドレスオフセット、期待値の期待値、新しい値x。現在の時間で変数の値と期待値が等しい場合は、変数の値をxに更新してみてください。更新が成功した場合はtrueを返します。それ以外の場合は、falseを返します。
//変数値をxに更新します。現在の値が予想される場合// o:オブジェクトオフセット:オフセット:期待値x:新しい値パブリックファイナルネイティブブールアンドスワップオブジェクト(オブジェクトO、ロングオフセット、オブジェクト予想、オブジェクトx);パブリックファイナルネイティブブールアンドスワピント(オブジェクトO、ロングオフセット、int redict、int x);パブリックファイナルネイティブブールの比較(オブジェクトO、ロングオフセット、長い予想、ロングx);
Java 8から始めて、次の方法は安全ではありません。
// public final int getandaddint(object o、long offset、int delta){int v; do {v = getIntvolatile(o、offset); } while(!compareandswapint(o、offset、v、v + delta)); Return V do {v = getLongVolatile(o、offset); } while(!compareandswaplong(o、offset、v、v + delta)); return v do {v = getIntValatile(o、offset); } while(!compareandswapint(o、offset、v、newValue)); return v;} public final long getandsetlong(オブジェクトo、long offset、long newValue){long v; do {v = getLongValatile(o、offset); } while(!compareandswaplong(o、offset、v、newValue)); Return V {v = getobjectvalatile(o、offset); } while(!compareandswapobject(o、offset、v、newValue)); vを返します。2.4.2スレッドスケジューリング関連
//パブリックネイティブボイドアンパーク(オブジェクトスレッド); //ブロックスレッドパブリックネイティブボイドパーク(boolean isabsolute、long time); //オブジェクトロックパブリックネイティブボイドモニターエンター(オブジェクトO);
2.4.3揮発性関連の読み取りと書き込み
Javaには、基本的なタイプ(Boolean、Byte、Char、short、int、long、long、float、double)およびオブジェクト参照タイプには次の方法があります。
//オブジェクトの指定されたオフセットから変数の参照を取得し、揮発性の負荷セマンティクスを使用します// getobjectの揮発性バージョン(オブジェクト、長い)パブリックオブジェクトgetobjectvolatile(オブジェクトO、ロングオフセット)に相当します。 //オブジェクトの指定されたオフセットへの変数の参照を保存し、揮発性のストレージセマンティクスを使用します
/** * {@link #putobjectvolatile(object、long、object)} *のバージョンは、他のスレッドに対するストアの即時の可視性を保証しません。この方法は、一般に、 *基礎となるフィールドがJava揮発性である場合にのみ役立ちます(または、アレイセル、1つは揮発性アクセスを使用してのみアクセスされる場合)。 */public Native void putorderedObject(オブジェクトO、ロングオフセット、オブジェクトX); /** {@link #putintvolatile(object、long、int)}*/public native void putorderedint(object o、long offset、int x); /** {@link #putlongvolatile(object、long、long)}*/public native void putorderedlong(object o、long offset、long x);2.4.4関連するメモリバリア
Java 8は、コードの再注文を避けるためにメモリの障壁を定義するために導入されました。
//メモリバリア、負荷操作が再注文されること、つまり障壁の前の負荷操作を障壁に並べ替えることはできません。障壁の後の負荷操作は、障壁の前面に並べ替えることができません();障壁の前面に公衆ネイティブのvoid fullfence();
2.5直接メモリアクセス(非HEAPメモリ)
AllocateMemoryによって割り当てられたメモリは、手動で無料である必要があります(GCによってリサイクルされていません)
//(boolean、byte、char、short、int、long、float、double)次の2つの方法があります。 //指定されたアドレスでint値を取得するパブリックネイティブint getint(長いアドレス); //指定されたアドレスでint値を設定します//パブリックネイティブロングアロカテメモリ(長いバイト); //リアルロケートパブリックネイティブロングリアルカテメモリー(長い住所、長いバイト); //メモリコンテンツの初期化パブリックオフセット、長いバイト、バイト値); setMemory(null、address、bytes、value);} //メモリコンテンツの初期化public native void copymemory(オブジェクトsrcbase、long srcoffset、object destbase、long destoffset、long bytes); //メモリコンテンツの初期化null、destaddress、bytes);} //公開ネイティブvoid freememory(長い住所)をリリースします。
2.6システム関連
//ポインターのサイズを返します。返品値は4または8です。パブリックネイティブint addresssize(); /** {@code addresssize()}*/public static final int dorders_size = theunsafe.addresssize();の値; //メモリページのサイズ。 public Native int pagesize();3。参照資料
//www.vevb.com/article/140709.htm Javaの安全でないクラスについて話しましょう
//www.vevb.com/article/140721.htm Java Magic Class:sun.misc.unsafe
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。