組成
1. 局部變量表:一個數字數組,用于存儲方法參數和定義在方法體內的局部變量。數據類型包括基本數據類型和引用數據類型。所需容量大小在編譯器就確定下來了。
? ? ? ? 變量的分類:按照數據類型分:1. 基本數據類型?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2. 引用數據類型
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按照在類中的位置分:1. 成員變量:在使用前,都經歷過默認初始化賦值。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1)類變量:在類加載的連接階段賦默認值,在初始化階段賦初始值。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2)實例變量:隨著對象的創建,在堆空間中分配實例變量空間,并賦默認值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2. 局部變量:在使用前必須要顯示賦值
2. 操作數棧:用棧來操作數,將數放入棧中再放入局部變量表中,需要使用時再入棧出棧。如果方法有返回值,會將返回值放入棧中。
3. 動態鏈接:指向運行時常量池的方法引用
4. 方法返回地址:調用的方法棧幀出棧之后將返回值壓入調用者的操作數棧中以供使用。
作用
每個線程運行的時候,需要的內存空間。一個線程對應一個棧
每個棧內由多個棧楨組成。
棧楨
每個方法運行時需要的內存(參數,局部變量,返回地址),每個方法執行時都要提前分配內存地址
當調用一個方法的時候,就會給方法劃分一個棧楨并壓入棧內,當方法執行完畢,就會讓這個棧楨出棧釋放內存。
一個方法中可能會劃分多個棧楨:如調用該方法時內部調用了其他方法。但每個線程只能有一個活動棧楨,對應著當前正在執行的那個方法。
主方法也對應著一個棧楨
問題
1. 垃圾回收是否設計棧內存?
? ? 否,棧內存即每次方法執行的棧楨內存,每個棧楨內存在方法調用結束后都會被釋放
2. 棧內存分配越大越好嗎?
? ? 在運行java代碼的時候,可以設置棧內存的大小,默認大小為1024kb
? ? 棧內存越大,只是能進行多次的方法遞歸調用,反而會讓線程數變少
3. 方法內的局部變量是否線程安全?
? ? 看一個變量是否線程安全就要看它是否是對一個線程共享的還是獨占的。
? ? 如果是一個基本變量是線程安全的,一個線程對應一個棧,不同的線程在調用同一個方法的時候,會有不同的棧。線程內每一次方法調用都會產生一個新的棧楨。
????但如果是staic的變量,是針對多個的線程共享的,則會涉及到線程安全問題
? ? 如果方法內局部變量沒有逃離方法的作用范圍,它是線程安全的。反之,如果它作為行參傳入或return了這個變量,則它可能會被其他線程操作,為線程所共享。
棧內存溢出
stackoverflowError
什么情況會導致棧內存溢出?
在棧內存不能動態擴展的情況下:
1. 棧楨過多導致棧內存溢出(如果方法的遞歸沒有設置一個遞歸退出的條件)
2. 棧楨過大也會導致棧內存溢出(這種情況很少,棧楨直接超出棧內存)
如何設置棧的內存大小
線程運行診斷
nohup:后臺運行Java程序
案例1: cpu占用過多
? ? 使用命令
? ? 1. 用top定位到那個進程對cpu占用過高
? ? 2. ps H -eo pid,tid,%cpu | grep 進程id,定位到哪個線程對cpu占用過高
? ? 3. 使用jdk提供的 jstack 進程id:定位該進程到所有的java輸出的線程,將linux下的線程id轉換為16進制即可找到對應的java線程