❶ 簡述java語言的執行過程
先編寫好.java的文件,這個成為源文件,在使用javac編譯源文件,得到.class文件(javac
Test.java),最後執行java命令得到結果(java
Test)。
❷ 麻煩解釋一下這個java程序的執行流程,詳細一點,謝謝!
類的實例化過程:
1。首先執行父類的靜態初始化塊、靜態屬性定義,執行順序與源代碼書寫順序相同。
2。然後執行子類的靜態初始化塊、靜態屬性定義,執行順序與源代碼書寫順序相同。
3。執行父類的普通初始化塊、普通屬性定義、構造函數,它們執行的順序為,先執行普通初始化塊、普通屬性定義,執行順序與源代碼書寫順序相同。然後再執行構造函數。
4。執行子類的普通初始化塊、普通屬性定義、構造函數,它們執行的順序為,先執行普通初始化塊、普通屬性定義,執行順序與源代碼書寫順序相同。然後再執行構造函數。
5。注意初始化時的方法重寫的情況。
6。以上執行的理解:當系統在第一次使用某個類時,將會載入並初始化它,在類的准備階段,系統將會為該類的類屬性分配內存空間,並指定默認默認值。初始化後,系統將在堆內存為這個類分配一塊內存空間。當創建第二個此類的對象時,因為它已經存在堆內存中,所以不再需要對這個類進行初始化。
❸ 你知道java的運行原理是什麼嗎
Java這一語言的執行過程也遵循這樣的過程:源代碼--->機器碼。 但是,從源代碼到機器碼之間,究竟經過什麼樣的過程,則是Java獨一無二的了。寬泛地講,Java源代碼(.java)經過java編譯器(javac.exe)編譯之後,並沒有直接轉化為機器碼,而是轉化成一種中間格式,成為位元組碼(.class),位元組碼再經過java虛擬機轉化成特定CPU架構的機器碼。也正是因為這一中間物,java才有所謂的跨平台。在windows平台上編譯好的位元組碼,到linux平台後,經過為linux而設計的Java虛擬機解釋後即可執行。跨平台這一特徵,是通過位元組碼和JVM來實現的。
因此,想搞清楚java程序到底是如何運行的,重點在於弄明白位元組碼是如何被轉化成跟CPU架構相關的機器碼然後被執行的。也就是要理解JVM到底是如何工作的。在了解JVM之前,我們再跳出來一下,先看看什麼是虛擬機。所謂虛擬機,我是這么理解的:用軟體的方式模擬出跟硬體類似的環境,比如說寄存器、存儲器等等。當然,所有最終的工作還是由原來的CPU來完成。比如說VirtualBox這個虛擬機產品,它其實就是一個應用程序,用某種編程語言編寫的應用程序。當運行這個應用程序時,它會要求操作系統給它獨立施展手腳的空間:給我一些內存,給我一定的CPU時間片,然後不用管我了。你可能會問,寄存器是硬體啊,它怎麼能劃分啊,難道是時間劃分?不是的,像內存這樣的硬體,可以給虛擬機一塊獨立的內存塊,但是寄存器之後的,則需要用「模擬模擬」的方式來模擬。OK,回到Java虛擬機。到底什麼是Java虛擬機,很難有一個十分明確的定義,狹窄一點說,它就是一個應用程序,大部分用C++編寫的。寬泛地說,它就是執行位元組碼的一整個環境。
❹ 簡述JAVA程序的編輯編譯和運行過程
第一步(編譯): 創建完源文件之後,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然後引用,否則直接引用,這個有點象make。
如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報「cant find symbol」的錯誤。
第二步(運行):java類運行的過程大概可分為兩個過程:1、類的載入 2、類的執行。需要說明的是:JVM主要在程序第一次主動使用類的時候,才會去載入該類。也就是說,JVM並不是在一開始就把一個程序就所有的類都載入到內存中,而是到不得不用的時候才把它載入進來,而且只載入一次。
特別說明:java類中所有public和protected的實例方法都採用動態綁定機制,所有私有方法、靜態方法、構造器及初始化方法<clinit>都是採用靜態綁定機制。而使用動態綁定機制的時候會用到方法表,靜態綁定時並不會用到。
(4)java程序的執行過程是擴展閱讀:
Java整個編譯以及運行的過程相當繁瑣,本文通過一個簡單的程序來簡單的說明整個流程。
Java代碼編譯:是由Java源碼編譯器來完成;
Java位元組碼的執行:是由JVM執行引擎來完成
Java程序從源文件創建到程序運行要經過兩大步驟:
1、源文件由編譯器編譯成位元組碼(ByteCode)
2、位元組碼由java虛擬機解釋運行。因為java程序既要編譯同時也要經過JVM的解釋運行,所以說Java被稱為半解釋語言( "semi-interpreted" language)。
❺ 簡述java應用程序的運行過程
java的運行在自身的虛擬機上(jvm),jvm通過loader(類載入器)載入.class文件(java的指令文件),jvm把class文件最終翻譯成系統指令執行.
❻ java程序的執行步驟
通過下面這個程序你可以清晰地看到執行過程,方括弧里的數字代表執行順序。
-------------------------------------------------------
public class BreakLoop{
static int s=0;
public static void main (String[] args)
{
for (int i=0;i<3;i++)
{
System.out.print("Pass"+i+":");
for(int j=0;j<100;j++)
{
if(j==15) break;
System.out.print(j+"["+(s++)+"]");
}
System.out.println();
}
System.out.println("Loops Complete.");
}
}
❼ 誰能簡單闡述下java編譯執行的過程
Java虛擬機(JVM)是可運行Java代碼的假想計算機。只要根據JVM規格描述將解釋器移植到特定的計算機上,就能保證經過編譯的任何Java代碼能夠在該系統上運行。本文首先簡要介紹從Java文件的編譯到最終執行的過程,隨後對JVM規格描述作一說明。
一.Java源文件的編譯、下載、解釋和執行
Java應用程序的開發周期包括編譯、下載、解釋和執行幾個部分。Java編譯程序將Java源程序翻譯為JVM可執行代碼?位元組碼。這一編譯過程同C/C++的編譯有些不同。當C編譯器編譯生成一個對象的代碼時,該代碼是為在某一特定硬體平台運行而產生的。因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉換為特定的內存偏移量,以保證程序運行。Java編譯器卻不將對變數和方法的引用編譯為數值引用,也不確定程序執行過程中的內存布局,而是將這些符號引用信息保留在位元組碼中,由解釋器在運行過程中創立內存布局,然後再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性。
運行JVM位元組碼的工作是由解釋器來完成的。解釋執行過程分三部進行:代碼的裝入、代碼的校驗和代碼的執行。裝入代碼的工作由"類裝載器"(class loader)完成。類裝載器負責裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調用的類。當類裝載器裝入一個類時,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。在本台計算機上的所有類都在同一地址空間內,而所有從外部引進的類,都有一個自己獨立的名字空間。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響。當裝入了運行程序需要的所有類後,解釋器便可確定整個可執行程序的內存布局。解釋器為符號引用同特定的地址空間建立對應關系及查詢表。通過在這一階段確定代碼的內存布局,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採用了"big endian"的編碼方式來處理這種情況,即高位bits存放在低位元組中。這同 Motorola及其他的RISC CPU採用的編碼方式是一致的,而與Intel採用的"little endian "的編碼方式即低位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解釋器和Hot Java環境中,碎片回收用後台線程的方式來執行。這不但為運行系統提供了良好的性能,而且使程序設計人員擺脫了自己控制內存使用的風險。
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解釋器程序的平台下運行。
❽ 簡述JAVA程序運行過程
1,如果java文件沒有package,就默認給文件加上"無名"package;
2,默認導入java.lang包,所以我們的java程序中可以使用Sting,Math,Integer等類,包括一些異常類;
3,如果生成的類沒有父類,則為這個類隱式加上父類:Object;因此,包括Object中的許多方法可以使用;
4,欄位的初始化;
二,我們所看的到的:
既然看的到,就先看程序運行結果:
public class JRun1 {
public JRun1() {
System.out.println(" 構造函數");
}
static
{
System.out.println("static{}");
}
{
System.out.println("{}");
}
public static void main(String[] args) {
System.out.println("main()");
}
}
運行結果:
static{}
main()
顯然,程序運行時,先運行:
static
{
System.out.println("static{}");
}
再調用main();
如果我們在類中建立一個對象:
public class JRun1 {
public JRun1() {
System.out.println(" 構造函數");
}
static
{
System.out.println("static{}");
}
{
System.out.println("{}");
}
public static void main(String[] args) {
System.out.println("main()");
new JRun1();
}
}
運行結果:
static{}
main()
{}
構造函數
從而,我們得出:
建立一個非主類對象,順序為:靜態初始化塊static{}-->初始化塊{}-->構造函數constructor;
那麼,牽涉到繼承,運行流程又如何?
看程序:
class JRun1Father{
JRun1Father(){
System.out.println("父類構造函數");
}
static{
System.out.println("父類靜態初始化塊");
}
{
System.out.println("父類初始化塊");
}
}
public class JRun1 extends JRun1Father{
public JRun1() {
System.out.println("子類構造函數");
}
static
{
System.out.println("子類靜態初始化塊");
}
{
System.out.println("子類初始化塊");
}
public static void main(String[] args) {
//System.out.println("主方法)");
new JRun1();
}
}
運行結果:
父類靜態初始化塊
子類靜態初始化塊
父類初始化塊
父類構造函數
子類初始化塊
子類構造函數
所以,牽涉到父類:父靜態-->子靜態-->父初始化及構造-->子初始化及構造;
注意:初始化塊和構造是接連運行的,不會父類子類交替.
❾ Java編譯運行過程
程序員所編寫的是以.java為後綴的文件,此文件操作系統不能正確識別,因此,首先要經過編譯,生成所謂的位元組碼文件(.class),而位元組碼文件需要JVM來提供運行環境的支持。
JVM是一個軟體,安裝在操作系統中,是建立在操作系統之上的,為位元組碼文件提供運行環境,效果如圖 – 1 所示。
圖- 1
Java官方提供了針對不同平台的JVM軟體,即:不同平台的JVM是不同的。但這些JVM遵循著相同的標准,即:只要是標準的.class文件,就可以在不同的JVM上運行,而且運行的效果相同。這樣,就實現了所謂的「一次編程到處使用」。效果如圖– 2所示:
圖- 2
Java程序遵循著先編譯、後執行的原則。首先,通過javac命令將JAVA源程序(.java文件)編譯為JAVA位元組碼(.class文件),而後,通過java命令啟動JVM,由JVM來載入.class文件並運行.class文件。效果如圖 – 3所示:
圖- 3
❿ java文件是怎麼執行的
首先:使用javac命令把.java文件編譯成.class文件(位元組碼文件)
然後:JVM(java虛擬機)裝載.class文件並翻譯成機器碼後運行java程序;
共同學習-----請參考:
我們手工執行java程序是這樣的:
1 在記事本中或者是UE的文本編輯器中,寫好源程序;
2 使用javac命令把源程序編譯成.class文件;
編譯後的.class(類位元組碼)文件中會包含以下內容:
ConstantPool:符號表;
FieldInfo:類中的成員變數信息;
MethodInfo:類中的方法描述;
Attribute:可選的附加節點。
FieldInfo節點包含成員變數的名稱,諸如public,private,static等的標志。ConstantValue屬性用來存儲靜態的不變的成員變數的值。Deprecated和Synthetic被用來標記一個成員變數是不被推薦的或由編譯器生成的。
3 有了.class文件,我們執行 java 解釋命令就可以運行java程序了。
現在我們主要討論一下,當執行 java這個命令後,會發生什麼事情呢?
首先,JVM裝載.class,也就是類裝載器裝載類位元組碼。一個類裝載器本身也是一個java類,所以,類裝載器自身也需要被另外一個類裝載器裝載,這就出現了類似先有蛋,還是先有雞的問題。但JAVA中的類裝載器的這個問題卻很容易解決。JAVA的虛擬機(JVM)中內嵌了一個稱為Bootstrap類裝載器,它是用特定於操作系統的本地代碼實現的,屬於JAVA虛擬機的內核,Bootstrap類不用專門的類裝載器去進行裝載。Bootstrap類負責載入JAVA核心包中的類(即rt.jar文件中的類),這些類的Class.getClassLoader()方法返回值為null,即表示是Bootstrap類裝載器。JAVA核心包中有另外兩個類裝載器:ExtClassLoader和AppClassLoader,它們都是用JAVA語言編寫的JAVA類,其中ExtClassLoader類裝載負責載入存放在<JAVA_HOME>/jre/lib/ext目錄下的jar包中的類,AppClassLoader負責載入應用程序的啟動執行類,即當使用java命令去啟動執行一個類時,JAVA虛擬機使用AppClassLoader載入這個類。在編譯和運行JAVA程序時,都會通過ExtClassLoader類裝載器去<JAVA_HOME>/jre/lib/ext目錄下的JAR包中搜索要載入的類,所以,如果將包含例如Servlet API的jar包或者是javamail.jar包復制到該目錄下,在編譯Servlet或JavaMail程序時,就不必在CLASSPATH環境變數中增加包含Servlet API的jar包或者是javamail.jar包文件。
以上,就是一個JAVA程序執行的大致過程。