この記事のメインテキストを開始する前に、次のコードをご覧ください。
Javaの整数クラスの整数の役割
パッケージ名:java.lang
ファイル名:integer.java
メソッド名:integercache
メソッドのコードは次のとおりです。
private static class integercache {static final int high;静的最終整数キャッシュ[]; static {final int low = -128; //高い値は、プロパティint h = 127で構成できます。 if(integercachehighpropvalue!= null){//ここでlong.decodeを使用して、// integerの自動ボクシングキャッシュを初期化する必要がある方法を呼び出さないようにします。 i = math.max(i、127); //最大配列サイズはinteger.max_value h = math.min(i、integer.max_value - low); } high = h; cache = new Integer [(high -low) + 1]; int j = low; for(int k = 0; k <cache.length; k ++)cache [k] = new Integer(j ++); } private integercache(){}}コードでは、Lowは-128、Highは127であることがわかります。このようにして、Javaプログラミングでは、間隔-128-127でオブジェクトを使用する場合、このキャッシュでオブジェクトを直接使用します。
上記は、誰もがintegercacheを理解するのに役立つ簡単な紹介です。この記事の主なテキストは次のとおりです。
導入
5年前、私はJDKのintegercacheを変更する方法についてハンガリーに投稿を投稿しました。このアプローチは、実際にはJavaランタイムに深く入り込むことであり、実際にはシナリオでは使用されていません。この研究コードを開発すると、反射がどのように機能し、整数クラスがどのように実施するかをよりよく理解できます。
整数クラスには、-127から128の範囲の値を持つ整数オブジェクトを含むintegercacheという名前のプライベートネストがあります。
コードをintタイプから整数オブジェクトに囲む必要があり、値がこの範囲内にある場合、Javaランタイムは新しい整数オブジェクトを作成する代わりにこのキャッシュを使用します。これは主にパフォーマンスの最適化に関する考慮事項に関するものです。多くのINT値は、プログラムのこの範囲内にあることが多いことに注意してください(配列の添え字インデックスなど)。
これの副作用は、多くの場合、等号演算子を使用して2つの整数オブジェクトを比較する場合、値が範囲内にある限り、有効であることです。これは、単体テストで典型的です。実行モードでは、値が128を超えると、コードの実行が失敗します。
リフレクションを使用してIntegerCacheクラスにアクセスすると、奇妙な副作用が発生する可能性があります。これはJVM全体に影響することに注意してください。サーブレットが小整数キャッシュ値を再定義する場合、同じTomcatの下で実行される他のすべてのサーブレットが同じ問題に遭遇します。
Lukas EderとSitePointには、上記の他の記事があります。
Java 9の初期のリリースで遊んでいるので、私が常に心の中でやらなければならなかったのは、新しいJavaバージョンを試すことだけです。開始する前に、Java 8でそれを行う方法を見てみましょう。
Lukasの記事で、私は彼のサンプルコードをここに投稿しました:
Import java.lang.reflect.field; Import java.util.random; public class entropy {public static void main(string [] args)throws exception {//反射クラスを介してintegercacheを抽出しますか? > clazz = class.forname( "java.lang.integer $ integercache");フィールドフィールド= clazz.getDeclaredfield( "キャッシュ"); field.setAccessible(true); integer [] cache =(integer [])field.get(clazz); //(int i = 0; i <cache.length; i ++){cache [i] = new integer(new Random()。nextint(cache.length)); } //(int i = 0; i <10; i ++){system.out.println((integer)i); }}}このコードは、反射を介してintegercacheにアクセスし、ランダム値を使用してキャッシュを埋めます(いたずら!)。
Java 9で同じコードを実行しようとします。楽しみを期待しないでください。誰かがそれに違反しようとすると、Java 9がより制限的であることがわかります。
スレッド「Main」java.lang.reflect.inaccessibleObjecception:フィールド静的な最終java.lang.integerを作成できませんjava.lang.integer $ integercache.cacheアクセス可能:モジュールjava.baseはjava.lang "Opens java.lang" Open
このプログラムは、Java 8では発生しない例外をスローします。オブジェクトはモデルベースではないと言うのと同等です。 Java.Baseモジュールのため、これはJDKの不可欠な部分です。各Javaプログラムが開始されたときに自動的にインポートされ、名前のないモジュールは開かれていません。この例外は、フィールドにアクセス可能なプロパティを設定しようとするとスローされます。
Java 8で簡単にアクセスできるオブジェクトは、Java 9でアクセスできなくなりました。これは、新しいモジュールシステムがこれを保護するためです。コードは、クラスが同じモジュールにある場合にのみ、反射によってアクセスできるフィールド、メソッド、およびその他の情報のみにアクセスできます。モジュールには、反射アクセス用のパッケージが開かれています。これは、モジュールinfo.javaモジュール定義ファイルを介して実装できます。
モジュールmyModule {exports com.javax0.module.demo; com.javax0.module.demoを開く;}このモジュールJava.Baseは、特に名前のないモジュールの場合、反射アクセスのために独自に開く必要はありません。モジュールを作成して名前を付けると、エラーメッセージにはモジュールの名前が含まれます。
プログラムでモジュールを開くことはできますか? java.lang.reflect.Moduleモジュールには、実行できるアドペンメソッドがあります。
実行可能ですか?
開発者にとっての悪いニュースは、それが実行可能ではないことです。別のモジュールのモジュール内のパッケージのみを開くことができ、このメソッドを呼び出すことにより、そのモジュールでパッケージが開かれました。この方法では、他のモジュールが何らかの方法で同じパッケージを開き、未開封のパッケージを開くことができない場合、モジュールを別のモジュールの権利に渡すことのみを可能にすることができます(翻訳者注:理解するのは難しいですか?)。
しかし、同時に、良いニュースは次のとおりです。Java9はJava 8ほど簡単に割るのは簡単ではありません。少なくともこの脆弱性は閉じられています。 Javaはおもちゃだけでなく、プロのレベルに向かって発展し始めているようです(翻訳者の注:Javaはおもちゃだと誰が言いましたか?)。近い将来、RPGおよびCOBOL言語のプロジェクトをJavaに非常に真剣に移行できます。 (申し訳ありませんが、冗談を言っていました)
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。
この記事は、https://dzone.com/articles/hacking-the-integercache-in-java-9から翻訳されています