ホームページ Java &#&チュートリアル JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

Aug 24, 2019 pm 03:57 PM
jvm

JVM の実行エンジンが Java コードを実行する場合、通常、インタープリタ実行 (インタープリタを介した実行) とコンパイル済み実行 (ジャストインタイム コンパイラを介して生成されたローカル コード実行) の 2 つのオプションがあります。

スタック フレーム

定義:

スタック フレームは、仮想マシンによるメソッド呼び出しとメソッド実行をサポートするために使用されるデータです。仮想マシン スタック内にある構造。

関数:

呼び出しの開始から実行の完了までのすべてのメソッドは、仮想マシン スタック内のスタックからスタックまでのスタック フレームに対応します。のプロセス。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

特徴:

(1) スタックフレームにはローカル変数テーブル、オペランドスタックなどが含まれます。必要ですか? ローカル変数テーブルとオペランド スタックの深さはコンパイル時に決定されます。スタック フレームに割り当てる必要があるメモリの量は、プログラム実行時の変数データの影響を受けないためです。

(2) 2 つのスタック フレーム間のデータ共有。概念モデルでは 2 つのスタック フレームは完全に独立していますが、仮想マシンの実装では、2 つのスタック フレームが部分的に重なるように最適化処理が行われます。このようにして、追加のパラメーターのコピーや受け渡しを必要とせずに、メソッド呼び出しを行うときにデータの一部を共有できます。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

(1) ローカル変数テーブル

ローカル変数テーブルは、変数値の格納セットです。スペース: メソッド パラメータとメソッド内で定義されたローカル変数を格納するために使用されます。

//方法参数   
max(int a,int b)
ログイン後にコピー
int a;//全局变量
void say(){
   int b=0;//局部变量
 }
ログイン後にコピー

ローカル変数はクラス変数(静的に変更された変数)とは異なります

クラス変数には、準備フェーズ(システム初期値の割り当て)と初期化フェーズの 2 つの初期値割り当てプロセスがあります。 (プログラマが定義した初期値を割り当てます)。したがって、初期化フェーズ中にクラス変数に値が割り当てられていなくても、特定の初期値が保持されているため、問題はありません。
ただし、ローカル変数は異なり、定義しても初期値が代入されていない場合は使用できません。

(2) オペレーション スタック

メソッドの実行が開始されたばかりのとき、このメソッドのオペランド スタックは空です。オペランド スタックに内容を書き込み、抽出するためのさまざまなバイトコード命令、つまりポップおよびプッシュ操作があります。

たとえば、次のように計算します。

int a=2+3
ログイン後にコピー

オペランド スタックの先頭に最も近い 2 つの要素は 2 と 3 です。iadd 命令が実行されると、2 と 3 がスタックからポップされます。そして追加されました。 、そして追加された結果 5 をスタックにプッシュします。

(3) ダイナミックリンク

#クラスファイルの定数プールには多数のシンボル参照があり、メソッド呼び出しが行われます。バイトコード内の命令 定数プール内のメソッドへのシンボリック参照をパラメータとして取得するだけです。これらのシンボル参照は 2 つの部分に分かれています。

静的解析: クラスの読み込みフェーズ中または初めて使用されるときに、直接参照に変換されます。ダイナミックリンク: 各実行中に直接参照に変換されます。

(4) 返送先住所


当一个方法开始执行后,只有两种方式可以退出这个方法:正常退出、异常退出。无论采用何种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行。

当方法正常退出时

调用者的PC计数器作为返回地址。栈帧中一般会保存这个计数器值。

当方法异常退出时

返回地址是要通过异常处理器表来确定的。栈帧中一般不会保存这部分信息。

方法调用

方法调用是确定调用哪一个方法。

(1)解析

对“编译器可知,运行期不可变”的方法进行调用称为解析。符合这种要求的方法主要包括

静态方法,用static修饰的方法私有方法,用private修饰的方法

(2)分派

分派讲解了虚拟机如何确定正确的目标方法。分派分为静态分派和动态分派。讲解静动态分派之前,我们先看个多态的例子。

Human man=new Man();
ログイン後にコピー

在这段代码中,Human为静态类型,其在编译期是可知的。Man是实际类型,结果在运行期才可确定,编译期在编译程序的时候并不知道一个对象的实际类型是什么。

静态分派:

所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。它的典型应用是重载。

public class StaticDispatch{  
   static abstract class Human{  
    }  
   static class Man extends Human{
    }
    static class Woman extends Human{
    }
    public void say(Human hum){  
        System.out.println("I am human");  
    }  
    public void say(Man hum){  
        System.out.println("I am man");  
    }  
    public void say(Woman hum){  
        System.out.println("I am woman");  
    }  
    
    public static void main(String[] args){  
        Human man = new Man();  
        Human woman = new Woman();  
        StaticDispatch sr = new StaticDispatch();  
        sr.say(man);  
        sr.say(woman);  
    }  
}
ログイン後にコピー

运行结果是:

I am human
I am human
ログイン後にコピー

为什么会产生这个结果呢?
因为编译器在重载时,是通过参数的静态类型而不是实际类型作为判断依据的。在编译阶段,javac编译器会根据参数的静态类型决定使用哪个重载版本,所以两个对say()方法的调用实际为sr.say(Human)。

动态分派:

在运行期根据实际类型确定方法执行版本的分派过程。它的典型应用是重写。

public class DynamicDispatch{  
   static abstract class Human{  
            protected abstract void say();
    }  
   static class Man extends Human{
            @Override
             protected abstract void say(){
             System.out.println("I am man");  
            }
    }
    static class Woman extends Human{
         @Override
             protected abstract void say(){
             System.out.println("I am woman ");  
            }
    }
    
    public static void main(String[] args){  
        Human man = new Man();  
        Human woman = new Woman();  
        man.say();
        woman.say();
        man=new Woman();
        man.say();
    }  
}
ログイン後にコピー

运行结果:

I am man
I am woman 
I am woman
ログイン後にコピー

这似乎才是我们平时敲的java代码。对于方法重写,在运行时才确定调用哪个方法。由于Human的实际类型是man,因此调用的是man的name方法。其余的同理。

动态分派的实现依赖于方法区中的虚方法表,它里面存放着各个方法的实际入口地址。如果某个方法在子类中被重写了,那子类方法表中的地址将会替换为指向子类实现版本的入口地址,否则,指向父类的实现入口。

单分派和多分派:

方法的接收者与方法的参数统称为方法的宗量,根据分派基于多少种宗量,分为单分派和多分派。

在静态分派中,需要调用者的实际类型和方法参数的类型才能确定方法版本,所以其是多分派类型。在动态分派中,已经知道了参数的实际类型,所以此时只需知道方法调用者的实际类型就可以确定出方法版本,所以其是单分派类型。综上,java是一门静态多分派,动态单分派的语言。

字节码解释执行引擎

虚拟机中的字节码解释执行引擎是基于栈的。下面通过一段代码来仔细看一下其解释的执行过程。

public int calc(){  
    int a = 100;  
    int b = 200;  
    int c = 300;  
    return (a + b) * c;  
}
ログイン後にコピー

第一步:将100入栈。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 2: 操作スタックから 100 をポップし、ローカル変数に保存します。後続の 200,300 についても同様です。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 3: ローカル変数テーブルの 100 をオペランド スタックの先頭にコピーします。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 4: ローカル変数テーブルの 200 をオペランド スタックの先頭にコピーします。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 5: 100 と 200 をスタックからポップし、整数の加算を実行し、最後に結果の 300 をスタックにプッシュします。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 6: ローカル変数テーブルから 3 番目の数値 300 をスタックの先頭にコピーします。次のステップでは、2 つの 300 をスタックからポップし、整数乗算を実行して、最終結果 90000 をスタックにプッシュします。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

ステップ 7: メソッドは終了し、オペランド スタックの最上位の整数値がこのメソッドの呼び出し元に返されます。

JAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジン

上記は、JAVA 仮想マシン バイトコード実行エンジンの完全な紹介です。その他の関連する質問については、PHP 中国語 Web サイトを参照してください: JAVA ビデオ チュートリアル

以上がJAVA 仮想マシン (JVM) の詳細な紹介 (6) - バイトコード実行エンジンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

非常に実用的な分散型 JVM 監視ツールです。 非常に実用的な分散型 JVM 監視ツールです。 Aug 15, 2023 pm 05:15 PM

このプロジェクトは、開発者が複数のリモート ホスト JVM をより速く監視できるように設計されています。プロジェクトが Spring Boot の場合、統合は非常に簡単です。jar パッケージを導入するだけです。Spring Boot でない場合でも、落胆する必要はありません。 Spring Boot プログラムを手早く初期化し、自分で導入する Jar パッケージで十分です

JVM コマンドラインパラメータの詳細説明: JVM の動作を制御する秘密兵器 JVM コマンドラインパラメータの詳細説明: JVM の動作を制御する秘密兵器 May 09, 2024 pm 01:33 PM

JVM コマンド ライン パラメータを使用すると、JVM の動作をきめ細かいレベルで調整できます。共通パラメータは次のとおりです。 Java ヒープ サイズの設定 (-Xms、-Xmx) 新しい世代サイズの設定 (-Xmn) パラレル ガベージ コレクタの有効化 (-XX:+UseParallelGC) Survivor 領域のメモリ使用量の削減 (-XX: -ReduceSurvivorSetInMemory) 冗長性の削除 ガベージ コレクションの削除 (-XX:-EliminateRedundantGCs) ガベージ コレクション情報の印刷 (-XX:+PrintGC) G1 ガベージ コレクターの使用 (-XX:-UseG1GC) ガベージ コレクションの最大休止時間の設定 (-XX:MaxGCPau)

JVMメモリ管理のポイントと注意事項 JVMメモリ管理のポイントと注意事項 Feb 20, 2024 am 10:26 AM

JVM のメモリ使用量を使いこなすためのポイントと注意点 JVM (JavaVirtualMachine) は Java アプリケーションが動作する環境であり、最も重要なのは JVM のメモリ管理です。 JVM メモリを適切に管理すると、アプリケーションのパフォーマンスが向上するだけでなく、メモリ リークやメモリ オーバーフローなどの問題も回避できます。この記事では、JVM メモリ使用の重要なポイントと考慮事項を紹介し、いくつかの具体的なコード例を示します。 JVM メモリ パーティション JVM メモリは主に次の領域に分割されます。 ヒープ (ヒープ)

JVM仮想マシンの機能と原理の分析 JVM仮想マシンの機能と原理の分析 Feb 22, 2024 pm 01:54 PM

JVM 仮想マシンの機能と原理の分析の紹介: JVM (JavaVirtualMachine) 仮想マシンは、Java プログラミング言語の中核コンポーネントの 1 つであり、Java の最大のセールス ポイントの 1 つです。 JVM の役割は、Java ソース コードをバイトコードにコンパイルし、これらのバイトコードを実行することです。この記事では、JVM の役割とその仕組みを紹介し、読者の理解を深めるためにいくつかのコード例を示します。機能: JVM の主な機能は、さまざまなプラットフォーム上での Java プログラムの移植性の問題を解決することです。

Java エラー: JVM メモリ オーバーフロー エラー、対処方法と回避方法 Java エラー: JVM メモリ オーバーフロー エラー、対処方法と回避方法 Jun 24, 2023 pm 02:19 PM

Java は人気のあるプログラミング言語ですが、Java アプリケーションの開発中に、JVM メモリ オーバーフロー エラーが発生する場合があります。通常、このエラーによりアプリケーションがクラッシュし、ユーザー エクスペリエンスに影響を与えます。この記事では、JVM メモリ オーバーフロー エラーの原因と、そのようなエラーに対処および回避する方法について説明します。 JVMメモリオーバーフローエラーとは何ですか? Java 仮想マシン (JVM) は、Java アプリケーションの実行環境です。 JVM では、メモリはヒープ、メソッド領域、スタックなどの複数の領域に分割されます。ヒープは作成されたオブジェクトを保存するために使用されます

JVM が 32 ビットか 64 ビットかを確認する Java プログラム JVM が 32 ビットか 64 ビットかを確認する Java プログラム Sep 05, 2023 pm 06:37 PM

JVM が 32 ビットか 64 ビットかを確認する Java プログラムを作成する前に、まず JVM について説明します。 JVM は Java 仮想マシンであり、バイトコードの実行を担当します。これは Java ランタイム環境 (JRE) の一部です。 Java はプラットフォームに依存しませんが、JVM はプラットフォームに依存することは誰もが知っています。オペレーティング システムごとに個別の JVM が必要です。 Java ソース コードのバイトコードがあれば、JVM により任意のプラットフォームで簡単に実行できます。 Java ファイル実行のプロセス全体は次のとおりです。まず、Java ソース コードを .java 拡張子で保存し、コンパイラがそれを .class 拡張子を持つバイトコードに変換します。これはコンパイル時に発生します。さて、実行時に、J

JVM ヒープ メモリ サイズを効率的に調整するにはどうすればよいですか? JVM ヒープ メモリ サイズを効率的に調整するにはどうすればよいですか? Feb 18, 2024 pm 01:39 PM

JVM メモリ パラメータ設定: ヒープ メモリ サイズを合理的に調整するにはどうすればよいですか? Java アプリケーションでは、JVM はメモリの管理を担当する主要なコンポーネントです。このうちヒープ メモリはオブジェクト インスタンスの保存に使用され、ヒープ メモリのサイズ設定はアプリケーションのパフォーマンスと安定性に重要な影響を与えます。この記事では、ヒープメモリサイズを合理的に調整する方法を具体的なコード例とともに紹介します。まず、JVM メモリに関する基本的な知識を理解する必要があります。 JVM のメモリは、ヒープ メモリ、スタック メモリ、メソッド領域などを含むいくつかの領域に分割されます。で

JVM の動作原理の謎を解く: Java 仮想マシンの原理の詳細な探求 JVM の動作原理の謎を解く: Java 仮想マシンの原理の詳細な探求 Feb 18, 2024 pm 12:28 PM

JVM 原理の詳細な説明: Java 仮想マシンの動作原理を詳しく調べるには、特定のコード例が必要です。 1. はじめに Java プログラミング言語の急速な発展と広範な応用により、Java 仮想マシン (JavaVirtualMachine、JVM と呼ばれます) が登場しました。 )もソフトウェア開発には欠かせないものとなっています。 Java プログラムの実行環境として、JVM はクロスプラットフォーム機能を提供し、Java プログラムをさまざまなオペレーティング システムで実行できるようにします。この記事では、JVM の仕組みについて詳しく説明します。

See all articles