先給大家講一個今天看到的一個笑話:
有一人彩票中獎中了500W,記者專門對他進行了采訪浩蓉;
記者:“請問你中獎之后有什么打算嗎派继?”
“先買一套房子吧”;?
記者:“然后呢捻艳?”
“然后剩下的慢慢還”驾窟。
看了之后也是醉了,也不吐槽現(xiàn)在各地的房價了认轨,現(xiàn)在在帝都工作绅络,這個城市搞不懂,還是好好哦的敲代碼吧嘁字,昨天看到了一些東西恩急,與之前自己理解的有一些不一樣的地方,所以在這里總結(jié)下纪蜒,如果能幫到你衷恭,表示非常榮幸,要是有什么不對的或者讓你誤解的霍掺,先表示歉意匾荆。
內(nèi)存泄漏
概念:當(dāng)一個對象已經(jīng)不需要再使用了,本該被回收時杆烁,而有另外一個正在使用的對象持有它的引用從而就導(dǎo)致對象不能被回收牙丽。這種導(dǎo)致了本該被回收的對象不能被回收而停留在堆內(nèi)存中,就產(chǎn)生了內(nèi)存泄漏
內(nèi)存泄漏會造成我們僅限的內(nèi)存空間可使用的內(nèi)存越來越少兔魂,會造成應(yīng)用程序的卡頓甚至崩潰烤芦,想知道每款手機為每個app進程分配的內(nèi)存可以在AS里的Android Monitor里面的Memory中看到每個app系統(tǒng)分配的內(nèi)存空間,當(dāng)然利用Android Monitor也可以進行監(jiān)視內(nèi)存變化析校,分析內(nèi)存泄漏构罗,這些以后再說。首先我來給大家分析下內(nèi)存泄漏發(fā)生的一二三智玻。
JVM內(nèi)存分配的策略有:
1遂唧、靜態(tài)區(qū)
靜態(tài)區(qū)和我之前的理解是一樣的,內(nèi)存在程序編譯的時候就已經(jīng)分配好吊奢,這塊的內(nèi)存在程序整個運行期間都一直存在盖彭。它主要存放靜態(tài)數(shù)據(jù)、全局的static數(shù)據(jù)和一些常量页滚。
2召边、棧區(qū)
棧區(qū)和我之前的理解不太一樣,先說下我之前錯誤的理解裹驰,之前我一直以為在程序運行期間所有的基礎(chǔ)類型變量都是在棧區(qū)里面隧熙,所有的對象引用都在站里面,不過昨天我才知道自己的理解太過片面幻林,其實棧區(qū)中存儲的數(shù)據(jù)是函數(shù)(方法)在執(zhí)行時贞盯,函數(shù)一些內(nèi)部變量的存儲放在棧上面創(chuàng)建,函數(shù)執(zhí)行結(jié)束的時候這些存儲單元就會自動被釋放掉沪饺。當(dāng)然提前說一下邻悬,在方法內(nèi)部實例化的對象 即:通過new關(guān)鍵字創(chuàng)建的對象是保存在堆中,對象的引用是在棧里面随闽。等下面描述完了堆一塊給大家舉個例子父丰。
3、堆區(qū)
堆是不連續(xù)的內(nèi)存區(qū)域掘宪,堆空間比較靈活也特別大蛾扇。棧是一塊連續(xù)的內(nèi)存區(qū)域,大小是有操作系統(tǒng)覺決定的魏滚,我們所說的內(nèi)存泄漏都是發(fā)生在堆里镀首,因為棧里的數(shù)據(jù)在函數(shù)執(zhí)行完成之后已經(jīng)進行了銷毀,所以堆是出現(xiàn)內(nèi)存泄漏的地方鼠次,堆里面存放的數(shù)據(jù)就是我們new出來的東西了更哄。
舉個例子:
public class Main
{
int a=1; ?//之前一直認為是在棧里芋齿,結(jié)果想錯了,因為a屬于Main成翩,所以呀在實例化的Main對象肯定在堆里
Student s=newStudent();//引用在棧里觅捆,對象在堆里
public void XXX()
{
intb =1;//棧里面,因為是是方法內(nèi)部變量
Student s2 =newStudent(); //引用在棧里麻敌,對象在堆里
}
}
在上面的這個類里面栅炒,如果我們Main main = new Main();執(zhí)行了這句代碼之后,在內(nèi)存中main對象放在堆中术羔,main引用是在棧中赢赊,因為a這個變量是屬于main的,所以a也是在堆中级历,但是如果main.XXX()調(diào)用了該方法释移,那么b肯定在站里面,s2的引用在棧里寥殖, 對象在堆里秀鞭。
總結(jié)一下:
1.成員變量全部存儲在堆中(包括基本數(shù)據(jù)類型,引用的對象實體)---因為他們屬于類扛禽,類對象最終還是要被new出來的锋边。
2.局部變量的基本數(shù)據(jù)類型和引用存儲于棧當(dāng)中,引用的對象實體存儲在堆中编曼。-----因為他們屬于方法當(dāng)中的變量豆巨,生命周期會隨著方法一起結(jié)束。