一、名詞解釋:java
棧幀:棧幀是用於支持虛擬機進行方法調用和方法執行的數據結構,它是虛擬機運行時數據區中的虛擬機棧的棧元素。數據結構
二、程序計數器:多線程
程序計數器是一塊比較小的內存空間,能夠將它看做是當前線程所執行的字節碼的行號指示器。函數
因爲Java是支持多線程的語言,當運行的線程數超過CPU數量時,線程之間根據CPU時間片輪詢搶奪CPU資源,在任意一個時刻,一個處理器(例如一個單核的CPU)都只能執行一條線程中的指令,其餘線程都必須被切換出去。所以爲了保證每個線程切換後能恢復到正確的執行位置,每條線程都須要一個獨立的程序計數器,各個線程之間,程序計數器獨立工做,互不影響;因此程序計數器是線程的私有空間。性能
若是當前線程正在執行一個Java方法,則程序計數器記錄正在執行的Java字節碼地址,若是當前線程正在執行一個Native方法,則程序計數器爲空。在Java虛擬機規範中,該區域是沒有規定任何OOM(OutOfMemoryError在之後的文章中都將使用OOM來表示OutOfMemoryError)的區域。this
三、Java虛擬機棧線程
Java虛擬機棧與程序計數器同樣也是線程私有的內存空間,它隨着線程的建立而建立,隨着線程的消失而消失;它主要用於存儲方法的局部變量、操做數棧、動態連接方法和返回地址等信息。指針
虛擬機在運行時使用一種叫棧幀的數據結構保存上下文數據。在棧幀中,存放了方法的局部變量表、操做數棧、動態連接方法和返回地址等信息。每個方法的調用都伴隨着棧幀的入棧操做;相同地,方法的返回則伴隨着棧幀的出棧操做(這就是傳說中的入棧、出棧)。因爲局部變量表中存儲的是基本數據類型(boolean、byte、int、short、char、float、double、long)、對象的引用(能夠理解爲一個指針,指向堆內存中的對象)和返回值地址,因此當一個方法的參數和局部變量相對較多時,那麼棧幀中的局部變量表就會比較大,棧幀會膨脹以知足方法調用所需傳遞的信息。在Java虛擬機棧中與性能調優關係最爲密切的部分就是局部變量表。局部變量表用於存放方法的參數和局部變量。其中long與double佔用8個字節(64位),int和float佔用4個字節,short和char佔用2個字節,byte佔用1個字節,boolean佔用1位(虛擬機按1個字節進行處理)。在方法執行時,虛擬機使用局部變量表完成方法的傳遞,對於非static方法還會將當前對象this做爲參數經過局部變量表傳遞給當前方法。對象
Java虛擬機規範容許,Java棧的大小是動態的或者固定的。在java虛擬機規範中,對該區域定義了兩種異常:StackOverflowError和OOM。若是線程在計算過程當中,請求的棧深度大於最大可用的棧深度,則拋出StackOverflowError;若是Java棧能夠動態擴展,而在擴展棧的過程當中,沒有足夠的內存空間來支持棧的擴展,則拋出OOM。內存
在Java虛擬機中,可使用-Xss參數來設置棧的大小。棧的大小直接決定了函數調用的可達深度。