圖文詳解Java的記憶體機制(附程式碼)
Java把記憶體分成兩種:一種是堆疊內存,另一種是堆疊內存。在函數中定義的一些基本型別的變數和物件的引用變數都是在函數的堆疊記憶體中分配,當在一段程式碼區塊定義一個變數時,Java 就在棧中為這個變數分配記憶體空間,當超過變數的作用域後(比如,在函數A中呼叫函數B ,在函數B中定義變數a,變數a的作用域只是函數B,在函數B運行以後,變數a會自動被銷毀。釋放掉為該變數分配的記憶體空間,該記憶體空間可以立即另做他用。
堆記憶體用來存放由new創建的記憶體陣列,在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。 在堆中產生一個數組或物件之後,還可以在堆疊中定義一個特殊的變量,讓堆疊中的這個變量的取值等於數組或物件在堆疊內存中的首地址,棧中的這個變量就變成了數組或對象的引用變量,以後就可以在程式中使用棧中的變量來訪問堆中的數組或者對象,引用變量就相當於為數組或者對象起的一個名字。 引用變數是普通的變量,定義時在堆疊中分配,引用變數在程式運行到其他作用域之外後邊釋放。而陣列和物件本省在堆中分配,即使程式運行到使用new產生的陣列或物件的語句所在的程式碼區塊之外,陣列和物件本省佔據的記憶體不會被釋放。陣列和物件在沒有引用變數指向它的時候,才變成垃圾,不能再被使用,在隨後的一個不確定時間被垃圾回收器收走(釋放掉)。這也是Java比較佔記憶體的原因,實際上,堆疊中的變數指向堆疊記憶體中的變量,這就是Java中的指標。
程式碼實例Demo1:單一物件建立
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo1 { public static void main(String[] args) { Person per = new Person() ; } }
在上述程式中實例化了一個物件per,在實例化的過程中需要再記憶體中開啟空間,其中包括堆疊內存和堆內存,具體的內存分配如下圖所示:
圖1-1 物件的實例化過程
我們可以從上圖中發現,物件名稱per被保存在了堆疊記憶體中(更準確的說法是,在堆疊記憶體中保存的是堆記憶體空間的存取位址),而物件的具體內容,例如屬性name和age,被保存在堆記憶體中。因為per物件只是被實例化,還沒有被具體賦值,所以都是預設值。 字串的預設值為null,int的型別的預設值為0。前面已經提到,堆記憶體空間必須使用new關鍵字才能開啟。
程式碼實例Demo2:多個物件建立
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo2 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = new Person() ; per1.name="张三" ; per1.age=30 ; per2.age=33 ; per1.tell(); per2.tell(); } }
圖1-2 實例化兩個物件
程式碼實例Demo3:物件參考傳遞1######
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo3 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = per1 ;//-------注意-------- per1.name="张三" ; per1.age=30 ; per2.age=33 ; per1.tell(); per2.tell(); } }
图1-3 对象引用的传递内存分配
图1-3 对象引用的传递内存分配(续)
注意:上述实例中对象per2没有堆内存空间,这是因为对象per2只进行声明操作,也没有进行实例化操作。只是使用new关键字,实例化以后才会有堆内存空间
代码实例Demo4:对象引用传递2
class Person { String name ; int age ; public void tell() { System.out.println("姓名:"+name+",年龄:"+age); } } public class Demo4 { public static void main(String[] args) { Person per1 = new Person() ; Person per2 = new Person() ; per1.name="张三" ; per1.age=30 ; per2.name="李四" ; per2.age=33 ; per2=per1 ;//-----注意---- per1.tell(); per2.tell(); } }
上述运行程序结果为:
从程序的输出结果可以发现跟Demo3差不多。不过内存分配发生了一些变化,具体如下所示:
图1-4 (垃圾对象)的产生
注意点:
1.Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期释放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="李四";age=33。
2.一个栈内存只能指向一个堆内存空间,如果要想指向其他堆内存空间,则必须先断开已有的指向,才能分配新的指向。
Java中常见的内存区域
在Java中主要存在4块内存空间,这些内存的名称及作用如下:
1.栈内存空间:保存所有对象的名称。
2.堆内存空间:保存每个对象的具体属性内容。
3.全局数据区:保存static类型的属性值。
4.全局代码区:保存所有的方法定义。
以上是圖文詳解Java的記憶體機制(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...
