據(jù)類型到 JVM 內(nèi)存與 GC)
結(jié)論對于基本類型 比數(shù)值對于引用類型 比地址 equals沒重寫比地址重寫了比內(nèi)容。來龍去脈1.數(shù)據(jù)類型Java數(shù)據(jù)類型 ├─ 基本類型8種 └─ 引用類型 ├─ 類 ├─ 接口 ├─ 數(shù)組 ├─ 枚舉 └─ 注解1.1基本類型共 8 種不是對象沒有equals()直接用比較值byteshortintlongfloatdoublecharboolean特點(diǎn)變量里直接存真實(shí)的值。1.2引用類型所有不是上面 8 個(gè)的全是引用類型類Integer、String、自定義類接口數(shù)組數(shù)組也是對象int[]是引用類型枚舉注解特點(diǎn)變量里存對象在堆中的地址比較地址equals()用來比較對象內(nèi)容。2.Object類的equals方法源碼publicbooleanequals(Objectobj){return(thisobj);}可以看到底層默認(rèn)就是用 比較地址但是對于Integer、String這些JDK已經(jīng)定義好的類都重寫了該方法用于比較值。3.JVM的內(nèi)存結(jié)構(gòu)上述提到基本類型在棧區(qū)引用類型在堆區(qū)這里引出了JVM的內(nèi)存結(jié)構(gòu)。運(yùn)行時(shí)數(shù)據(jù)區(qū)域被劃分為 5 個(gè)主要組件3.1方法區(qū) (Method Area)所有類級別數(shù)據(jù)將被存儲在這里包括靜態(tài)變量。每個(gè) JVM 只有一個(gè)方法區(qū)它是一個(gè)共享的資源。eg.被static final修飾的靜態(tài)變量3.2堆區(qū) (Heap Area)所有的對象和它們相應(yīng)的實(shí)例變量以及數(shù)組將被存儲在這里。每個(gè) JVM 同樣只有一個(gè)堆區(qū)。由于方法區(qū)和堆區(qū)的內(nèi)存由多個(gè)線程共享所以存儲的數(shù)據(jù)不是線程安全的。eg.ThreadLocalMap、-128到127緩存的對象實(shí)例3.3棧區(qū) (Stack Area)對每個(gè)線程會單獨(dú)創(chuàng)建一個(gè)運(yùn)行時(shí)棧。對每個(gè)函數(shù)呼叫會在棧內(nèi)存生成一個(gè)棧幀(Stack Frame)。所有的局部變量將在棧內(nèi)存中創(chuàng)建。棧區(qū)是線程安全的因?yàn)樗皇且粋€(gè)共享資源。棧幀被分為三個(gè)子實(shí)體局部變量數(shù)組 - 包含多少個(gè)與方法相關(guān)的局部變量并且相應(yīng)的值將被存儲在這里。操作數(shù)棧 - 如果需要執(zhí)行任何中間操作操作數(shù)棧作為運(yùn)行時(shí)工作區(qū)去執(zhí)行指令。幀數(shù)據(jù) - 方法的所有符號都保存在這里。在任意異常的情況下catch 塊的信息將會被保存在幀數(shù)據(jù)里面。eg.基本類型、局部變量3.4PC 寄存器每個(gè)線程都有一個(gè)單獨(dú)的 PC 寄存器來保存當(dāng)前執(zhí)行指令的地址一旦該指令被執(zhí)行pc 寄存器會被更新至下條指令的地址。3.5本地方法棧本地方法棧保存本地方法信息。對每一個(gè)線程將創(chuàng)建一個(gè)單獨(dú)的本地方法棧。4.JVM 的 GC 垃圾回收機(jī)制上述提到JVM的內(nèi)存結(jié)構(gòu)這就不得不引出JVM的GC機(jī)制。JVM的垃圾回收Garbage Collection機(jī)制是自動管理內(nèi)存的一種機(jī)制它可以識別和回收不再使用的對象釋放其占用的內(nèi)存空間。以下是垃圾回收機(jī)制的介紹以及一些常見的垃圾回收算法4.1垃圾回收機(jī)制介紹垃圾回收器負(fù)責(zé)自動檢測和回收不再使用的對象。它通過標(biāo)記-清除、復(fù)制、標(biāo)記-整理等算法來回收垃圾對象。垃圾回收過程包括標(biāo)記、清除、整理和壓縮等階段。4.2常見的垃圾回收算法標(biāo)記-清除算法Mark and Sweep首先標(biāo)記出所有活動對象然后清除未標(biāo)記的對象。復(fù)制算法Copying將可用內(nèi)存分為兩塊每次只使用其中一塊將存活對象復(fù)制到另一塊中然后清除當(dāng)前使用的塊。標(biāo)記-整理算法Mark and Compact標(biāo)記出所有活動對象然后將活動對象向一端移動之后清理邊界外的內(nèi)存。分代收集算法Generational Collection將堆內(nèi)存分為新生代和老年代并使用不同的回收算法。新生代通常使用復(fù)制算法老年代使用標(biāo)記-清除或標(biāo)記-整理算法。4.3默認(rèn)的垃圾回收算法默認(rèn)情況下HotSpot JVM使用分代收集算法。新生代使用復(fù)制算法其中的Eden區(qū)和Survivor區(qū)各占一部分并且采用了對象晉升機(jī)制。老年代使用標(biāo)記-清除或標(biāo)記-整理算法來回收內(nèi)存。最簡回答GC垃圾回收機(jī)制是指Java虛擬機(jī)自動管理內(nèi)存的機(jī)制通過自動識別和回收不再使用的對象釋放對應(yīng)的內(nèi)存資源以避免內(nèi)存泄漏和提高程序性能。5.JVM的調(diào)優(yōu)既然提到JVM不得不引入JVM調(diào)優(yōu)了。一般調(diào)優(yōu)通常優(yōu)先對堆內(nèi)存空間進(jìn)行調(diào)整-Xms表示初始堆內(nèi)存大小(默認(rèn)為物理內(nèi)存的1/64-Xmx表示最大分配對內(nèi)存大小(默認(rèn)為物理內(nèi)存的1/4)舉例物理內(nèi)存4G運(yùn)行JAR包時(shí)可指定堆內(nèi)存參數(shù)java-Xmx3.2g-Xms1g-jarxxx.jar6.包裝類緩存在 java.lang.Integer 類中有一個(gè)靜態(tài)內(nèi)部類叫做 IntegerCache。當(dāng)通過自動裝箱Autoboxing或者調(diào)用 Integer.valueOf(int) 創(chuàng)建對象時(shí)如果數(shù)值在 -128 到 127 之間這是默認(rèn)范圍JVM 不會去堆Heap中創(chuàng)建新的對象而是直接返回 IntegerCache 中預(yù)先初始化好的數(shù)組里的對象實(shí)例。Integera127;Integerb127;System.out.println(ab);// true因?yàn)槭峭粋€(gè)緩存對象Integerc128;Integerd128;System.out.println(cd);// false超出了緩存范圍是兩個(gè)不同的new出來的對象IntegerenewInteger(127);Integerf127;System.out.println(ef);// falsenew出來的對象在堆中不走緩存7.自動裝箱/拆箱7.1自動裝箱基本類型 → 包裝類把基本類型賦值給包裝類引用變量編譯器自動調(diào)用Integer.valueOf()// 自動裝箱Integera10;// 編譯器實(shí)際翻譯為IntegeraInteger.valueOf(10);7.2自動拆箱包裝類 → 基本類型包裝類對象賦值給基本類型變量編譯器自動調(diào)用.intValue()// 自動拆箱Integerb20;intnumb;// 編譯器實(shí)際翻譯為intnumb.intValue();包裝類做算術(shù)運(yùn)算 - * /時(shí)會先自動拆箱成對應(yīng)的基本類型再做計(jì)算。Integerx1;Integery2;Integerz3;System.out.println(zxy);// true其他包裝類同理Double ? double、Boolean ? boolean 等