導航:首頁 > 源碼編譯 > 編譯和執行過程

編譯和執行過程

發布時間:2023-02-08 17:22:16

❶ 誰能簡單闡述下java編譯執行的過程

Java虛擬機(JVM)是可運行Java代碼的假想計算機。

只要根據JVM規格描述將解釋器移植到特定的計算機上,就能保證經過編譯的任何Java代碼能夠在該系統上運行。

本文首先簡要介紹從Java文件的編譯到最終執行的過程,隨後對JVM規格描述作一說明。

一.Java源文件的編譯、下載、解釋和執行

Java應用程序的開發周期包括編譯、下載、解釋和執行幾個部分。

Java編譯程序將Java源程序翻譯為JVM可執行代碼?位元組碼。

這一編譯過程同C/C++的編譯有些不同。

當C編譯器編譯生成一個對象的代碼時,該代碼是為在某一特定硬體平台運行而產生的。

因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉換為特定的內存偏移量,以保證程序運行。

Java編譯器卻不將對變數和方法的引用編譯為數值引用,也不確定程序執行過程中的內存布局,而是將這些符號引用信息保留在位元組碼中,由解釋器在運行過程中創立內存布局,然後再通過查表來確定一個方法所在的地址。

這樣就有效的保證了Java的可移植性和安全性。

運行JVM位元組碼的工作是由解釋器來完成的。

解釋執行過程分三部進行:代碼的裝入、代碼的校驗和代碼的執行。

裝入代碼的工作由"類裝載器"(classloader)完成。

類裝載器負責裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調用的類。

當類裝載器裝入一個類時,該類被放在自己的名字空間中。

除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。

在本台計算機上的所有類都在同一地址空間內,而所有從外部引進的類,都有一個自己獨立的名字空間。

這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響。

當裝入了運行程序需要的所有類後,解釋器便可確定整個可執行程序的內存布局。

解釋器為符號引用同特定的地址空間建立對應關系及查詢表。

通過在這一階段確定代碼的內存布局,Java很好地解決了由超類改變而使子類崩潰的問題,同時也防止了代碼對地址的非法訪問。

隨後,被裝入的代碼由位元組碼校驗器進行檢查。

校驗器可發現操作數棧溢出,非法數據類型轉化等多種錯誤。

通過校驗後,代碼便開始執行了。

Java位元組碼的執行有兩種方式:

1.即時編譯方式:解釋器先將位元組碼編譯成機器碼,然後再執行該機器碼。

2.解釋執行方式:解釋器通過每次解釋並執行一小段代碼來完成Java位元組碼程序的所有操作。

通常採用的是第二種方法。

由於JVM規格描述具有足夠的靈活性,這使得將位元組碼翻譯為機器代碼的工作

具有較高的效率。

對於那些對運行速度要求較高的應用程序,解釋器可將Java位元組碼即時編譯為機器碼,從而很好地保證了Java代碼的可移植性和高性能。

二.JVM規格描述

JVM的設計目標是提供一個基於抽象規格描述的計算機模型,為解釋程序開發人員提很好的靈活性,同時也確保Java代碼可在符合該規范的任何系統上運行。

JVM對其實現的某些方面給出了具體的定義,特別是對Java可執行代碼,即位元組碼(Bytecode)的格式給出了明確的規格。

這一規格包括操作碼和操作數的語法和數值、標識符的數值表示方式、以及Java類文件中的Java對象、常量緩沖池在JVM的存儲映象。

這些定義為JVM解釋器開發人員提供了所需的信息和開發環境。

Java的設計者希望給開發人員以隨心所欲使用Java的自由。

JVM定義了控制Java代碼解釋執行和具體實現的五種規格,它們是:

JVM指令系統

JVM寄存器

JVM棧結構

JVM碎片回收堆

JVM存儲區

2.1JVM指令系統

JVM指令系統同其他計算機的指令系統極其相似。

Java指令也是由操作碼和操作數兩部分組成。

操作碼為8位二進制數,操作數進緊隨在操作碼的後面,其長度根據需要而不同。

操作碼用於指定一條指令操作的性質(在這里我們採用匯編符號的形式進行說明),如iload表示從存儲器中裝入一個整數,anewarray表示為一個新數組分配空間,iand表示兩個整數的"與",ret用於流程式控制制,表示從對某一方法的調用中返回。

當長度大於8位時,操作數被分為兩個以上位元組存放。

JVM採用了"bigendian"的編碼方式來處理這種情況,即高位bits存放在低位元組中。

這同Motorola及其他的RISCCPU採用的編碼方式是一致的,而與Intel採用的"littleendian"的編碼方式即低位bits存放在低位位元組的方法不同。

Java指令系統是以Java語言的實現為目的設計的,其中包含了用於調用方法和監視多先程系統的指令。

Java的8位操作碼的長度使得JVM最多有256種指令,目前已使用了160多種操作碼。

2.2JVM指令系統

所有的CPU均包含用於保存系統狀態和處理器所需信息的寄存器組。

如果虛擬機定義較多的寄存器,便可以從中得到更多的信息而不必對棧或內存進行訪問,這有利於提高運行速度。

然而,如果虛擬機中的寄存器比實際CPU的寄存器多,在實現虛擬機時就會佔用處理器大量的時間來用常規存儲器模擬寄存器,這反而會降低虛擬機的效率。

針對這種情況,JVM只設置了4個最為常用的寄存器。

它們是:

pc程序計數器

optop操作數棧頂指針

frame當前執行環境指針

vars指向當前執行環境中第一個局部變數的指針

所有寄存器均為32位。

pc用於記錄程序的執行。

optop,frame和vars用於記錄指向Java棧區的指針。

2.3JVM棧結構

作為基於棧結構的計算機,Java棧是JVM存儲信息的主要方法。

當JVM得到一個Java位元組碼應用程序後,便為該代碼中一個類的每一個方法創建一個棧框架,以保存該方法的狀態信息。

每個棧框架包括以下三類信息:

局部變數

執行環境

操作數棧

局部變數用於存儲一個類的方法中所用到的局部變數。

vars寄存器指向該變數表中的第一個局部變數。

執行環境用於保存解釋器對Java位元組碼進行解釋過程中所需的信息。

它們是:上次調用的方法、局部變數指針和操作數棧的棧頂和棧底指針。

執行環境是一個執行一個方法的控制中心。

例如:如果解釋器要執行iadd(整數加法),首先要從frame寄存器中找到當前執行環境,而後便從執行環境中找到操作數棧,從棧頂彈出兩個整數進行加法運算,最後將結果壓入棧頂。

操作數棧用於存儲運算所需操作數及運算的結果。

2.4JVM碎片回收堆

Java類的實例所需的存儲空間是在堆上分配的。

解釋器具體承擔為類實例分配空間的工作。

解釋器在為一個實例分配完存儲空間後,便開始記錄對該實例所佔用的內存區域的使用。

一旦對象使用完畢,便將其回收到堆中。

在Java語言中,除了new語句外沒有其他方法為一對象申請和釋放內存。

對內存進行釋放和回收的工作是由Java運行系統承擔的。

這允許Java運行系統的設計者自己決定碎片回收的方法。

在SUN公司開發的Java解釋器和HotJava環境中,碎片回收用後台線程的方式來執行。

這不但為運行系統提供了良好的性能,而且使程序設計人員擺脫了自己控制內存使用的風險。

2.5JVM存儲區

JVM有兩類存儲區:常量緩沖池和方法區。

常量緩沖池用於存儲類名稱、方法和欄位名稱以及串常量。

方法區則用於存儲Java方法的位元組碼。

對於這兩種存儲區域具體實現方式在JVM規格中沒有明確規定。

這使得Java應用程序的存儲布局必須在運行過程中確定,依賴於具體平台的實現方式。

JVM是為Java位元組碼定義的一種獨立於具體平台的規格描述,是Java平 *** 立性的基礎。

目前的JVM還存在一些限制和不足,有待於進一步的完善,但無論如何,JVM的思想是成功的。

對比分析:如果把Java原程序想像成我們的C++原程序,Java原程序編譯後生成的位元組碼就相當於C++原程序編譯後的80x86的機器碼(二進製程序文件),JVM虛擬機相當於80x86計算機系統,Java解釋器相當於80x86CPU。

在80x86CPU上運行的是機器碼,在Java解釋器上運行的是Java位元組碼。

Java解釋器相當於運行Java位元組碼的「CPU」,但該「CPU」不是通過硬體實現的,而是用軟體實現的。

Java解釋器實際上就是特定的平台下的一個應用程序。

只要實現了特定平台下的解釋器程序,Java位元組碼就能通過解釋器程序在該平台下運行,這是Java跨平台的根本。

當前,並不是在所有的平台下都有相應Java解釋器程序,這也是Java並不能在所有的平台下都能運行的原因,它只能在已實現了Java解釋器程序的平台下運行。

❷ C語言編譯執行的全過程是怎樣的

預處理階斷:這個就是那些#include啥的。
編譯階斷:把C語言的代碼轉成匯編語言代碼,比如 int a = 2; 它會生成mov a, 2;
匯編階斷:把匯編代碼轉換成機器碼,比如把mov a , 2 ; 轉成 cd07 (mov指令的機器碼中的一種機器碼)
鏈接階斷:製作成一個可執行文件,比如windows是PE的可執行文件,linux是elf的可執行文件,要製作成可以運行的程序。

❸ 編譯執行的具體介紹

使用編譯執行的程序一般稱為編譯程序,這是一類很重要的語言處理程序,它把高級語言(如FORTRAN、COBOL、Pascal、C等)源程序作為輸入,進行翻譯轉換,產生出機器語言的目標程序,然後再讓計算機去執行這個目標程序,得到計算結果。
編譯程序工作時,先分析,後綜合,從而得到目標程序。所謂分析,是指詞法分析和語法分析;所謂綜合是指代碼優化,存儲分配和代碼生成。為了完成這些分析綜合任務,編譯程序採用對源程序進行多次掃描的辦法,每次掃描集中完成一項或幾項任務,也有一項任務分散到幾次掃描去完成的。
下面舉一個四遍掃描的例子:第一遍掃描做詞法分析;第二遍掃描做語法分析;第三遍掃描做代碼優化和存儲分配;第四遍掃描做代碼生成。
值得一提的是,大多數的編譯程序直接產生機器語言的目標代碼,形成可執行的目標文件,但也有的編譯程序則先產生匯編語言一級的符號代碼文件,然後再調用匯編程序進行翻譯加工處理,最後產生可執行的機器語言目標文件。
在實際應用中,對於需要經常使用的有大量計算的大型題目,採用招待速度較快的編譯型的高級語言較好,雖然編譯過程本身較為復雜,但一旦形成目標文件,以後可多次使用。相反,對於小型題目或計算簡單不太費機時的題目,則多選用解釋型的會話式高級語言,如BASIC,這樣可以大大縮短編程及調試的時間

❹ 簡述JAVA程序的編輯編譯和運行過程

第一步(編譯): 創建完源文件之後,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然後引用,否則直接引用,這個有點象make。

如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報「cant find symbol」的錯誤。

第二步(運行):java類運行的過程大概可分為兩個過程:1、類的載入 2、類的執行。需要說明的是:JVM主要在程序第一次主動使用類的時候,才會去載入該類。也就是說,JVM並不是在一開始就把一個程序就所有的類都載入到內存中,而是到不得不用的時候才把它載入進來,而且只載入一次。

特別說明:java類中所有public和protected的實例方法都採用動態綁定機制,所有私有方法、靜態方法、構造器及初始化方法<clinit>都是採用靜態綁定機制。而使用動態綁定機制的時候會用到方法表,靜態綁定時並不會用到。

(4)編譯和執行過程擴展閱讀:

Java整個編譯以及運行的過程相當繁瑣,本文通過一個簡單的程序來簡單的說明整個流程。

Java代碼編譯:是由Java源碼編譯器來完成;

Java位元組碼的執行:是由JVM執行引擎來完成

Java程序從源文件創建到程序運行要經過兩大步驟:

1、源文件由編譯器編譯成位元組碼(ByteCode)

2、位元組碼由java虛擬機解釋運行。因為java程序既要編譯同時也要經過JVM的解釋運行,所以說Java被稱為半解釋語言( "semi-interpreted" language)。

❺ 請問一下當編譯軟體編譯代碼的時候是按照怎麼的順序執行的呀

編譯代碼首先是進行預處理,然後編譯,再鏈接,生成可執行程序

程序執行從main函數開始,程序順序執行。如有以下代碼:
#include <stdio.h>
#include <stdlib.h>

int add(int a, int b)
{
return a + b;
}

int sum(int a, int b)
{
return add(a, b);
}

int main(void)
{
int a = 1, b = 2, c = 3, d = 4;
int vaule1, vaule2;

vaule1 = sum(a, b);
vaule2 = add(c, d);

system("pause");
return 0;
}

則執行過程為
1、首先進入main函數
2、遇到第一個調用函數sum,則進入sum函數
3、在進入sum函數後,sum又調用了add函數,則進入add函數
4、add函數將 a+ b的值返回至sum函數;
5、sum函數返回至主函數,至此sum函數調用結束
6、在main函數中接下來開始進入調用函數add
7、add函數返回a+b的值至主函數,
8、程序執行結束

❻ 簡述將源程序編譯成可執行程序的過程

一個源程序到一個可執行程序的過程:預編譯、編譯、匯編、鏈接。其中,編譯是主要部分,其中又分為六個部分:詞法分析、語法分析、語義分析、中間代碼生成、目標代碼生成和優化。

預編譯:主要處理源代碼文件中的以「#」開頭的預編譯指令。處理規則如下:

1、刪除所有的#define,展開所有的宏定義。

2、處理所有的條件預編譯指令,如「#if」、「#endif」、「#ifdef」、「#elif」和「#else」。

3、處理「#include」預編譯指令,將文件內容替換到它的位置,這個過程是遞歸進行的,文件中包含其他文件。

4、刪除所有的注釋,「//」和「/**/」。

5、保留所有的#pragma 編譯器指令,編譯器需要用到他們,如:#pragma once 是為了防止有文件被重復引用。

6、添加行號和文件標識,便於編譯時編譯器產生調試用的行號信息,和編譯時產生編譯錯誤或警告是能夠顯示行號。

(6)編譯和執行過程擴展閱讀:

編譯過程中語法分析器只是完成了對表達式語法層面的分析,語義分析器則對表達式是否有意義進行判斷,其分析的語義是靜態語義——在編譯期能分期的語義,相對應的動態語義是在運行期才能確定的語義。

其中,靜態語義通常包括:聲明和類型的匹配,類型的轉換,那麼語義分析就會對這些方面進行檢查,例如將一個int型賦值給int*型時,語義分析程序會發現這個類型不匹配,編譯器就會報錯。

❼ C#程序的編譯和執行過程有什麼特點主要操作步驟是什麼

C#編譯過程中編譯多個源文件有兩個方面的特點:
1.把所有的源文件編譯成一個exe文件
2.把一些文件編譯成dll,一些編譯成exe 然後作為一個應用程序一起使用。

❽ 編譯執行和解釋執行的區別

一、主體不同

1、編譯執行:由編譯程序將目標代碼一次性編譯成目標程序,再由機器運行目標程序。

2、解釋執行:將源語言直接作為源程序輸入,解釋執行解釋一句後就提交計算機執行一句,並不形成目標程序。

二、優勢不同

1、編譯執行:相比解釋執行編譯執行效率高,佔用資源小,適合復雜程序

2、解釋執行:開發速度快,出現嚴重BUG的幾率小。


三、缺點不同

1、編譯執行:兼容性差,例如在windows平台上寫的編譯程序一般不可以在unix平台上運行。

2、解釋執行:解析需要時間,不生成目標程序而是一句一句的執行的方式會造成計算機資源的浪費,即執行效率低。


❾ java語言編譯和解釋執行的具體過程是怎樣的

Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這台虛擬的機器在任何平台上都提供給編譯程序一個的共同的介面。編譯程序只需要面向虛擬機,生成虛擬機能夠理解的代碼,然後由解釋器來將虛擬機代碼轉換為特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫做位元組碼(ByteCode),它不面向任何特定的處理器,只面向虛擬機。每一種平台的解釋器是不同的,但是實現的虛擬機是相同的。Java源程序經過編譯器編譯後變成位元組碼,位元組碼由虛擬機解釋執行,虛擬機將每一條要執行的位元組碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,然後在特定的機器上運行。

❿ 如何使用 Visual Studio.Net 編譯和執行 C# 程序,步驟是

閱讀全文

與編譯和執行過程相關的資料

熱點內容
pdf合並成一個pdf在線 瀏覽:383
柱加密區構造要求 瀏覽:514
地板木龍骨標准跟加密區別 瀏覽:150
解壓放鬆的好地方河南 瀏覽:965
搜狗怎麼移動到文件夾 瀏覽:617
文件自動選擇到文件夾 瀏覽:794
贈送的app怎麼在ipad下載 瀏覽:508
頸椎解壓後神經恢復 瀏覽:849
怎麼看app訂閱扣費 瀏覽:314
linux系統的負載均衡 瀏覽:419
遇到挫折解壓視頻 瀏覽:778
什麼指令看伺服器運行負載 瀏覽:84
因碩智能門鎖卡片是加密的么 瀏覽:336
為什麼會伺服器不可用 瀏覽:290
wow宏命令設置 瀏覽:264
解壓神器一張紙折疊魔術球 瀏覽:23
怎麼樣可以取消加密軟體oppo 瀏覽:580
屏幕共享源碼哪家比較不錯 瀏覽:665
vb中雙擊命令按鈕 瀏覽:208
伺服器做了磁碟陣列怎麼重裝 瀏覽:606