HotSpot 仮想マシンのソースコードから Java のアクセス制御修飾子を理解する

HotSpot 仮想マシンのソースコードから Java のアクセス制御修飾子を理解する

[[340301]]

前回の Ribbon ソース コード分析の記事で、読者から次のような質問がありました。「XX クラスはパッケージ プライベートですが、書き直してもエラーは発生しないでしょうか?」答えは、実際には XX クラスはパッケージプライベートではなく、保護された静的内部クラスであるため、書き換えてもエラーは発生しないということです。

Java アクセス制御修飾子の役割に関しては、私も最初に Java を学んだときは暗記に頼っていました。さらにコードを書いていくうちに自然と理解できましたが、基礎となる実装について非常に興味があったので、長年の疑問に答えるために、HotSpot 仮想マシンのソース コードから答えを見つけようともしました。

クラス、フィールド、メソッドのアクセス制御修飾子は何ですか?

プライベート <private>、サブクラスにアクセス可能 <protected>、パブリック、パッケージ プライベート <package>、アクセス制御修飾子のないデフォルトではパッケージ プライベートです。

アクセス範囲 プライベート パッケージ 保護された 公共
同じクラス アクセス可能 アクセス可能 アクセス可能 アクセス可能
同じパッケージ内の他のクラス アクセスできません アクセス可能 アクセス可能 アクセス可能
異なるパッケージ内のサブクラス アクセスできません アクセスできません アクセス可能 アクセス可能
異なるパッケージ内の非サブクラス アクセスできません アクセスできません アクセスできません アクセス可能

パッケージ private <package> は、同じパッケージ内のクラスだけがアクセスでき、他のパッケージ内のクラスはアクセスできないことを意味します。

今日は、Java 仮想マシンを詳しく調べて、これらのアクセス制御修飾子のセマンティクスの実装について検討します。

InstanceKlass は、HotSpot VM のクラス ファイル構造に対応するデータ構造です。 InstanceKlass オブジェクトは、Java クラスが HotSpot VM によってロードされ、メソッド領域に格納された後に生成される C++ オブジェクトです。 Java コードで使用する Class オブジェクトは、実際には InstanceKlass のミラーです。

Java は、「this.」、「support.」、「a particular object.」の使用をサポートします。メソッド、または「特定のクラス」を呼び出します。静的メソッドを呼び出します。私たちの観点からすると、これはクラスの静的メソッドまたはオブジェクトのメソッドを呼び出していますが、仮想マシンでは違いはなく、すべてメソッド呼び出しです。

静的メソッドとオブジェクト メソッドの呼び出しの唯一の違いは、オブジェクト メソッドを呼び出すには、メソッド パラメーターで "this" 参照を渡す必要があることです。これは、コンパイラが Java コードをバイトコードにコンパイルするときに自動的に追加される暗黙的なパラメーターです。

「this」の使用の違い。そして「サポート」。 Java コードで独自のメソッドと親クラスのメソッドを呼び出す場合の違いは、生成されたメソッド呼び出しバイトコード命令のオペランドが異なる Methodref 定数を指し、メソッドの最初の暗黙的なパラメータによって渡されるオブジェクトが同じであることです。 Methodref 定数は、クラス名、メソッド名、メソッド記述子を含むメソッドへのシンボリック参照を参照します。

クラスのロードプロセスには、ロード、リンク、初期化の 3 つの段階が含まれることがわかっています。リンク段階は、検証、準備、解析の 3 つの段階にさらに分けられます。次の図はクラスのロード段階を理解するのに役立ちますが、正確ではありません。

Java 仮想マシン仕様では、クラスをロードするときに実行する必要があることのみが指定されており、順序に関する厳密な要件はありません。

次の図は、HotSpot 仮想マシン クラスのロード ソース コードを読んで、著者がまとめたフローチャートであり、参考用です。 (元の画像が必要な場合は、公式アカウント「hotspot」に返信してください)

HotSpot 仮想マシンでは、ロード フェーズの後にリンク フェーズの準備フェーズが完了します。リンクフェーズの検証も複数の検証に分割されます。このうち、ファイル形式の検証とメタデータの検証はロードフェーズで相互に完了しますが、バイトコード検証フェーズはクラスの初期化前にトリガーされ、解析フェーズはクラスのロードが完了した後に実行されます。

new、getstatic、putstatic、invokestatic など、クラスの初期化を引き起こすいくつかの命令では、仮想マシンがこれらの命令を実行するときに、まずクラスが初期化されているかどうかを判断します。そうでない場合は、クラスの初期化を完了します。リンク フェーズは、クラス初期化フェーズの前にトリガーされます。

リンク フェーズの解析段階は、Java 仮想マシンが定数プール内のシンボリック参照を直接参照に置き換えるプロセスです。 Java 仮想マシン仕様によれば、定数プール内のシンボリック参照定数 (CONSTANT_Class_info、CONSTANT_Field_info、CONSTANT_Methodref_info など) を指すオペランドを必要とする ane-warray、checkcast、getfield、getstatic、instanceof、invokedynamic、invokeinterface、invoke-special、invokestatic、invokevirtual、ldc、mulianewarray、new、putfield、putstatic などの命令を実行する前に、使用されるシンボリック参照をまず解析する必要があります。

シンボリック参照は、参照先クラスの CONSTANT_Class_info、クラスの参照先フィールドの CONSTANT_Field_info、クラスの参照先メソッドの CONSTANT_Methodref_info など、一連のシンボルを使用して参照先を記述します。

シンボル参照の検証は解析フェーズ中に行われます。シンボル参照の検証には、文字列で記述された完全修飾名が対応するクラスを見つけることができるかどうか、単純名で記述されたメソッドとフィールドが指定されたクラスに存在するかどうか、およびシンボル参照内のクラス、フィールド、およびメソッドのアクセス可能性が含まれます。 、公共、 )。

HotSpot 仮想マシンの実装では、解釈実行と動的呼び出し (invokedynamic) の場合、シンボリック参照が使用される前に解決フェーズが実行されます。

メソッド呼び出しソースコード: javaCalls.cpp;リンク解決ソースコード: linkResolver.cpp;

  1. // クラスをチェックする
  2. リンクリゾルバ::check_klass_accessability
  3. // チェック方法
  4. リンクリゾルバ::check_method_accessability
  5. // フィールドをチェックする
  6. LinkResolver::check_field_accessability

これらのメソッド呼び出しは、最終的に Reflection::verify_field_access メソッドなどの Reflection クラスの対応する verify メソッドを呼び出して、アクセス可能かどうかの判断を完了します。

Java 仮想マシンは、クラス ファイル構造を解析するときとバイトコード検証フェーズ中に、アクセス制御修飾子も検証します。

たとえば、クラス ファイル構造を解析するときに、親クラスを継承できるかどうかを確認します (Reflection::verify_class_access)。

クラスのアクセス修飾子は、クラスが他のクラスからアクセスできるかどうかを決定します。クラス ファイル構造の解析段階では、仮想マシンは、現在のクラスが親クラスを継承できるかどうか (親クラスのアクセス制御修飾子によって決定)、および各インターフェイスを実装できるかどうか (インターフェイスのアクセス修飾子によって決定) を確認できます。

バイトコード検証フェーズでは、現在のクラスがターゲット クラスの保護されたメソッドまたはフィールドにアクセスできるかどうかが検証されます。

バイトコード検証フェーズでは、仮想マシンはクラスの各メソッド内の各バイトコード命令を検証しますが、バイトコード検証フェーズでは、仮想マシンは getfield 命令に対してのみ check_protected 検証を実行します。バイトコード検証フェーズではアクセス制御の検証はあまり行われていないことがわかります。

この記事はWeChatの公開アカウント「Java Art」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合はJava Art公式アカウントまでご連絡ください。

[[340304]]

<<:  誰かがテンセントミーティングの計算をしたところ、5か月で714億元の社会コストが節約されたことが判明した。

>>:  JavaアプリケーションのKubernetesへの移行が加速している

推薦する

「Sheep a Sheep」はByteDanceのゲーム化の夢を活かす

「羊伝説」はWeChatとDouyinプラットフォームでオンラインになり、1か月近く人気が続いていま...

ウェブサイトの最適化には、真実かつ信頼できる

インターネットには真実と虚偽が多すぎます。検索市場はインターネットの最も本物の描写です。検索市場の検...

リトル・レッド・ブックのゲーム・オブ・スローンズ!

小紅書がKOLに対する厳しい取り締まりを開始してから9日が経過したが、このプラットフォームが従業員を...

最も重要な 5 つの分散システム設計パターン

分散アプリケーションは、現代のソフトウェア開発業界の定番です。これらはクラウド ストレージ サービス...

モノのインターネット (IoT) 向けトップ 11 クラウド プラットフォーム

ここでは、モノのインターネット (IoT) 開発に最も人気があり推奨されるプラットフォームを紹介しま...

建国記念日65周年キックオフイベント!

今年のTフロアイベントは、ASフォーラム(私が設立)の水上エリアにて午後9時から開催される予定です!...

QQオンラインショッピングがPaipaiマイクロストアと提携:マルチプラットフォーム開発をサポート、まずは2万元の保証金を支払う

【億騰電網ニュース】4月21日、JD.com POPプラットフォームとQQは本日共同で発表を行い、テ...

アプリプロモーションに必要なASO最適化テクニックとアイデア

上司から与えられるお金がこんなに少ないのに、どうやって商品を宣伝できるのかと友人たちが不満を漏らすの...

ウェブサイトを構築する前に、クラウドサーバーと仮想ホストの4つの違いを見てみましょう

クラウド サーバーと仮想ホストは名前が非常に似ているため、多くの企業はそれらの違いを理解していません...

IDC レポート: 中国電子クラウドが政府クラウド プラットフォームのトップにランクイン!

最近、世界有数のIT調査・コンサルティング企業であるInternational Data Corpo...

faconhost: 香港の高性能ダイレクトコネクト大帯域幅 VPS、年間 27.99 ポンド、512M メモリ/1 コア/10g NVMe/500g トラフィック

faconhostは香港VPSシリーズを新たに発売しました。デフォルトの帯域幅は100Mbpsです(...

型破りなSEOでウェブサイトのトラフィックが急増

後で知ったのですが、今夜はとても力強い共有セッションを聞いて、とても価値があったと感じました。これは...

Baidu の外部リンク アルゴリズムの更新後、推奨されない外部リンクはどれか

4月25日、Baiduはウェブマスタープラットフォームを通じて「外部リンクの判断について」と題した発...

分散ストレージ構築のための2つの展開モード(分離型またはハイパーコンバージド型)

データセンターの内部システムに求められる中核となる要件は「安定性と信頼性」です。まず、システムは運用...