あなたは後ろにHello Worldの原則を知りません

アリは伝えプログラマに書道に非常に興味を持って、この点で何かを達成するために引退することを決めました。だから、最高の四個の宝を買う大金を費やしています。

ある日、食事の緊急正興た後、いくつかのSurusumiは、紙を提案し、良い、非常に王羲之のスタイルではなく、円チェンの勢いと白檀を点灯して、ハード瞬間を見て、インクブラシ、厳粛に彼の言葉を書いた:こんにちは世界。

あなたは後ろにHello Worldの原則を知りません

もちろん、これはプログラマハッハッハのユニークな作品です。

だから、そう長くHello Worldのために書いている、我々はあなたが書いたものの後ろに自分の理解を決定する問題は、原理は何ですか?(O≖◡≖)

あなたはそれを明確にすることができた場合、[、コンパイル、ロードおよび実行を含むJavaのプログラム実行フローに関連する知識を、2分を考えると?]

次に、重大な期間を入力します(@¯ー¯@)

独特のHello World

public class Main {

    private static String word = "Hello World!";

    public static void main(String[] args) {
        new Main().say();
    }

    private void say() {
        System.out.println(word);
    }
}

コード全体の実行は、3つの段階に分けることができます。

  • コードのコンパイル
  • クラスローダ
  • クラスの実行

コードのコンパイル

役割は、私たちがMain.classファイルにMain.javaファイルを記述したコードをコンパイルすることで、.classファイルもここでバイトコードファイルと呼ばれ、火星の山を開き、[とにかく]ここでは、読み込まれません我々はのjavac JDKツールが提供されてツールを使用して、原料の生産プロセスとしてJVMプロセスをコンパイルすることができます。
プロセスは、実質的に次のように

  • 字句解析では、文字が転送プロセストークンセットのソースになろうとしています。方言の記述は、当社の実際のプログラミングである下では、このようなキーワード、変数名、リテラル、演算子として、最小単位は単一の文字であるが、実際にプログラミング過程で、最小単位のマークがあり、そのため、一見、トークンになることができますまだ多少(>﹏<)、このような我々のINT整数プログラミングのような、それは私は、N、3つの文字T、およびプロセスでは、コンパイルトークンではない、すなわち、3つの文字であり、例えば、盲目スプリット。

このプロセスは、実際には、完全にシールドされ、私たちのためであるが、実際にそれが現代の古典的なコンパイラの理論である
ルーチンが、また、準備にコンパイル字句解析をお返しします]

  • 構文解析トークンは、字句解析によって設定された取得、次のステップは、抽象構文木を構築することである、抽象構文木が実際に構文木の各ノード方法を表すために使用されるプログラムコードの構文を記述した木構造であると呼ばれます全ては、バッグ、タイプ、修飾子、オペレータなど、プログラムコードに文法的構造を表します。

私たちの目には、Main.javaはすでに明確に最後に書かれているのか理解が、JVMのために無知探すことを余儀なくされているので、それはもはや、ソースファイルに対して、この手順の後に構文木に組み込まする必要はありません操作、およびその後の操作は、抽象構文木の上に構築されています

  • シンボルテーブルを充填、シンボルテーブルは、テーブルや記号からなるシンボリックアドレス情報の集合であり、このテーブルは、対象となるコード生成フェーズは、シンボル名が割り当てに取り組むコンパイルの異なる段階で使用される、シンボルテーブルでありますアドレス割り当ての基礎。

  • 意味解析は、それはパースに来るが、それが正しいと適切であるかどうかを構文木は、木の構文木を構築する際に、意味解析フェーズはまた、セマンティック検出フェーズがトップ、言うことができる、それが意味解析によって行われ、意味解析がでマークされます検査データ及び制御フロー解析および二段階の検査は、生成されたチェック情報バイトコードの最後のステップを開始します。

  • バイトコード生成、コンパイルプロセスのjavacバイトコード生成フェーズの最終段階は、バイトコードに以前に生成された情報のそれぞれを変換するだけの単純なステップではない、その後ディスクにも数が少ないですそして、このような当社独自のオーバーロードされたコンストラクタとして、コード変換作業を追加します。

コンパイルここで終了し、その後、誰が行うJVM仮想マシンにこれらの物質を輸送するために起こっていますか?今回は、クラスをロードするプロセスをご覧ください。

クラスローダ

クラスローダは、単にクラスローダのバイトコードファイルがコンパイルされている] [Main.classは、仮想マシンにロードされた
ので、当然、我々は最初の4つのタイプのローダーを導入しなければなりません、

ローダーの4種類についてのトーク

あなたは後ろにHello Worldの原則を知りません

上の図から分かるように、第四は、私たち自身の実現によりある一方で、クラスローダは、4つのカテゴリに分けることができ、その後、我々は、メインプログラムで起動JVMクラスのロード処理によって提供される他の3人は何を果たしましたその中で役割?

首先说说启动类加载器 Bootstrap ClassLoader ,启动类加载器的作用主要是加载 %JAVA_HOME%\jre\lib\rt.jar 类库,将其加载到虚拟机内存中,那么rt.jar类库到底有什么作用呢?rt.jar下包含了Java的基础类库,也就是Java doc里面看到的所有的类的class文件,感兴趣的朋友可以自己打开目录看下。

其次是扩展类加载器 Extension ClassLoader ,扩展类加载器的作用主要是负责加载JAVA_HOME\jre\lib\ext目录下的所有类库,主要是载入扩展包。

再者是系统类加载器 Application ClassLoader, 也称之为应用程序类加载器,负责加载用户类路径(也就是我们配置的CLASSPATH)上所指定的类库,是应用程序中默认的类加载。

看完以上三个类加载器的简单描述过程,是不是有种终于知道了我们配置的jdk环境的最终作用了吧,是的,就是让类加载器识别到后加载各种类库。

那么问题来了?是哪个类加载器加载了我们的Hello World程序呢?是的,就是应用程序中默认的类加载器 Application ClassLoader。

知道了类加载器后,那接下来总要了解下类加载器怎么加载的吧?

说说类加载的过程

あなたは後ろにHello Worldの原則を知りません

网上找了张图片,简单明了。虽说是简单明了,不过确实异常重要的,因为是面试热点(✿◡‿◡)

加载

其实就是上文说到的系统类加载器 Application ClassLoader将编译后的Main.class文件加载到内存中。

【思考】抛出个问题,所谓的加载到内存中,我们都知道JVM把内存分成了几大模块,那么请问是加载到哪个模块中?热点面试题,答案见文末

链接

链接中包含了三部曲,总的作用就是负责将Main.class的二进制数据合并到JRE中。

关于三部曲,其实很好理解;

首先是验证阶段,类加载器将二进制字节流加载到虚拟机中,肯定是需要进行验证的,避免危害虚拟机自身安全,而这也是验证阶段存在的价值;

接下来是准备阶段,准备阶段是正式为类变量分配内存并且设置类变量默认值的地方,比如上面HelloWorld程序中的

private static String word = "Hello World!";

注意我描述的第一个是类变量,也就是static所描述的变量,其次是默认值,也就是上面的word的默认值null,如果是数字则为0。

最后是解析阶段,解析阶段的作用主要是将常量池内的符号引用替换为直接引用的过程,解析阶段其实有点难理解,至少是比上面的两个阶段要难理解的,我这里尽量直白点;

所谓的符号引用指的是包含了类的信息、方法名、方法参数等信息的字符串,而当第一次运行时,JVM会根据这行字符串去检索到对应的方法入口,而为了下次不用再做同样的检索,在第一次运行的时候就会将符号引用替换成直接引用,这样后面就可以省去一定的消耗了;这里的直接引用其实就是指偏移量,虚拟机可以通过偏移量直接找到方法入口,不再需要做检索了。

初始化
终于来到初始化阶段了,上面我们有说到word默认值是null,是系统赋的默认值,而在初始化阶段,则是根据我们人为的初始化类变量和其他资源,比如上面的word则被我初始化成了"Hello World!"。

类执行

上面说到Main.class被加载到了Java虚拟机内存中,那么接下来便是执行的过程了。那么由谁来执行这一过程呢?

あなたは後ろにHello Worldの原則を知りません

实际上,一个Java虚拟机在运行的时候可以划分为三个子系统:

  • 类加载子系统
  • 执行引擎子系统
  • 垃圾收集子系统

これは、実行エンジン・サブシステムは、プロセスのこの部分を実装するための責任があり、クラスローダサブシステムの図は、上記の話されている、非常に明確で明確であるか、それのようなものでしょうか?

実際には非常に簡単、実行エンジンは、どのような[マシンコードにバイトコードに変換されますか?私はまだ変換しています。<(ˉ^ˉ)>、JVMバイトコードが識別された言語コードは、最後のバイトは、オペレーティングシステムに認識言語ですしてください]

オペレーティングシステムは、実際にJavaのを学ぶために多くのことを呼び出すことができるか、人々はJITの聞いたことがあるけど、まさにそれがあなたである理由は、具体的に知りませんでした。

ここでは、最後に(ラインでバイトラインを説明した翻訳作業を使用すると、JIT(ジャストインタイム)タイムコンパイラ(全体のホットコードコンパイラ)とJavaバイトコードインタプリタであるマシンコードにバイトコードを説明コード)が完了します。
次のワークフローにここでJITコンパイラ:

JVMバイトコード - >機械独立最適化 - >中間コード - >機種依存最適化 - >中間コード - >中間コード - - >ターゲットマシンコード生成 - >ターゲットマシンコード>割当レジスタ

最後に、実行エンジンは、メイン()このエントリの方法、および前記バイトコード命令の実行を検索します。

[考察]疑問ローディング段階が完了した後、仮想マシン内の記憶フォーマットその方式エリア、java.lang.Classクラスのインスタンス化されたオブジェクトの、メモリに応じて仮想マシンMain.classバイナリバイトストリームデータのこれらの種類の外部インタフェースアクセス方法のプログラム領域として、オブジェクト・クラスのjava.lang.Classインスタンスは、プロセス領域に格納された後。

おすすめ

転載: blog.51cto.com/14295088/2415840