前言-與正文無關
????????生活遠不止眼前的苦勞與奔波,它還充滿了無數值得我們去體驗和珍惜的美好事物。在這個快節奏的世界中,我們往往容易陷入工作的漩渦,忘記了停下腳步,感受周圍的世界。讓我們一起提醒自己,要適時放慢腳步,欣賞生活中的每一道風景,享受與家人朋友的溫馨時光,發現那些平凡日子里隱藏的幸福時刻。因為,這些點點滴滴匯聚起來的,才是構成我們豐富多彩生活的本質。希望每個人都能在繁忙的生活中找到自己的快樂之源,不僅僅為了生存而工作,更為了更好的生活而生活.
????????送你張美圖!希望你開心!
目錄
棧、堆、方法區
棧和堆
堆和方法區
棧、堆、方法區和線程
棧
存儲內容
棧的特性
棧與請求
圖解數據創建
棧、堆、方法區
棧內存中放哪些東西?
? ①基本類型的變量,例如int a=3中的a;
? ②上圖對象的引用變量,例如Person person=new Person();中的person
堆內存中存放哪些東西?
? ① 存放由new創建的對象和數組。如上圖的new Person()后的對象:
? 在堆中存放的內存,由Java虛擬機垃圾回收器來管理。在堆中產生了一個數組或者對象后,還可以在棧中定義一個特殊的變量,這個變量持有的內容等于數組或者對象在堆內存中的首地址。在棧中的這個特殊的變量,就成了數組或者對象的引用變量,以后就可以在程序中使用棧內存中的引用變量來訪問堆中的數組或者對象,引用變量相當于為數組或者對象起的一個別名,或者代號。
靜態區/方法區(也叫元空間)存放哪些東西?:
? 方法區(method)也叫做靜態區,跟堆一樣,被所有的線程共享。方法區包含所有的class和static變量,還有string的直接賦值的數據值。
? 方法區中包含的都是在整個程序中永遠唯一的元素,例如class,static變量。
? 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量放在相鄰的另一塊區域。
棧和堆
????????通俗來講,堆是用來存放對象的(在細說一下代碼執行的new,包括new后set的內容,也就是對象所持內容都是堆存放。),而棧是用來執行程序還有對象引用的,方法區存放類,靜態變量的。同一個棧中有3個部分是共享的:基本類型變量區,執行環境上下文,操作指令區。
????????就速度來說,有如下關系: 寄存器 > 棧 >堆 >其他這是棧的優勢。但缺點是,存在棧中的數據大小和生存期是必須確定的,缺乏靈活性。棧有一個很重要的特性,就是存在棧中的數據可以共享。假設我們同時定義:
????????int a = 3;
????????int b = 3;
????????編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然后查找棧中是否有3這個值,如果沒找到,就將3存放進來,然后將a指向3。接著處理int b = 3;在創建完b的引用變量后,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再令a=4;那么編譯器會重新搜索棧中是否有4值,如果沒有,則將4存放進來,并令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。要注意這種數據的共享與兩個對象的引用時
堆和方法區
????????注意一下String s3 = "china" 中china也存在方法區;String ss1 = new String("china"); 才存在堆中。對于通過 new 產生一個字符串(假設為 ”china” )時,會先去常量池中查找是否已經有了 ”china” 對象,如果沒有則在常量池中創建一個此字符串對象,然后堆中再創建一個常量池中此 ”china” 對象的拷貝對象。并把ss1指向堆中的地址。(在常量池中創建目的是為了提升字符串的訪問效率)
棧、堆、方法區和線程
棧是私有,堆和元空間是公有
棧
棧也叫棧內存,是在線程創建時創建,用于管理該線程的局部變量、方法調用信息、操作數棧等。它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對于棧來說不存在垃圾回收問題,只要線程一結束該棧就Over,這些棧在物理內存中是獨立的,互不干擾。8種基本類型的變量+對象的引用變量+實例方法都是在函數的棧內存中分配 。每一個棧對應一個線程,但是棧的數量實在太多了,導致jvm無法容納這么多的棧。虛擬機將拋出一個OutOfMemory 異常
每個線程在創建時都會分配一個獨立的棧,
存儲內容
-
局部變量表:包含方法參數和局部變量。局部變量表的大小在編譯時確定。
-
操作數棧:用于執行字節碼指令時存儲操作數和中間結果。
-
棧幀:每個方法調用都會創建一個棧幀,棧幀包含局部變量表、操作數棧、動態鏈接和方法返回地址。
-
動態鏈接:用于支持方法調用的動態鏈接。
-
方法返回地址:方法返回時需要跳轉的地址。
棧的特性
-
獨立性:每個線程都有一個獨立的棧,棧內數據不會與其他線程共享。
-
內存大小:棧的大小可以通過 JVM 參數
-Xss
配置,通常在 512 KB 到 1 MB 之間。1.5以后默認1M. -
棧幀:每次方法調用都會創建一個新的棧幀,保存方法的局部變量、操作數棧、動態鏈接和返回地址。
-
生命周期:棧的生命周期與線程相同,從線程創建到線程銷毀。
棧與請求
-
請求到達服務器:
-
當一個新的 HTTP 請求到達服務器時,服務器會從線程池中獲取一個可用線程(如果沒有可用線程,可能會阻塞或拒絕請求,視線程池配置而定)。
-
-
線程處理請求:
-
獲取到線程后,該線程會開始處理請求,包括解析請求頭、處理業務邏輯、訪問數據庫、生成響應等。
-
在這個過程中,線程會使用它的棧來保存方法調用的信息、局部變量和中間計算結果。
-
-
請求處理完成:
-
當請求處理完成后,線程會生成 HTTP 響應并返回給客戶端。
-
處理完成后,線程會返回到線程池中,等待下一個請求。
-
圖解數據創建
package test01;public class StackHeadMethod {public static void main(String[] args) {int a = 1;String b = "testBName";Test test = new Test();test.testMethod(a, b);}
}class Test {private int testA;private String testB;private static final int testC = 2;public void testMethod(int testA, String testB){this.testA = testA;this.testB = testB;}
}
?首先,JVM將StackHeadMethod.class、Test.class裝載到方法區(JVM會執行啟動類裝載器、擴展類裝載器和類路徑裝載器,在此只詳細講解針對本測試代碼的字節碼文件的執行)。其中方法區中的2是Test.java中的靜態變量,在類加載的時候就在方法區中的靜態存儲空間分配內存。
?然后,在StackHeadMethod.class文件中,找到main方法,開始執行main方法。將main方法在棧中開辟一個空間,稱為棧幀。執行下面07、08、09、17、18、19行代碼。?? 再然后,執行test.testMethod(a, b);這一行,在棧中新分配一個棧幀,調用test中的testMethod方法。
? 最后,testMethod方法執行完之后,testMethod棧幀從棧中釋放空間,然后main方法執行完之后,main棧幀也釋放空間,最后堆中的對象和方法區中的靜態變量、字符串和字節碼指令都沒被使用時,根據java虛擬機的垃圾回收機制,進行對垃圾的回收。
? ? 以上,是執行一段代碼,對內存進行開辟和釋放的整個過程。
------------------------------------------與正文內容無關------------------------------------
?如果覺的文章寫對各位讀者老爺們有幫助的話,麻煩點贊加關注唄!作者在這拜謝了!
混口飯吃了!如果你需要Java 、Python畢設、商務合作、技術交流、就業指導、技術支持度過試用期。請在關注私信我,本人看到一定馬上回復!
這是我全部文章所在目錄,看看是否有你需要的,如果遇到覺得不對地方請留言,看到后我會查閱進行改正。
A樂神-CSDN博客
關注在文章左上角,作者信息處。