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への移行が加速している

推薦する

ローカル Web サイト - コミュニティとポータルに関する考察

著者が作成した小さな郡のポータルは、最終的には大失敗に終わりましたが、実際の運用とプロモーションの経...

ウェブサイト構築からSEOを始めましょう。Yunzhiウェブサイト構築は、ウェブサイト構築におけるSEOツールです。

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますSEO を...

Kubernetes コンテナ クラウド プラットフォームへの移行について知っておくべき 9 つのこと

1. 既存のプラットフォームが直面する課題コンテナへの移行に対する当初の意図は企業によって異なります...

ウェブサイトのタイトルを変更した後、重みとランキングを復元する方法

多くのウェブマスターは、ウェブサイトの構築を始めるときに厳密に物事を考えず、タイトルをかなり大雑把に...

SEM戦略のアイデアを分析し策定する

ほとんどの SEM 担当者は、大規模な電子商取引サイトの検索エンジン マーケティングに関しては途方に...

#BlackFriday# sharktech: Shark データセンター、専用サーバー 44 ドル、VPS 年間支払い 36 ドル、すべて 60G 防御付き

Sharktech(シャークデータセンター)がブラックフライデー5年目にして役立つ情報を配信しました...

#11.11# cmivps: 香港 VPS 生涯 50% オフ、香港 CN2 (Ali 専用回線) + 米国専用サーバー生涯 10% オフ、クラスター サーバー付き

2018 年のダブル イレブン期間中、cmivps は次のような素晴らしいプロモーションを実施しまし...

NetEase、ゲーム分野で戦い続ける

最近、NetEase は 2019 年 6 月 30 日を締め日とする第 2 四半期の業績発表と中間...

中国、オンライン著作権侵害と海賊版対策として「建王作戦」を開始

北京7月4日(隋小飛記者)記者は4日、北京で行われた2012年「剣ネット作戦」ネット著作権侵害・海賊...

エッジコンピューティングはコロナウイルス後に繁栄すると予想される

コロナウイルスが世界的に流行する前は、エッジコンピューティングはIT分野で最も注目されている新興トレ...

百度百科事典の作り方は?百度百科事典のプロモーション効果分析

Baidu 百科事典は、Baidu が立ち上げたオンライン百科事典で、オープンなコンテンツ、厳格なレ...