150天打卡day20_內(nèi)存管理
1.上節(jié)回顧
內(nèi)部類的定義
成員內(nèi)部類
匿名內(nèi)部類
2.內(nèi)存管理
java的編譯過程,編譯期從.java文件編譯成字節(jié)碼.class文件,運(yùn)行期又JVM(java虛擬機(jī))加載.class文件,運(yùn)行程序。所以Java程序都是要經(jīng)過編譯最后在JVM虛擬機(jī)中運(yùn)行

變量是在內(nèi)存中存儲數(shù)據(jù)的一塊空間,程序中所有的數(shù)據(jù)都要用變量臨時保存在內(nèi)存中。


學(xué)習(xí)數(shù)組,學(xué)習(xí)靜態(tài)的時候也都會解釋內(nèi)存變化
在程序中,無論是代碼還是數(shù)據(jù)都要保存在內(nèi)存中,而內(nèi)存變化由運(yùn)行程序的JVM來管理所需的內(nèi)存空間。內(nèi)存又分為三大塊,分別是堆(heap)、棧、方法區(qū)。
2.1 堆內(nèi)存
堆:可以理解為內(nèi)存中一片分散的區(qū)域
堆內(nèi)存在某種意義上來說是在內(nèi)存中最靈活的,也是唯一可以讓程序員主動控制的空間。因為堆內(nèi)存里面存放的都是new出來的對象實例,用完之后靠垃圾回收器不定期的自動消除比如:
Human h1 = new Human();
程序運(yùn)行的時候會先執(zhí)行等號右邊的new Human();在內(nèi)存中創(chuàng)建出一個h1對象,假設(shè)里面有兩個屬性,名字和年齡,地址為0x50;
其實h1對象就是創(chuàng)建在堆內(nèi)存中的,每new一次,就會開辟一塊內(nèi)存空間,而且每個對象都會有唯一的內(nèi)存地址。
由于每個對象都沒有名字,只有地址,由引用變量保存,指向?qū)ο蟮刂罚蠹蚁扔涀∮脕肀4娴刂返囊米兞渴潜4嬖跅V小?/span>

?
2.1.1. 對象生命周期
對象也是有生命周期的,當(dāng)一個對象沒有任何變量指向他的時候,就會被視為廢棄的對象,就要等待被回收。對象中的成員變量也會等待回收。
所以對象和成員變量的的生命周期為:從對象在堆中被創(chuàng)建開始到對象從堆中被回收結(jié)束。
2.1.2 垃圾回收機(jī)制
在Java中會有一個自動回收的機(jī)制:叫垃圾回收器(Garbage ?Collection),簡稱gc,他是JVM自帶的一個線程(自動運(yùn)行著的程序),用于回收沒有任何引用指向的對象。
?
問題一:
既然gc會把廢棄的對象自動回收掉,那會不會把成員變量也一并回收了?
2.1.3 內(nèi)存泄漏
內(nèi)存泄漏就是指不再使用的內(nèi)存沒有被及時的回收掉。嚴(yán)重的內(nèi)存泄漏會因為過多的內(nèi)存占用而導(dǎo)致程序奔潰。
例如:
Human h1 = new Human()Human ();
new出來的對象都存儲在堆中,然后通過引用變量保存地址指向h1對象,假如有另一個
Human h2 = h1
?

問題二:
那么h2會不會新開辟一個空間?
問題三:
如果這時候h1=null的時候意味著c里面已經(jīng)沒有地址了,那對象算不算垃圾?
?
2.1.4.System.gc()方法
而gc的回收過程對于程序員來說是透明的,不一定說是發(fā)現(xiàn)了垃圾就會立馬清除掉,所以呢這時候就需要程序員手動調(diào)用System.gc()方法來建議JVM盡快幫我們調(diào)用gc來回收垃圾。
2.2.棧內(nèi)存
棧:可以理解為是內(nèi)存中一片連續(xù)的區(qū)域
基本數(shù)據(jù)類型,局部變量都是存放在棧內(nèi)存中,用完就消失。
JVM在其內(nèi)存空間開辟一個稱為”?!钡拇鎯臻g,用于存儲程序運(yùn)行時在方法中聲明的所有的局部變量
方法中的變量就是局部變量,是在棧內(nèi)存中分配的,如果變量為基本類型,則在棧內(nèi)存儲的是該變量的值。如果變量為引用類型,則在棧中存儲的是堆中的對象的地址。
一個運(yùn)行的Java程序從開始到結(jié)束可能會有多次方法的調(diào)用,而JVM會為每一個方法的調(diào)用在棧中分配一個對應(yīng)的空間,這個空間稱為是該方法的棧幀。而且一個棧幀對應(yīng)一個正在調(diào)用中的方法,棧幀里面存放了這個方法的局部變量和參數(shù)。只有當(dāng)方法調(diào)用完了,對應(yīng)的棧幀也將會被清除,局部變量也隨之失效。
例如:
class Add{ ?int numA; ?void show(int numB){ ? ?int numC = 5; ?} }
2.2.1.局部變量的生命周期
方法調(diào)用時,生命周期開始,方法結(jié)束調(diào)用后,生命周期結(jié)束
2.2.2.成員變量和局部變量
成員變量
寫在類中,方法外的叫成員變量,有默認(rèn)的初始值,而且在類實例化的時候,存放在堆中,和對象的生命周期一樣,對象失效時,成員變量也一并失效。
class Add{ ?int numA; }
局部變量:
寫在方法里面的,包括參數(shù)都叫做局部變量,沒有默認(rèn)的初始值,必須自己設(shè)定初始值,方法被調(diào)用時,存在棧中,方法調(diào)用完了,就從棧中清除了。
?
2.3.方法區(qū)
方法區(qū)是各個線程共享的內(nèi)存區(qū)域,用于存儲已經(jīng)被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,即時編譯器編譯后的代碼等數(shù)據(jù)
方法區(qū)里存的是.class的字節(jié)碼文件,一旦程序運(yùn)行的時候,有個類裝載器會先加載.class字節(jié)碼信息,而經(jīng)過解析后裝在方法區(qū)中,所以方法區(qū)中存的是字節(jié)碼文件、方法和靜態(tài)變量.
方法區(qū)中的內(nèi)容在類存在的時候就已經(jīng)有了,所以只會加載一次
方法只有一份,通過this來區(qū)分具體的對象,誰調(diào)用就用this
?
?
?
?
?
?
?
?