JVM內(nèi)存簡單描述
java的JVM內(nèi)存可分為3個(gè)區(qū):堆(heap),棧(stack)和方法區(qū)(method)。
堆
- 存儲(chǔ)的都是new出來的對(duì)象,每個(gè)對(duì)象都持有一個(gè)對(duì)應(yīng)的class信息驱敲;
- JVM只有一個(gè)堆,所有線程共享宽闲,堆中不放基本數(shù)據(jù)類型众眨,只放對(duì)象本身;
棧
- 每個(gè)線程有自己的棧容诬,棧中只保存基本數(shù)據(jù)類型和對(duì)象的引用(具體對(duì)象在堆中)娩梨;
- 棧和棧之間的數(shù)據(jù)都各自獨(dú)立、私有览徒,不能訪問狈定;
- 棧包含3個(gè)部分:基本數(shù)據(jù)類型區(qū)域,執(zhí)行環(huán)境上下文,操作指令區(qū)域纽什;
方法區(qū)
- 又叫靜態(tài)區(qū)措嵌,跟堆一樣,被所有線程共享芦缰,包含所有加載到內(nèi)存中的class和static變量企巢;
- 方法區(qū)的東西在整個(gè)程序中唯一存在;
例子
代碼
public class Main {
public static final void main(String[] args) {
Demo demo = new Demo();
demo.print();
}
}
class Demo {
public void print() {
System.out.println("hello");
}
}
從內(nèi)存角度來看執(zhí)行過程
- 系統(tǒng)收到我們發(fā)出的指令(點(diǎn)擊運(yùn)行后)让蕾,啟動(dòng)了一個(gè)java虛擬機(jī)進(jìn)程浪规,該進(jìn)程首先從classpath中找到Main.class文件,讀取并加載到方法區(qū)中(這一過程叫做類加載)探孝;
- 解析該類笋婿,找到main方法的字節(jié)碼,準(zhǔn)備開始執(zhí)行顿颅;
- 進(jìn)入main方法缸濒,解析第一條語句
Demo demo = new Demo();
發(fā)現(xiàn)是需要Demo這個(gè)類,然后去方法區(qū)查找元镀,由于第一次使用該類绍填,方法區(qū)沒有找到; - 繼續(xù)從classpath中查找(如果沒有找到栖疑,會(huì)報(bào)ClassNotFoundException的錯(cuò)誤)讨永,找到Demo后,加載到內(nèi)存的方法區(qū)遇革;
- 下一條指令是new卿闹,說明需要在堆內(nèi)存中新建一份對(duì)象(假設(shè)新建的對(duì)象在內(nèi)存的0xff10-0xff6f中);
- 下一條指令是賦值符號(hào)“=”萝快,要求在當(dāng)前線程的棧內(nèi)存中保存下剛才新建的內(nèi)存對(duì)象地址賦值給demo變量(假設(shè)demo變量在棧內(nèi)存中的值為0xff10,指向堆內(nèi)存中實(shí)際的對(duì)象)锻霎;
- 執(zhí)行demo.print(),首先查找demo對(duì)應(yīng)的實(shí)際的對(duì)象是否有該方法的字節(jié)碼(如果沒有揪漩,會(huì)去父類中查找旋恼,直到查找失敗)奄容,查找后執(zhí)行該方法的字節(jié)碼包含的方法指令冰更。