JavaRush /Java Blog /Random-TL /Pag-compile at pag-execute ng mga Java application sa ila...
Павел Голов
Antas
Москва

Pag-compile at pag-execute ng mga Java application sa ilalim ng hood

Nai-publish sa grupo

Nilalaman:

  1. Panimula
  2. Pag-compile sa bytecode
  3. Halimbawa ng compilation at execution ng program
  4. Pagpapatupad ng isang programa sa isang virtual machine
  5. Just-in-time (JIT) compilation
  6. Konklusyon
Pag-compile at pag-execute ng mga application ng Java sa ilalim ng hood - 1

1. Panimula

Kamusta kayong lahat! Ngayon gusto kong magbahagi ng kaalaman tungkol sa kung ano ang nangyayari sa ilalim ng hood ng JVM (Java Virtual Machine) pagkatapos naming magpatakbo ng isang Java written application. Sa ngayon, may mga usong development environment na makakatulong sa iyong maiwasan ang pag-iisip tungkol sa internals ng JVM, pag-compile at pag-execute ng Java code, na maaaring maging sanhi ng mga bagong developer na makaligtaan ang mahahalagang aspetong ito. Kasabay nito, ang mga tanong tungkol sa paksang ito ay madalas na tinatanong sa mga panayam, kaya naman nagpasya akong magsulat ng isang artikulo.

2. Compilation sa bytecode

Pag-compile at pag-execute ng mga Java application sa ilalim ng hood - 2
Magsimula tayo sa teorya. Kapag sumulat kami ng anumang application, lumikha kami ng isang file na may extension .javaat ilagay ang code dito sa Java programming language. Ang nasabing file na naglalaman ng nababasang code ng tao ay tinatawag na source code file . Kapag handa na ang source code file, kailangan mo itong isagawa! Ngunit sa yugto ito ay naglalaman ng impormasyon na naiintindihan lamang ng mga tao. Ang Java ay isang multi-platform na programming language. Nangangahulugan ito na ang mga program na nakasulat sa Java ay maaaring isagawa sa anumang platform na may naka-install na dedikadong Java runtime system. Ang sistemang ito ay tinatawag na Java Virtual Machine (JVM). Upang maisalin ang isang programa mula sa source code sa code na mauunawaan ng JVM, kailangan mong i-compile ito. Ang code na nauunawaan ng JVM ay tinatawag na bytecode at naglalaman ng isang set ng mga tagubilin na pagkatapos ay isasagawa ng virtual machine. Upang i-compile ang source code sa bytecode, mayroong isang compiler javacna kasama sa JDK (Java Development Kit). Bilang input, tumatanggap ang compiler ng file na may extension .java, na naglalaman ng source code ng program, at bilang output, gumagawa ito ng file na may extension .class, na naglalaman ng bytecode na kinakailangan para sa program na maipatupad ng virtual machine. Sa sandaling ang isang programa ay naipon sa bytecode, maaari itong maisagawa gamit ang isang virtual machine.

3. Halimbawa ng compilation at execution ng program

Ipagpalagay na mayroon kaming isang simpleng programa, na nakapaloob sa isang file Calculator.java, na tumatagal ng 2 numeric command line argument at nagpi-print ng resulta ng kanilang karagdagan:
class Calculator {
    public static void main(String[] args){
        int a = Integer.valueOf(args[0]);
        int b = Integer.valueOf(args[1]);

        System.out.println(a + b);
    }
}
Upang ma-compile ang program na ito sa bytecode, gagamitin namin ang compiler javacsa command line:
javac Calculator.java
Pagkatapos ng compilation, nakatanggap kami ng file na may bytecode bilang isang output Calculator.class, na maaari naming isagawa gamit ang java machine na naka-install sa aming computer gamit ang java command sa command line:
java Calculator 1 2
Tandaan na pagkatapos ng pangalan ng file, 2 argumento ng command line ang tinukoy - mga numero 1 at 2. Pagkatapos isagawa ang programa, ipapakita ang numero 3 sa command line. Sa halimbawa sa itaas, mayroon kaming isang simpleng klase na nabubuhay sa sarili nitong . Ngunit paano kung ang klase ay nasa ilang pakete? Gayahin natin ang sumusunod na sitwasyon: lumikha ng mga direktoryo src/ru/javarushat ilagay ang aming klase doon. Ngayon ay ganito ang hitsura nito (idinagdag namin ang pangalan ng package sa simula ng file):
package ru.javarush;

class Calculator {
    public static void main(String[] args){
        int a = Integer.valueOf(args[0]);
        int b = Integer.valueOf(args[1]);

        System.out.println(a + b);
    }
}
Mag-compile tayo ng ganitong klase gamit ang sumusunod na command:
javac -d bin src/ru/javarush/Calculator.java
Sa halimbawang ito, gumamit kami ng karagdagang opsyon sa compiler -d binna naglalagay ng mga pinagsama-samang file sa isang direktoryo binna may istrakturang katulad ng direktoryo src, ngunit ang direktoryo binay dapat na malikha nang maaga. Ginagamit ang diskarteng ito upang maiwasan ang pagkalito ng mga source code file sa mga bytecode file. Bago patakbuhin ang pinagsama-samang programa, sulit na ipaliwanag ang konsepto classpath. Classpathay ang landas na nauugnay kung saan ang virtual machine ay maghahanap ng mga pakete at pinagsama-samang mga klase. Ibig sabihin, sa ganitong paraan sasabihin namin sa virtual machine kung aling mga direktoryo sa file system ang ugat ng hierarchy ng Java package. Classpathmaaaring tukuyin kapag sinimulan ang programa gamit ang bandila -classpath. Inilunsad namin ang programa gamit ang command:
java -classpath ./bin ru.javarush.Calculator 1 2
Sa halimbawang ito, kailangan namin ang buong pangalan ng klase, kasama ang pangalan ng package kung saan ito nakatira. Ang huling file tree ay ganito ang hitsura:
├── src
│     └── ru
│          └── javarush
│                  └── Calculator.java
└── bin
      └── ru
           └── javarush
                   └── Calculator.class

4. Pagpapatupad ng programa sa pamamagitan ng isang virtual machine

Kaya, inilunsad namin ang nakasulat na programa. Ngunit ano ang mangyayari kapag ang isang pinagsama-samang programa ay inilunsad ng isang virtual machine? Una, alamin natin kung ano ang ibig sabihin ng mga konsepto ng compilation at code interpretation. Ang compilation ay ang pagsasalin ng isang program na nakasulat sa isang mataas na antas ng source language sa isang katumbas na programa sa isang mababang antas na wika na katulad ng machine code. Ang interpretasyon ay isang operator-by-statement (command-by-line, line-by-line) na pagsusuri, pagproseso at agarang pagpapatupad ng source program o kahilingan (kumpara sa compilation, kung saan isinasalin ang program nang hindi ito isinasagawa). Ang wikang Java ay may parehong compiler ( javac) at isang interpreter, na isang virtual machine na nagko-convert ng bytecode sa machine code line sa pamamagitan ng linya at agad itong ipapatupad. Kaya, kapag nagpatakbo kami ng isang pinagsama-samang programa, ang virtual machine ay nagsisimulang bigyang-kahulugan ito, iyon ay, line-by-line na conversion ng bytecode sa machine code, pati na rin ang pagpapatupad nito. Sa kasamaang palad, ang purong bytecode na interpretasyon ay medyo mahabang proseso at ginagawang mabagal ang java kumpara sa mga kakumpitensya nito. Upang maiwasan ito, isang mekanismo ang ipinakilala upang mapabilis ang interpretasyon ng bytecode ng virtual machine. Ang mekanismong ito ay tinatawag na Just-in-time compilation (JITC).

5. Just-in-time (JIT) compilation

Sa madaling salita, ang mekanismo ng Just-In-Time compilation ay ito: kung may mga bahagi ng code sa program na naisakatuparan nang maraming beses, maaari silang i-compile nang isang beses sa machine code upang mapabilis ang kanilang pagpapatupad sa hinaharap. Matapos i-compile ang naturang bahagi ng programa sa machine code, sa bawat kasunod na tawag sa bahaging ito ng program, ang virtual machine ay agad na isasagawa ang pinagsama-samang machine code sa halip na bigyang-kahulugan ito, na natural na magpapabilis sa pagpapatupad ng programa. Ang pagpapabilis ng programa ay nakakamit sa pamamagitan ng pagtaas ng pagkonsumo ng memorya (kailangan nating iimbak ang pinagsama-samang machine code sa isang lugar!) At sa pamamagitan ng pagtaas ng oras na ginugol sa compilation sa panahon ng pagpapatupad ng programa. Ang JIT compilation ay medyo kumplikadong mekanismo, kaya lampasan natin ang tuktok. Mayroong 4 na antas ng JIT compilation ng bytecode sa machine code. Kung mas mataas ang antas ng compilation, mas kumplikado ito, ngunit sa parehong oras ang pagpapatupad ng naturang seksyon ay magiging mas mabilis kaysa sa isang seksyon na may mas mababang antas. JIT - Ang compiler ang nagpapasya kung anong antas ng compilation ang itatakda para sa bawat fragment ng program batay sa kung gaano kadalas naisasagawa ang fragment na iyon. Sa ilalim ng hood, ang JVM ay gumagamit ng 2 JIT compiler - C1 at C2. Ang C1 compiler ay tinatawag ding client compiler at may kakayahang mag-compile ng code hanggang sa ika-3 antas lamang. Ang C2 compiler ay responsable para sa ika-4, pinaka-kumplikado at pinakamabilis na antas ng compilation.
Pag-compile at pag-execute ng mga Java application sa ilalim ng hood - 3
Mula sa itaas, maaari nating tapusin na para sa mga simpleng aplikasyon ng kliyente, mas kumikita ang paggamit ng C1 compiler, dahil sa kasong ito mahalaga para sa amin kung gaano kabilis magsimula ang application. Ang mga server-side, matagal nang nabubuhay na mga application ay maaaring tumagal nang mas matagal upang magsimula, ngunit sa hinaharap dapat silang gumana at gumanap nang mabilis ang kanilang function - dito ang C2 compiler ay angkop para sa amin. Kapag nagpapatakbo ng Java program sa x32 na bersyon ng JVM, maaari naming manu-manong tukuyin kung aling mode ang gusto naming gamitin gamit ang -clientand flags -server. Kapag tinukoy ang flag na ito, -clienthindi magsasagawa ang JVM ng mga kumplikadong bytecode optimization, na magpapabilis sa oras ng pagsisimula ng application at bawasan ang dami ng memory na natupok. Kapag tinukoy ang flag, -serverang application ay magtatagal upang magsimula dahil sa kumplikadong bytecode optimizations at gagamit ng mas maraming memory upang mag-imbak ng machine code, ngunit ang programa ay tatakbo nang mas mabilis sa hinaharap. Sa x64 na bersyon ng JVM, -clientbinabalewala ang flag at ginagamit ang configuration ng server ng application bilang default.

6. Konklusyon

Ito ay nagtatapos sa aking maikling pangkalahatang-ideya kung paano gumagana ang pag-compile at pagpapatupad ng isang Java application. Mga pangunahing punto:
  1. Kino-convert ng javac compiler ang source code ng program sa bytecode na maaaring isagawa sa anumang platform kung saan naka-install ang Java virtual machine;
  2. Pagkatapos ng compilation, binibigyang-kahulugan ng JVM ang resultang bytecode;
  3. Upang pabilisin ang mga aplikasyon ng Java, ang JVM ay gumagamit ng Just-In-Time na mekanismo ng compilation na nagko-convert sa pinakamadalas na isinasagawang mga seksyon ng isang programa sa machine code at iniimbak ang mga ito sa memorya.
Umaasa ako na ang artikulong ito ay nakatulong sa iyo na magkaroon ng mas malalim na pag-unawa sa kung paano gumagana ang aming paboritong programming language. Salamat sa pagbabasa, criticism is welcome!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION