首頁  >  文章  >  Java  >  終端機中如何運行一個java程式?解析其運作機制及其運作原理

終端機中如何運行一個java程式?解析其運作機制及其運作原理

php是最好的语言
php是最好的语言原創
2018-08-01 15:30:464664瀏覽

想必稍微有點了解的人都應該知道,java是一門入門容易,想要精通卻很難的一門語言,因為其知識量很多,想要全部掌握並非一朝一夕能夠實現的,本篇文章討論的是Java程式的運作機制及其運作過程,大家應該都很期待吧,文章有些是我蒐集的,可能排版有些雜亂,多多諒解,我會持續更新更多優質的文章分享給大家的,我也會一直秉持著助人為樂的宗旨。 apache php mysql

java兩種核心機制:java虛擬機器跟垃圾回收機制。目前這兒主要講的是jvm運行java程式。

(一)終端機中如何執行一個java程式(這個是我在mac下運行的,windows下原理是一樣的,大同小異)

做這個事情的前提下,一定是jdk已經安裝好了且沒任何問題。

首先要想運行java類,應該先有個java類

1.創建個名為java的資料夾,在資料夾下面創建個以.java結尾的文件(我是用sublime編輯的,其他編輯器也行),這兒以HelloWorld為例

終端機中如何運行一個java程式?解析其運作機制及其運作原理

#2.透過指令編譯檔案

192:libexec huayu$ javac /Users/huayu/Desktop/java/HelloWord.java

執行完指令後你會發現在java資料夾下多出來一個以.class結尾的檔案

終端機中如何運行一個java程式?解析其運作機制及其運作原理

#3.執行編譯好的類別檔案(注意一定要在類別檔案的位置下去執行指令,要不然它就會報找不到類別的錯誤),你將會在終端機中看到以下輸出

192:java huayu$ java HelloWord
HelloWord

到此處,恭喜你!你已經在終端機中編譯並運行了第一個java程式。

其實小編知道上面例子中的字母敲錯啦,請大家裝作沒看見放小編一馬,別吐槽我了,嘻嘻

#(二)jvm的運作原理

以上例子的目的不是為了讓我們學會怎麼在終端機中運行java程序,而是希望大家知道在以上過程中都進行了哪些操作。

javac程式是一個Java編譯器。它將檔案HelloWorld.java編譯成HelloWorld.class文件,並傳送到java虛擬機器。虛擬機器執行編譯器放在class檔案中的字節碼。

(1)JVM 載入class 檔案的原理機制

終端機中如何運行一個java程式?解析其運作機制及其運作原理

#JVM 中類別的裝載是由類別載入器(ClassLoader)和它的子類別來實作的,Java 中的類別載入器是重要的Java 執行時間系統元件,它負責在執行時間尋找和裝入類別檔案中的類別。
由於 Java 的跨平台性,經過編譯的 Java 原始程式並不是一個可執行程序,而是一個或多個類別檔案。當 Java 程式需要使用某個類別時,JVM 會確保這個類別已經被載入、連接(驗證、準備和解析)和 初始化。

類別的載入是指把類別的.class 檔案中的資料讀入到記憶體中,通常是建立一個位元組數組讀 入.class 文件,然後產生與所載入類別對應的 Class 物件。載入完成後,Class 物件還不完整,所以此時的類別還不可用。當類別被載入後就進入連接階段,此階段包括驗證、準備(為靜態變數分 配記憶體並設定預設的初始值)和解析(將符號引用替換為直接引用)三個步驟。最後 JVM 對類別 進行初始化,包括:1)如果類別存在直接的父類別且這個類別還沒有被初始化,那麼就先初始化父類別; 2)如果類別中存在初始化語句,就依次執行這些初始化語句。

類別的載入是由類別載入器完成的,類別載入器包括:根載入器(BootStrap)、擴充功能載入器(Extension)、 系統載入器(System)和使用者自訂類別載入器( java.lang.ClassLoader 的子類別)。從 Java 2(JDK 1.2)開始,類別載入過程採取了父親委託機制(PDM)。 PDM 更好的保證了 Java 平台的安全性, 在該機制中,JVM 自帶的 Bootstrap 是根加載器,其他的加載器都有且僅有一個父類加載器。類別的載入首先請求父類別載入器加載,父類別載入器無能為力時才由其子類別載入器自行載入。 JVM 不會向 Java 程式提供對 Bootstrap 的引用。

下面是關於幾個類別載入器的說明:

Bootstrap:一般用本地程式碼實現,負責載入JVM 基礎核心類別庫(rt.jar);
Extension:從java.ext.dirs 系統屬性所指定的目錄中載入類別庫,它的父載入器是Bootstrap;

System:又叫應用程式類別載入器,其父類別是Extension。它是應用最廣泛的類別載入器。它從環境變數 classpath 或系統屬性 java.class.path 所指定的目錄中記載類,是使用者自訂載入 器的預設父載入器。

(2)java的「一次編譯到處執行」又是怎麼做到的呢?

終端機中如何運行一個java程式?解析其運作機制及其運作原理

虛擬機器可以理解成一個以字節碼為機器指令的CPU。

對於不同的運行平台,有不同的虛擬機器。

java虛擬機機制屏蔽了底層運行平台的差別,實現了「一次編譯,隨處運行」。

(三)垃圾回收機制(GC)

GC 是什麼?為什麼要有GC?

GC 是垃圾收集的意思,內存處理是程式設計人員容易出現問題的地方,忘記或錯誤的記憶體回收會導致程式或系統的不穩定甚至崩潰,Java 提供的GC 功能可以自動監測物件是否超過作用域從而達到自動回收記憶體的目的,Java 語言沒有提供釋放已分配記憶體的顯示操作方法。 Java 程 序員不用擔心記憶體管理,因為垃圾收集器會自動進行管理。若要要求垃圾收集,可以呼叫下面的 方法之一:System.gc() 或 Runtime.getRuntime().gc() ,但 JVM 可以屏蔽掉顯示的垃圾回收呼叫。垃圾回收可以有效的防止記憶體洩露,有效的使用可以使用的記憶體。垃圾回收器通常是作為一個單獨的低優先級的線程運行,不可預測的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個物件或所有物件進行垃圾回收(程式設計師無法精確把控回收時間,呼叫System.gc() 或Runtime.getRuntime().gc() 這兩個方法,就相當於通知GC來收,催了一下而已,什麼時候來收還不一定)。

在 Java 誕生初期,垃圾回收是 Java 最大的亮點之一,因為伺服器端的程式設計需要有效的防止記憶體 洩漏問題,然而時過境遷,如今 Java 的垃圾回收機制已經成為被詬病的東西。行動智慧終端用 戶通常覺得 iOS 的系統比 Android 系統有更好的使用者體驗,其中一個深層的原因就在於 Android 系統中垃圾回收的不可預測性。

補充:垃圾回收機制有很多種,包括:分代複製垃圾回收、標記垃圾回收、增量垃圾回收等方 式。標準的 Java 進程既有堆疊又有堆。棧保存了原始型局部變量,堆保存了要建立的物件。 Java 平台對堆記憶體回收和再利用的基本演算法稱為標記和清除,但是 Java 對其進行了改進,採用「分 代式垃圾收集」。這種方法會跟Java 物件的生命週期將堆記憶體劃分為不同的區域,在垃圾收集過程中,可能會將物件移動到不同區域:

- 伊甸園(Eden):這是物件最初誕生的區域,對大多數物件來說,這裡是它們唯一存在

過的區域。
- 倖存者樂園(Survivor):從伊甸園倖存下來的物件會被移到這裡。
- 終身頤養園(Tenured):這是足夠老的倖存對象的歸宿。年輕代收集(Minor-GC)過程是不 會觸及這個地方的。當年輕代收集無法把物件放進終身頤養園時,就會觸發一次完全收集 (Major-GC),這裡可能還會牽扯到壓縮,以便為大物件騰出足夠的空間。

與垃圾回收相關的JVM 參數:

  • #-Xms / -Xmx — 堆的初始大小/ 堆的最大大小

  • -Xmn — 堆中年輕代的大小

  • -XX:-DisableExplicitGC — 讓System.gc()不產生任何作用
  • -XX: PrintGCDetails — 列印GC 的細節
  • ##-XX: PrintGCDateStamps — 列印GC 操作的時間戳


  • -XX:NewSize / XX:MaxNewSize — 設定新生代大小/新生代最大大小


  • -XX:NewRatio — 可以設定老生代和新生代的比例


  • #-XX:PrintTenuringDistribution — 設定每次新生代GC 後輸出倖存者樂園中物件年齡的分



  • -XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設定老年代閥值的初始值和最

  • 大值


  • -XX:TargetSurvivorRatio:設定倖存區的目標使用率

    #題外話,談到jvm的運行機制,那麼java到底是編譯性型語言還是解釋型語言呢?

我查過很多資料,說什麼的都有,有人說是解釋型語言,有人為了把java 跟js做比較說它是編譯性語言。

首先,我們先來看看這兩種語言類型的介紹:

電腦高階語言類型主要有編譯型和解釋型兩種:

   編譯型語言:在程式執行之前,有一個單獨的編譯過程,將程式翻譯成機器語言,以後執行這個程式時,就不用再進行翻譯了。

    解釋型語言:是在運作的時候將程式翻譯成機器語言,所以運作速度相對於編譯型語言要慢。

  二者之間最大的差異就在於是否存下目標機器碼:編譯會把輸入的源程式以某種單位(例如基本塊/函數/方法/trace等)翻譯產生目標機器碼,並存下來(無論是在磁碟上或記憶體中)後續執行可以重複使用;解釋則是把原始程式中的指令逐條解釋執行,邊解釋邊執行,不存下目標碼,後續執行沒有可以重複使用的資訊。

 了解Java的運作過程:Java原始檔(*.java),透過java編譯器(javac)編譯產生一個ByteCode字節碼檔(*.class),字節碼由java自己設計的一台電腦(即java虛擬機,JVM)解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的目標機器碼,然後在特定的機器上運行。

終端機中如何運行一個java程式?解析其運作機制及其運作原理

雖然Java的第一道工序是javac編譯,其目標檔案是ByteCode,而並非機器語言,但後續可能有三種處理方式(在這,目前對這三種處理方式不做評價,需要對jvm知識深入探討後,再做驗證):

1、運行時,ByteCode由JVM逐條送給解釋器,解釋器將翻譯成機器碼運行。 (很多人說的是解釋型語言也是以此為出發點的)

2、運行時,部分ByteCode可能由實時編譯器(Just In Time Compiler,JIT)編譯為目標機器碼再執行(以method為翻譯單位,還會保存起來,第二次執行就不用再翻譯為機器碼了),因為考慮到有些JVM是採用純JIT編譯方式實現的,其內部沒有解釋器,例如:JRockit、Maxine VM。

3、RTSJ,繼javac之後執行AOT二次編譯,產生靜態的目標平台碼。

有的時候,可能是以上三種方式同時在使用,至少,1和2是同時使用的,3則需要程式設計師手動指定。

對此,本人比較願意接受的java是編譯與解釋兩者之間的混合式語言。

end:

到這篇文章就結束了,感謝大家的支持,如有不足之處,也歡迎指出交流!

相關文章:

Java中程式運作機制以及錯誤的分析

深入解讀PHP運行機制

相關影片:

方法的呼叫void類型方法的定義與呼叫-JAVA 初級入門影片教學 

以上是終端機中如何運行一個java程式?解析其運作機制及其運作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn