近段時(shí)間研究了java的程序執(zhí)行過程中的內(nèi)存分配,收獲頗多,解決了我最近時(shí)間學(xué)習(xí)java的很多困惑點(diǎn)。寫java內(nèi)存分析系列的目的主要有兩個(gè),一來是希望給像我一樣的java初學(xué)者一定的啟發(fā),希望也能解決的java關(guān)于內(nèi)存方面的困惑點(diǎn)。二來也是給自己做個(gè)總結(jié),畢竟只有自己親自寫出來的東西,才是真正的東西。今天就開始java程序執(zhí)行過程內(nèi)存分析系列第一篇。 一、 java執(zhí)行程序時(shí)內(nèi)存的劃分 一般來說,作為初學(xué)者,一般只是將java程序的內(nèi)存只是分為棧區(qū),和堆區(qū)。確實(shí)剛開始學(xué)時(shí)這樣劃分能都便于我們理解,但是隨著學(xué)習(xí)java時(shí)間的增多,如果內(nèi)存劃分還只是簡單的只有棧和堆兩個(gè)區(qū),就有很多東西不能深入理解,就拿個(gè)常用的字符來說,就很難理解字符串的一些特性。于是乎我這里就增加一個(gè)內(nèi)存區(qū)域的劃分,這樣比以前能理解更多的東西。這個(gè)新增的內(nèi)存區(qū)域是什么呢?其實(shí)也不是新增,就是把以前堆內(nèi)存劃分為方法區(qū)和其他區(qū)。那方法區(qū)里面存放些什么東西勒,方法區(qū)里面主要存放三個(gè)東西,第一個(gè)是程序的代碼,第二個(gè)是常量池,這里主要存放一些java程序中的一些常量和字符串常量,第三個(gè)是靜態(tài)的變量。堆內(nèi)存劃分如圖所示。首先我定義了一個(gè)people類,里面有姓名和性別兩個(gè)成員變量和一個(gè)說話的成員方法。另外還有一個(gè)測試類,測試people類,好了,萬事俱備,只欠東風(fēng)了。下面正式開始內(nèi)存分析。 1publicclass People { 2 String name;//定義一個(gè)人的姓名3 String sex; 4publicvoid speak{ 5 System.out.println('hi 你好'); 6 } 78 } 1publicclass Test { 2publicstaticvoid main(String args) { 3 People p = new People; 4 System.out.println(p.name); 5 System.out.println(p.sex); 6 p.speak; 7 } 8 } 在程序開始運(yùn)行時(shí),執(zhí)行的命令是 java Test(eclipse 剛開始也是要執(zhí)行這句命令,就是在執(zhí)行運(yùn)行的命令時(shí),就是在執(zhí)行java Test),這時(shí)jvm也就是java虛擬機(jī)會(huì)把Test類加載到方法區(qū),然后找到程序的test類的里面的main方法,作為整個(gè)程序的入口,開始運(yùn)行整個(gè)程序。首先執(zhí)行第三行命令people 怕= new people;執(zhí)行這行代碼時(shí),內(nèi)存中發(fā)生了到底哪些變化,當(dāng)jvm遇到people p首先會(huì)執(zhí)行jvm會(huì)到他管理路徑下面找people類,如果沒找到,就會(huì)報(bào)錯(cuò),如果找到就會(huì)把people類加載到方法區(qū),前面提過方法區(qū)里面主要存放一些代碼和一些常量,然后棧內(nèi)存中保存p引用變量,并初始化為null,加載完people類之后緊接著就執(zhí)行new people,jvm遇到new關(guān)鍵字到堆內(nèi)存開辟一塊空間,保存people類實(shí)例化的對(duì)象。并把這塊內(nèi)存的首地址賦值給p。具體如圖所示。 這里p引用的值是new people對(duì)象的內(nèi)存空間首地址。這里需要注意的是成員變量有個(gè)初始值,所有引用類型的初始值是為null,另外一個(gè)類創(chuàng)建的多個(gè)對(duì)象共享成員方法。 三、結(jié)語分析到這里,內(nèi)存分析系列一就到這里了,接下來我會(huì)繼續(xù)深入內(nèi)存分析,關(guān)于this,super以及static,string,和繼承的內(nèi)存分析,希望能對(duì)大家有所幫助。 |
|