JVM內(nèi)存模型

什么是內(nèi)存模型

  1. 寫(xiě)入動(dòng)作可見(jiàn)

    內(nèi)存模型定義了一個(gè)充分必要條件惭适,保證其它CPU的寫(xiě)入動(dòng)作對(duì)該CPU是可見(jiàn)的护桦,而且該CPU的寫(xiě)入動(dòng)作對(duì)其它CPU也是可見(jiàn)的

    1. 強(qiáng)內(nèi)存模型扳埂,所有CPU在任何時(shí)候都能看到內(nèi)存中任意位置相同的值宋彼,這種完全是硬件提供的支持赫悄。
    2. 弱內(nèi)存模型,需要執(zhí)行一些特殊指令(就是經(jīng)程梗看到或者聽(tīng)到的盐数,memory barriers內(nèi)存屏障),刷新CPU緩存的數(shù)據(jù)到內(nèi)存中伞梯,保證這個(gè)寫(xiě)操作能夠被其它CPU可見(jiàn)玫氢,或者將CPU緩存的數(shù)據(jù)設(shè)置為無(wú)效狀態(tài),保證其它CPU的寫(xiě)操作對(duì)本CPU可見(jiàn)谜诫。通常這些內(nèi)存屏障的行為由底層實(shí)現(xiàn)漾峡,對(duì)于上層語(yǔ)言的程序員來(lái)說(shuō)是透明的(不需要太關(guān)心具體的內(nèi)存屏障如何實(shí)現(xiàn))。
    3. 重排序可以發(fā)生在好幾個(gè)地方:編譯器喻旷、運(yùn)行時(shí)生逸、JIT等,比如編譯器會(huì)覺(jué)得把一個(gè)變量的寫(xiě)操作放在最后會(huì)更有效率且预,編譯后槽袄,這個(gè)指令就在最后了(前提是只要不改變程序的語(yǔ)義,編譯器锋谐、執(zhí)行器就可以這樣自由的隨意優(yōu)化)遍尺,一旦編譯器對(duì)某個(gè)變量的寫(xiě)操作進(jìn)行優(yōu)化(放到最后),那么在執(zhí)行之前涮拗,另一個(gè)線程將不會(huì)看到這個(gè)執(zhí)行結(jié)果乾戏。
Class Reordering {
    int x = 0, y = 0;
    public void writer() {
        x = 1;
        y = 2;
        }
    public void reader() {
        int r1 = y;
        int r2 = x; 
        } 
    /*在writer方法中迂苛,可能發(fā)生了重排序,
    *y的寫(xiě)入動(dòng)作可能發(fā)在x寫(xiě)入之前鼓择,這種情況下,
    *線程B就有可能看到 x的值還是0灾部。
    */
}

在Java內(nèi)存模型中,描述了在多線程代碼中惯退,哪些行為是正確的赌髓、合法的,以及多線程之間如何進(jìn)行通信催跪,代碼中變量的讀寫(xiě)行為如何反應(yīng)到內(nèi)存锁蠕、CPU緩存的底層細(xì)節(jié)。

在Java中包含了幾個(gè)關(guān)鍵字:volatile懊蒸、final和synchronized荣倾,幫助程序員把代碼中的并發(fā)需求描述給編譯器。Java內(nèi)存模型中定義了它們的行為骑丸,確保正確同步的Java代碼在所有的處理器架構(gòu)上都能正確執(zhí)行舌仍。

synchronization 可以實(shí)現(xiàn)什么

Synchronization有多種語(yǔ)義,其中最容易理解的是互斥通危,對(duì)于一個(gè)monitor對(duì)象铸豁,只能夠被一個(gè)線程持有,意味著一旦有線程進(jìn)入了同步代碼塊菊碟,那么其它線程就不能進(jìn)入直到第一個(gè)進(jìn)入的線程退出代碼塊(這因?yàn)槎寄芾斫猓?/p>

對(duì)于兩個(gè)線程來(lái)說(shuō)节芥,在相同的monitor對(duì)象上同步是很重要的,以便正確的設(shè)置happens-before關(guān)系逆害。

final 可以影響什么

如果一個(gè)類(lèi)包含final字段头镊,且在構(gòu)造函數(shù)中初始化,那么正確的構(gòu)造一個(gè)對(duì)象后魄幕,final字段被設(shè)置后對(duì)于其它線程是可見(jiàn)的相艇。

這里所說(shuō)的正確構(gòu)造對(duì)象,意思是在對(duì)象的構(gòu)造過(guò)程中纯陨,不允許對(duì)該對(duì)象進(jìn)行引用坛芽,不然的話,可能存在其它線程在對(duì)象還沒(méi)構(gòu)造完成時(shí)就對(duì)該對(duì)象進(jìn)行訪問(wèn)队丝,造成不必要的麻煩靡馁。

JVM的內(nèi)存分區(qū)

每個(gè)線程都有獨(dú)立的棧并且是相互隔離的欲鹏,

棧的大小

一個(gè)是jvm參數(shù) -XSS机久,默認(rèn)值隨著虛擬機(jī)版本以及操作系統(tǒng)影響。我們可以認(rèn)為64位linux默認(rèn)是1m的樣子赔嚎。 除了JVM設(shè)置膘盖,我們還可以在創(chuàng)建Thread的時(shí)候手工指定大小

棧的大小影響到了線程的最大數(shù)量胧弛,尤其在大流量的server中,我們很多時(shí)候的并發(fā)數(shù)受到的是線程數(shù)的限制侠畔,這時(shí)候需要了解限制在哪里

可看作:

線程數(shù) = (系統(tǒng)空閑內(nèi)存-堆內(nèi)存(-Xms, -Xmx)- perm區(qū)內(nèi)存(-XX:MaxPermSize)) / 線程棧大小(-Xss)

堆的結(jié)構(gòu)

對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)结缚,Java 堆(Java Heap)是Java 虛擬機(jī)所管理的內(nèi)存中最大的一塊。Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域软棺,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建红竭。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存喘落。

新對(duì)象會(huì)首先分配在Eden中(如果對(duì)象過(guò)大茵宪,比如大數(shù)組,將會(huì)直接放到老年代)瘦棋。在GC中稀火,Eden中的對(duì)象會(huì)被移動(dòng)到survivor中,直至對(duì)象滿(mǎn)足一定的年紀(jì)(定義為熬過(guò)minor GC的次數(shù))赌朋,會(huì)被移動(dòng)到老年代凰狞。

方法區(qū)

又稱(chēng)為“靜態(tài)區(qū)”,和堆一樣沛慢,被所有線程共享赡若。 其中包含所有的 class 和 static 變量

GC 垃圾收集

思考一下復(fù)制和標(biāo)記清除/整理的區(qū)別,為什么新生代要用復(fù)制团甲?因?yàn)閷?duì)新生代來(lái)講斩熊,一次垃圾收集要回收掉絕大部分對(duì)象,我們通過(guò)冗余空間的辦法來(lái)加速整理過(guò)程(不冗余空間的整理操作要做swap伐庭,而冗余只需要做move)粉渠。同時(shí)可以記錄下每個(gè)對(duì)象的『年齡』從而優(yōu)化『晉升』操作使得中年對(duì)象不被錯(cuò)誤放到老年代。而反過(guò)來(lái)老年代偏穩(wěn)定圾另,我們哪怕是用清除霸株,也不會(huì)產(chǎn)生太多的碎片,并且整理的代價(jià)也并不會(huì)太大集乔。

引用與內(nèi)存實(shí)例

首先去件,字面值及其引用
int a = 1;
int b = 1;
int b = 2;
//先創(chuàng)建名為a的引用,再去找是否已存在字面值為1的地址扰路,沒(méi)找到開(kāi)辟新地址放1.
//再創(chuàng)建b的引用變量尤溜,---棧---中已有“1”,直接指向它
//改變b時(shí)汗唱,a不會(huì)改變宫莱,因?yàn)楦淖兊氖莃的引用,而不是指向的字面值
new String()
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);//true
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println(str3 == str4);//false
//String 是特殊的包裝類(lèi)
//用new()來(lái)新建哩罪,會(huì)存放在---堆---中授霸,每次調(diào)用都是新的巡验。
//而創(chuàng)建引用常量還是和字面值一樣,不會(huì)新建碘耳,而去---棧---中的常量池中尋找
String str5 = str1+"World";
String str6 = "HelloWorld";
System.out.println(s5 == s6);//false
//equals判斷的是字面值是否相等显设,而==判斷的是引用是否指向同一個(gè)對(duì)象

new()出一個(gè)實(shí)例,JVM首先在堆中為其分配內(nèi)存辛辨,擁有著指向方法區(qū)

類(lèi)加載過(guò)程

參考鏈接:http://www.reibang.com/p/ace2aa692f96

從.java文件到實(shí)際加載到內(nèi)存中

JVM調(diào)用指定的ClassLoader去加載.class文件等各類(lèi)路徑捕捂、文件的類(lèi)

.java文件 -> 通過(guò)你的JDK環(huán)境相關(guān)指令編譯 -> .class文件 -> JVM初始化之后,如果有類(lèi)的執(zhí)行斗搞、調(diào)用等相關(guān)操作绞蹦,JVM就會(huì)將.class文件加載到內(nèi)存中,并開(kāi)始下面的一系列處理:(鏈接->初始化)

image
/* 類(lèi)加載方式:都是JVM調(diào)用ClassLoader去加載類(lèi) */
//方式一  Class.forName(String name);
public static Class<?> forName(String className) throws ClassNotFoundException { 
    return forName(className, true, VMStack.getCallingClassLoader()); 
}
public static Class<?> forName(String className, boolean shouldInitialize,
                               ClassLoader classLoader) throws ClassNotFoundException {
    if (classLoader == null) { 
        classLoader = BootClassLoader.getInstance(); 
    } 
    Class<?> result; 
    try { 
        result = classForName(className, shouldInitialize, classLoader); 
    } catch (ClassNotFoundException e) { 
        Throwable cause = e.getCause(); 
        if (cause instanceof LinkageError) { 
            throw (LinkageError) cause; 
        } 
        throw e; 
    } 
    return result; 
} 

//方式二

類(lèi)的初始化之前
  1. 加載
    • 通過(guò)一個(gè)類(lèi)全限定名(java.lang.String)來(lái)獲取定義此類(lèi)的二進(jìn)制字節(jié)流
    • 將其所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu) 》 方法區(qū)運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
    • 在---堆---中生成一個(gè)代表這個(gè)類(lèi)的java.lang.Class
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末榜旦,一起剝皮案震驚了整個(gè)濱河市幽七,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溅呢,老刑警劉巖澡屡,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咐旧,居然都是意外死亡驶鹉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)铣墨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)室埋,“玉大人,你說(shuō)我怎么就攤上這事伊约∫ο” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵屡律,是天一觀的道長(zhǎng)腌逢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)超埋,這世上最難降的妖魔是什么搏讶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮霍殴,結(jié)果婚禮上媒惕,老公的妹妹穿的比我還像新娘。我一直安慰自己来庭,他們只是感情好妒蔚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般面睛。 火紅的嫁衣襯著肌膚如雪絮蒿。 梳的紋絲不亂的頭發(fā)上尊搬,一...
    開(kāi)封第一講書(shū)人閱讀 51,692評(píng)論 1 305
  • 那天叁鉴,我揣著相機(jī)與錄音,去河邊找鬼佛寿。 笑死幌墓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冀泻。 我是一名探鬼主播常侣,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弹渔!你這毒婦竟也來(lái)了胳施?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肢专,失蹤者是張志新(化名)和其女友劉穎舞肆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體博杖,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椿胯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剃根。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哩盲。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖狈醉,靈堂內(nèi)的尸體忽然破棺而出廉油,到底是詐尸還是另有隱情,我是刑警寧澤苗傅,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布娱两,位于F島的核電站,受9級(jí)特大地震影響金吗,放射性物質(zhì)發(fā)生泄漏十兢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一摇庙、第九天 我趴在偏房一處隱蔽的房頂上張望旱物。 院中可真熱鬧,春花似錦卫袒、人聲如沸宵呛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宝穗。三九已至户秤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逮矛,已是汗流浹背鸡号。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留须鼎,地道東北人鲸伴。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像晋控,于是被迫代替她去往敵國(guó)和親汞窗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1 CPU和內(nèi)存的交互 了解jvm內(nèi)存模型前赡译,了解下cpu和計(jì)算機(jī)內(nèi)存的交互情況仲吏。【因?yàn)镴ava虛擬機(jī)內(nèi)存模型定義...
    Garwer閱讀 367,618評(píng)論 54 549
  • 文章轉(zhuǎn)自 http://blog.csdn.net/u012152619/article/details/4696...
    云狗狗狗狗狗閱讀 606評(píng)論 1 4
  • 我們知道蝌焚,計(jì)算機(jī)CPU和內(nèi)存的交互是最頻繁的裹唆,內(nèi)存是我們的高速緩存區(qū),用戶(hù)磁盤(pán)和CPU的交互综看,而CPU運(yùn)轉(zhuǎn)速度越來(lái)...
    join_a922閱讀 281評(píng)論 0 0
  • 見(jiàn)山見(jiàn)水見(jiàn)云天品腹,素面素身素心田。 知事知理知轉(zhuǎn)變红碑,了增了減了亦然舞吭。
    末學(xué)_d05e閱讀 237評(píng)論 3 10
  • 32 小曦從學(xué)校回來(lái)沒(méi)有去林峰家…而是回了自己的家析珊。然后給林峰打電話要求他過(guò)來(lái)一下羡鸥。過(guò)了半個(gè)小時(shí)。林峰過(guò)來(lái)了忠寻。林峰...
    驕傲的向日葵閱讀 306評(píng)論 0 1