被面試官問(wèn)臭了的jvm性能優(yōu)化你還不知道峭火?建議收藏!

一 智嚷、JVM性能優(yōu)化專題

1卖丸、Java類加載過(guò)程

Java 類加載需要經(jīng)歷一下7 個(gè)過(guò)程:

1.1 . 加載

加載是類加載的第一個(gè)過(guò)程,在這個(gè)階段,將完成一下三件事情:

  • 通過(guò)一個(gè)類的全限定名獲取該類的二進(jìn)制流。
  • 將該二進(jìn)制流中的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法去運(yùn)行時(shí)數(shù)據(jù)結(jié) 構(gòu)盏道。
  • 在內(nèi)存中生成該類的Class對(duì)象,作為該類的數(shù)據(jù)訪問(wèn)入口稍浆。

1.2 . 驗(yàn)證

驗(yàn)證的目的是為了確保Class,文件的字節(jié)流中的信息不回危害到虛擬機(jī).在該階段主要完成以下四鐘驗(yàn)證:

  • 文件格式驗(yàn)證:驗(yàn)證字節(jié)流是否符合文件的規(guī)范,如主次版本號(hào) 是否在當(dāng)前虛擬機(jī)范圍內(nèi),常量池中的常量是否有不被支持的類型.
  • 元數(shù)據(jù)驗(yàn)證:對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析,如這個(gè)類是否有父類, 是否集成了不被繼承的類等。
  • 字節(jié)碼驗(yàn)證:是整個(gè)驗(yàn)證過(guò)程中最復(fù)雜的一個(gè)階段,通過(guò)驗(yàn)證數(shù)據(jù)流和 控制流的分析,確定程序語(yǔ)義是否正確,主要針對(duì)方法體的驗(yàn)證猜嘱。如:方 法中的類型轉(zhuǎn)換是否正確,跳轉(zhuǎn)指令是否正確等衅枫。
  • 符號(hào)引用驗(yàn)證:這個(gè)動(dòng)作在后面的解析過(guò)程中發(fā)生,主要是為了確保解析動(dòng)作能正確執(zhí)行。

1.3 . 準(zhǔn)備

準(zhǔn)備階段是為類的靜態(tài)變量分配內(nèi)存并將其初始化為默認(rèn)值,這些內(nèi)存都將在方法區(qū)中進(jìn)行分配朗伶。準(zhǔn)備階段不分配類中的實(shí)例變量的內(nèi)存,實(shí)例變量將會(huì)在對(duì)象實(shí)例化時(shí)隨著對(duì)象一起分配在Java 堆中弦撩。

 public static int value=123;//在準(zhǔn)備階段value初始值為0 。在初始化階段才會(huì)變?yōu)?23 论皆。

1.4 . 解析

該階段主要完成符號(hào)引用到直接引用的轉(zhuǎn)換動(dòng)作益楼。解析動(dòng)作并不一定在初 始化動(dòng)作完成之前,也有可能在初始化之后。

1.5 . 初始化

初始化時(shí)類加載的最后一步,前面的類加載過(guò)程,除了在加載階段用戶應(yīng)用程序可以通過(guò)自定義類加載器參與之外,其余動(dòng)作完全由虛擬機(jī)主導(dǎo)和控制点晴。到了初始化階段,才真正開(kāi)始執(zhí)行類中的定義的java程序代碼感凤。

1.6. 使用

1.7. 卸載

2、java內(nèi)存分配

  • 寄存器:我們無(wú)法控制粒督。
  • 靜態(tài)域:static定義的靜態(tài)成員陪竿。
  • 常量池:編譯時(shí)被確定并保存在.class文件中的(final)常量值和一些文本修飾的符號(hào)引用(類和接口的全限定名,字段的名稱和描述符, 方法和名稱和描述符)。
  • 非RAM存儲(chǔ):硬盤(pán)等永久存儲(chǔ)空間屠橄。
  • 堆內(nèi)存:new 創(chuàng)建的對(duì)象和數(shù)組,由Java 虛擬機(jī)自動(dòng)垃圾回收器管理, 存取速度慢族跛。
  • 棧內(nèi)存:基本類型的變量和對(duì)象的引用變量(堆內(nèi)存空間的訪問(wèn)地址),速度快,可以共享,但是大小與生存期必須確定,缺乏靈活性。

2.1.Java 堆的結(jié)構(gòu)是什么樣子的2什么是堆中的永久代?

JVM的堆是運(yùn)行時(shí)數(shù)據(jù)區(qū),所有類的實(shí)例和數(shù)組都是在堆上分配內(nèi)存锐墙。它
在JVM啟動(dòng)的時(shí)候被創(chuàng)建庸蔼。對(duì)象所占的堆內(nèi)存是由自動(dòng)內(nèi)存管理系統(tǒng)也就
是垃圾收集器回收。
堆內(nèi)存是由存活和死亡的對(duì)象組成的贮匕。存活的對(duì)象是應(yīng)用可以訪問(wèn)的,不會(huì)被垃圾回收。死亡的對(duì)象是應(yīng)用不可訪問(wèn)尚且還沒(méi)有被垃圾收集器回收 掉的對(duì)象花枫。一直到垃圾收集器把這些對(duì)象回收掉之前,他們會(huì)一直占據(jù)堆內(nèi)存空間刻盐。

3、描述一下JVM加載Class文件的原理機(jī)制2

Java 語(yǔ)言是一種具有動(dòng)態(tài)性的解釋型語(yǔ)言,類(Class)只有被加載到JVM 后才能運(yùn)行劳翰。當(dāng)運(yùn)行指定程序時(shí),JVM 會(huì)將編譯生成的 .class
文件按照需求和一定的規(guī)則加載到內(nèi)存中,并組織成為一個(gè)完整的Java 應(yīng)用程序敦锌。這個(gè)加載過(guò)程是由類加載器完成,具體來(lái)說(shuō),就是由 ClassLoader 和它的子類來(lái)實(shí)現(xiàn)的。類加載器本身也是一個(gè)類,其實(shí)質(zhì)是把類文件從硬盤(pán)讀取到內(nèi)存中佳簸。
類的加載方式分為隱式加載和顯示加載乙墙。隱式加載指的是程序在使用new 等方式創(chuàng)建對(duì)象時(shí),會(huì)隱式地調(diào)用類的加載器把對(duì)應(yīng)的類加載到JVM 中颖变。顯示加載指的是通過(guò)直接調(diào)用class.forName() 方法來(lái)把所需的類加載到JVM 中。

任何一個(gè)工程項(xiàng)目都是由許多類組成的,當(dāng)程序啟動(dòng)時(shí),只把需要的類加 載到JVM 中,其他類只有被使用到的時(shí)候才會(huì)被加載,采用這種方法一方面可以加快加載速度,另一方面可以節(jié)約程序運(yùn)行時(shí)對(duì)內(nèi)存的開(kāi)銷(xiāo)听想。此外,在Java 語(yǔ)言中,每個(gè)類或接口都對(duì)應(yīng)一個(gè) 文件.class,這些文件可以被看成是一個(gè)個(gè)可以被動(dòng)態(tài)加載的單元,因此當(dāng)只有部分類被修改 時(shí),只需要重新編譯變化的類即可,而不需要重新編譯所有文件,因此加 快了編譯速度腥刹。
在Java 語(yǔ)言中,類的加載是動(dòng)態(tài)的,它并不會(huì)一次性將所有類全部加載后再運(yùn)行,而是保證程序運(yùn)行的基礎(chǔ)類(例如基類)完全加載到JVM 中,至于其他類,則在需要的時(shí)候才加載。
類加載的主要步驟:

  • 裝載汉买。根據(jù)查找路徑找到相應(yīng)的class 文件,然后導(dǎo)入衔峰。
  • 鏈接。鏈接又可分為3 個(gè)小步:
  • 檢查,檢查待加載的class 文件的正確性蛙粘。
  • 準(zhǔn)備,給類中的靜態(tài)變量分配存儲(chǔ)空間垫卤。
  • 解析,將符號(hào)引用轉(zhuǎn)換為直接引用(這一步可選)
  • 初始化。對(duì)靜態(tài)變量和靜態(tài)代碼塊執(zhí)行初始化工作出牧。

4穴肘、GC 是什么? 為什么要有 GC?

GC 是垃圾收集的意思(GabageCollection),內(nèi)存處理是編程 人員容易出現(xiàn)問(wèn)題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或 系統(tǒng)的不穩(wěn)定甚至崩潰,Java 提供的 GC 功能可以自動(dòng)監(jiān)測(cè)對(duì)象 是否超過(guò)作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java 語(yǔ)言沒(méi)有提 供釋放已分配內(nèi)存的顯示操作方法。

5舔痕、簡(jiǎn)述 Java 垃圾回收機(jī)制)

在 Java 中,程序員是不需要顯示的去釋放一個(gè)對(duì)象的內(nèi)存的,而 是由虛擬機(jī)自行執(zhí)行评抚。在 JVM 中,有一個(gè)垃圾回收線程,它是低 優(yōu)先級(jí)的,在正常情況下是不會(huì)執(zhí)行的,只有在虛擬機(jī)空閑或者當(dāng) 前堆內(nèi)存不足時(shí),才會(huì)觸發(fā)執(zhí)行,掃面那些沒(méi)有被任何引用的對(duì)象, 并將它們添加到要回收的集合中,進(jìn)行回收。

6赵讯、 如何判斷一個(gè)對(duì)象是否存活?(或者 GC 對(duì)象的判定方法)

判斷一個(gè)對(duì)象是否存活有兩種方法:

6.1 . 引用計(jì)數(shù)法

所謂引用計(jì)數(shù)法就是給每一個(gè)對(duì)象設(shè)置一個(gè)引用計(jì)數(shù)器,每當(dāng)有一 個(gè)地方引用這個(gè)對(duì)象時(shí),就將計(jì)數(shù)器加一,引用失效時(shí),計(jì)數(shù)器就 減一盈咳。當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)器為零時(shí),說(shuō)明此對(duì)象沒(méi)有被引用, 也就是“死對(duì)象”,將會(huì)被垃圾回收.
引用計(jì)數(shù)法有一個(gè)缺陷就是無(wú)法解決循環(huán)引用問(wèn)題,也就是說(shuō)當(dāng)對(duì) 象 A 引用對(duì)象 B,對(duì)象 B 又引用者對(duì)象 A,那么此時(shí) A、B 對(duì) 象的引用計(jì)數(shù)器都不為零,也就造成無(wú)法完成垃圾回收,所以主流 的虛擬機(jī)都沒(méi)有采用這種算法边翼。

6.2 . 可達(dá)性算法(引用鏈法)

該算法的思想是:從一個(gè)被稱為 GC Roots 的對(duì)象開(kāi)始向下搜索, 如果一個(gè)對(duì)象到 GC Roots 沒(méi)有任何引用鏈相連時(shí),則說(shuō)明此對(duì) 象不可用鱼响。在 Java 中可以作為 GC Roots 的對(duì)象有以下幾種:

  • 虛擬機(jī)棧中引用的對(duì)象
  • 方法區(qū)類靜態(tài)屬性引用的對(duì)象 ? 方法區(qū)常量池引用的對(duì)象
  • 本地方法棧 JNI 引用的對(duì)象
    雖然這些算法可以判定一個(gè)對(duì)象是否能被回收,但是當(dāng)滿足上述條 件時(shí), 一個(gè)對(duì)象比不一定會(huì)被回收。當(dāng)一個(gè)對(duì)象不可達(dá) GC Root 時(shí),這個(gè)對(duì)象并不會(huì)立馬被回收,而是出于一個(gè)死緩的階段,若要 被真正的回收需要經(jīng)歷兩次標(biāo)記.
    如果對(duì)象在可達(dá)性分析中沒(méi)有與 GC Root 的引用鏈,那么此時(shí)就 會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是是否有必要執(zhí)行finalize()方法组底。當(dāng)對(duì)象沒(méi)有覆蓋 finalize() 方法或者已被虛擬機(jī)調(diào)用過(guò),那么就認(rèn)為是沒(méi)必要的丈积。 如果該對(duì)象有必要執(zhí)行finalize()方法,那么這個(gè)對(duì)象將會(huì)放在一個(gè)稱為 F-Queue 的對(duì) 隊(duì)列中,虛擬機(jī)會(huì)
    觸發(fā)一個(gè)Finalize()線程去執(zhí)行,此線程是低 優(yōu)先級(jí)的,并且虛擬機(jī)不會(huì)承諾一直等待它運(yùn)行完,這是因?yàn)槿绻?finalize() 執(zhí)行緩慢或者發(fā)生了死鎖,那么就會(huì)造成 F-Queue 隊(duì)列一直等待,造成了內(nèi)存回收系統(tǒng)的崩潰。GC 對(duì)處于 F-Queue 中的對(duì)象進(jìn)行第二次被標(biāo)記,這時(shí),該對(duì)象將被移除” 即將回收” 集合,等待回收债鸡。

7江滨、垃圾回收的優(yōu)點(diǎn)和原理)并考慮 2 種回收機(jī)制)

Java 語(yǔ)言中一個(gè)顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使 C++ 程序員最頭疼的內(nèi)存管理的問(wèn)題迎刃而解,它使得 Java 程序員在 編寫(xiě)程序的時(shí)候不再需要考慮內(nèi)存管理。由于有個(gè)垃圾回收機(jī)制, Java 中的對(duì)象不再有“作用域”的概念,只有對(duì)象的引用才有"作用域"厌均。垃圾回收可以有效的 防止內(nèi)存泄露,有效的使用可以使 用的內(nèi)存唬滑。垃圾回收器通常是作為一個(gè)單獨(dú)的低級(jí)別的線程運(yùn)行, 不可預(yù)知的情況下對(duì)內(nèi)存堆中已經(jīng)死亡的或者長(zhǎng)時(shí)間沒(méi)有使用的 對(duì)象進(jìn)行清楚和回收,程序員不能實(shí)時(shí)的調(diào)用垃圾回收器對(duì)某個(gè)對(duì) 象或所有對(duì)象進(jìn)行垃圾回收。
回收機(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收棺弊。

8晶密、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內(nèi)存嗎?有什么辦法主動(dòng)通知虛擬機(jī)進(jìn)行垃圾回收?

對(duì)于 GC 來(lái)說(shuō),當(dāng)程序員創(chuàng)建對(duì)象時(shí),GC 就開(kāi)始監(jiān)控這個(gè)對(duì)象 的地址、大小以及使用情況模她。通常,GC 采用有向圖的方式記錄和 管理堆(heap)中的所有對(duì)象稻艰。通過(guò)這種方式確定哪些對(duì)象是” 可達(dá)的”,哪些對(duì)象是”不可達(dá)的”。當(dāng) GC 確定一些對(duì)象為“不 可達(dá)”時(shí),GC 就有責(zé)任回收這些內(nèi)存空間侈净∽鹞穑可以僧凤。程序員可以手動(dòng)執(zhí)行System.gc(),通知 GC 運(yùn)行,但是Java 語(yǔ)言規(guī)范并不 保證 GC 一定會(huì)執(zhí)行。

9元扔、Java 中會(huì)存在內(nèi)存泄漏嗎?請(qǐng)簡(jiǎn)單描述)

所謂內(nèi)存泄露就是指一個(gè)不再被程序使用的對(duì)象或變量一直被占 據(jù)在內(nèi)存中躯保。Java 中有垃圾回收機(jī)制,它可以保證一對(duì)象不再被 引用的時(shí)候,即對(duì)象變成了孤兒的時(shí)候,對(duì)象將自動(dòng)被垃圾回收器 從內(nèi)存中清除掉。由于Java 使用有向圖的方式進(jìn)行垃圾回收管理, 可以消除引用循環(huán)的問(wèn)題, 例如有兩個(gè)對(duì)象,相互引用,只要它們 和根進(jìn)程不可達(dá)的,那么 GC 也是可以回收它們的,例如下面的 代碼可以看到這種情況的內(nèi)存回收:

*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub try { gcTest();
} catch (IOException e) {
// TODO Auto-generated catch block e.printStackTrace();
}
System.out.println("has exited gcTest!"); System.in.read();
System.in.read(); System.out.println("out begin gc!"); for(int i=0;i<100;i++)
{
System.gc(); System.in.read(); System.in.read(); }
}
private static void gcTest() throws IOException { System.in.read();
System.in.read();
Person p1 = new Person(); System.in.read(); System.in.read();
Person p2 = new Person(); p1.setMate(p2); p2.setMate(p1);
System.out.println("before exit gctest!"); System.in.read(); System.in.read();
System.gc(); System.out.println("exit gctest!");
}
private static class Person {
byte[] data = new byte[20000000]; Person mate = null; public void setMate(Person other) {
mate = other;
}
}
}

Java 中的內(nèi)存泄露的情況:長(zhǎng)生命周期的對(duì)象持有短生命周期對(duì) 象的引用就很可能發(fā)生內(nèi)存泄露,盡管短生命周期對(duì)象已經(jīng)不再需 要,但是因?yàn)殚L(zhǎng)生命周期對(duì)象持有它的引用而導(dǎo)致不能被回收,這 就是 Java 中內(nèi)存泄露的發(fā)生場(chǎng)景,通俗地說(shuō),就是程序員可能創(chuàng) 建了一個(gè)對(duì)象,以后一直不再使用這個(gè)對(duì)象,這個(gè)對(duì)象卻一直被引 用,即這個(gè)對(duì)象無(wú)用但是卻無(wú)法被垃圾回收器回收的,這就是 java 中可能出現(xiàn)內(nèi)存泄露的情況,例如,緩存系統(tǒng),我們加載了一個(gè)對(duì) 象放在緩存中 (例如放在一個(gè)全局 map 對(duì)象中),然后一直不再 使用它,這個(gè)對(duì)象一直被緩存引用,但卻不再被使用摇展。
檢查 Java 中的內(nèi)存泄露,一定要讓程序?qū)⒏鞣N分支情況都完整執(zhí) 行到程序結(jié)束,然后看某個(gè)對(duì)象是否被使用過(guò),如果沒(méi)有,則才能 判定這個(gè)對(duì)象屬于內(nèi)存泄露吻氧。
如果一個(gè)外部類的實(shí)例對(duì)象的方法返回了一個(gè)內(nèi)部類的實(shí)例對(duì)象, 這個(gè)內(nèi)部類對(duì)象被長(zhǎng)期引用了,即使那個(gè)外部類實(shí)例對(duì)象不再被使 用,但由于內(nèi)部類持久外部類的實(shí)例對(duì)象,這個(gè)外部類對(duì)象將不會(huì) 被垃圾回收,這也會(huì)造成內(nèi)存泄露。
下面內(nèi)容來(lái)自于網(wǎng)上(主要特點(diǎn)就是清空堆棧中的某個(gè)元素,并不 是徹底把它從數(shù)組中拿掉,而是把存儲(chǔ)的總數(shù)減少,本人寫(xiě)得可以 比這個(gè)好,在拿掉某個(gè)元素時(shí),順便也讓它從數(shù)組中消失,將那個(gè) 元素所在的位置的值設(shè)置為 null 即可):
我實(shí)在想不到比那個(gè)堆棧更經(jīng)典的例子了,以致于我還要引用別人 的例子,下面的例子不是我想到的,是書(shū)上看到的,當(dāng)然如果沒(méi)有 在書(shū)上看到,可能過(guò)一段時(shí)間我自己也想的到,可是那時(shí)我說(shuō)是我 自己想到的也沒(méi)有人相信的咏连。

public class Stack {
private Object[] elements=new Object[10]; private int size = 0
;
public void push(Object e){ ensureCapacity(); elements[size++] = e;
}
public Object pop(){
if( size == 0) throw new EmptyStackException(); return element

 s[--size];
}
private void ensureCapacity(){ if(elements.length == size){ Object[] oldElements = elements;
elements = new Object[2 * elements.length+1]; System.arraycopy (oldElements,0, elements, 0,
size);
}
}
}

上面的原理應(yīng)該很簡(jiǎn)單,假如堆棧加了 10 個(gè)元素,然后全部彈 出來(lái),雖然堆棧是空的,沒(méi)有我們要的東西,但是這是個(gè)對(duì)象是無(wú) 法回收的,這個(gè)才符合了內(nèi)存泄露的兩個(gè)條件:無(wú)用,無(wú)法回收盯孙。 但是就是存在這樣的東西也不一定會(huì)導(dǎo)致什么樣的后果,如果這個(gè) 堆棧用的比較少,也就浪費(fèi)了幾個(gè) K 內(nèi)存而已,反正我們的內(nèi)存都 上 G 了,哪里會(huì)有什么影響,再說(shuō)這個(gè)東西很快就會(huì)被回收的, 有什么關(guān)系。下面看兩個(gè)例子祟滴。

public class Bad{
public static Stack s=Stack(); static{ s.push(new Object());
s.pop(); //這里有—個(gè)對(duì)象發(fā)生內(nèi)存泄露
s.push(new Object()); //上面的對(duì)象可以被回收了,等于是自 愈了
}
}

因?yàn)槭?static,就一直存在到程序退出,但是我們也可以看到它有 自愈功能,就是說(shuō)如果你的 Stack 最多有 100 個(gè)對(duì)象,那么最 多也就只有 100 個(gè)對(duì)象無(wú)法被回收其實(shí)這個(gè)應(yīng)該很容易理解, Stack 內(nèi)部持有 100 個(gè)引用,最壞的情況就是他們都是無(wú)用的, 因?yàn)槲覀円坏┓判碌倪M(jìn)取,以前的引用自然消失!
內(nèi)存泄露的另外一種情況:當(dāng)一個(gè)對(duì)象被存儲(chǔ)進(jìn) HashSet 集合中 以后,就不能修改這個(gè)對(duì)象中的那些參與計(jì)算哈希值的字段了,否 則,對(duì)象修改后的哈希值與最初存儲(chǔ)進(jìn) HashSet 集合中時(shí)的哈希 值就不同了,在這種情況下,即使在 contains 方法使用該對(duì)象的 當(dāng)前引用作為的參數(shù)去 HashSet 集合中檢索對(duì)象,也將返回找不 到對(duì)象的結(jié)果,這也會(huì)導(dǎo)致無(wú)法從 HashSet 集合中單獨(dú)刪除當(dāng)前 對(duì)象,造成內(nèi)存泄露振惰。

10、深拷貝和淺拷貝)

簡(jiǎn)單來(lái)講就是復(fù)制垄懂、克隆骑晶。

Person p=new Person(“張三”);

淺拷貝就是對(duì)對(duì)象中的數(shù)據(jù)成員進(jìn)行簡(jiǎn)單賦值,如果存在動(dòng)態(tài)成員或者指針就會(huì)報(bào)錯(cuò)。
深拷貝就是對(duì)對(duì)象中存在的動(dòng)態(tài)成員或指針重新開(kāi)辟內(nèi)存空間草慧。

11桶蛔、System.gc() 和 Runtime.gc() 會(huì)做什么事情?

這兩個(gè)方法用來(lái)提示 JVM 要進(jìn)行垃圾回收。但是,立即開(kāi)始還是 延遲進(jìn)行垃圾回收是取決于 JVM 的漫谷。

12仔雷、finalize() 方法什么時(shí)候被調(diào)用?析構(gòu)函數(shù) (finalization) 的 目的是什么?

垃圾回收器(garbage colector)決定回收某對(duì)象時(shí),就會(huì)運(yùn)行該 對(duì)象的finalize() 方法 但是在 Java 中很不幸,如果內(nèi)存總是充 足的,那么垃圾回收可能永遠(yuǎn)不會(huì)進(jìn)行,也就是說(shuō) filalize() 可能 永遠(yuǎn)不被執(zhí)行,顯然指望它做收尾工作是靠不住的。 那么 finalize() 究竟是做什么的呢? 它最主要的用途是回收特殊渠道 申請(qǐng)的內(nèi)存舔示。Java 程序有垃圾回收器,所以一般情況下內(nèi)存問(wèn)題 不用程序員操心碟婆。但有一種 JNI(Java Native Interface)調(diào)用non-Java 程序(C 或 C++), finalize() 的工作就是回收這部 分的內(nèi)存。

13惕稻、如果對(duì)象的引用被置為 null?垃圾收集器是否會(huì)立即釋放對(duì)象占 用的內(nèi)存?

不會(huì),在下一個(gè)垃圾回收周期中,這個(gè)對(duì)象將是可被回收的竖共。

14、什么是分布式垃圾回收(DGC)?它是如何工作的?

DGC 叫做分布式垃圾回收俺祠。RMI 使用 DGC 來(lái)做自動(dòng)垃圾回收公给。 因?yàn)?RMI 包含了跨虛擬機(jī)的遠(yuǎn)程對(duì)象的引用,垃圾回收是很困難 的。DGC 使用引用計(jì)數(shù)算法來(lái)給遠(yuǎn)程對(duì)象提供自動(dòng)內(nèi)存管理蜘渣。

15妓布、串行(serial)收集器和吞吐量(throughput)收集器的區(qū)別 是什么?

吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等規(guī)模 和大規(guī)模數(shù)據(jù)的應(yīng)用程序。 而串行收集器對(duì)大多數(shù)的小應(yīng)用(在 現(xiàn)代處理器上需要大概 100M 左右的內(nèi)存)就足夠了宋梧。

16、在 Java 中?對(duì)象什么時(shí)候可以被垃圾回收?

當(dāng)對(duì)象對(duì)當(dāng)前使用這個(gè)對(duì)象的應(yīng)用程序變得不可觸及的時(shí)候,這個(gè) 對(duì)象就可以被回收了狰挡。

17捂龄、簡(jiǎn)述 Java 內(nèi)存分配與回收策率以及 Minor GC 和 Major GC)

  • 對(duì)象優(yōu)先在堆的 Eden 區(qū)分配
  • 大對(duì)象直接進(jìn)入老年代
  • 長(zhǎng)期存活的對(duì)象將直接進(jìn)入老年代
    當(dāng) Eden 區(qū)沒(méi)有足夠的空間進(jìn)行分配時(shí),虛擬機(jī)會(huì)執(zhí)行一次 Minor GC释涛。Minor GC 通常發(fā)生在新生代的 Eden 區(qū),在這個(gè)區(qū) 的對(duì)象生存期短,往往發(fā)生 Gc 的頻率較高,回收速度比較快; Full GC/Major GC 發(fā)生在老年代,一般情況下,觸發(fā)老年代 GC 的時(shí)候不會(huì)觸發(fā) Minor GC,但是通過(guò)配置,可以在 Full GC 之 前進(jìn)行一次 Minor GC 這樣可以加快老年代的回收速度。

18倦沧、JVM 的永久代中會(huì)發(fā)生垃圾回收么?

垃圾回收不會(huì)發(fā)生在永久代,如果永久代滿了或者是超過(guò)了臨界值, 會(huì)觸發(fā)完全垃圾回收(Full GC)唇撬。
注: Java 8 中已經(jīng)移除了永久代,新加了一個(gè)叫做元數(shù)據(jù)區(qū)的 native 內(nèi)存
區(qū)。

19展融、Java 中垃圾收集的方法有哪些?

標(biāo)記 - 清除:這是垃圾收集算法中最基礎(chǔ)的,根據(jù)名字就可以知 道,它的 思想就是標(biāo)記哪些要被回收的對(duì)象,然后統(tǒng)一回收窖认。這種 方法很簡(jiǎn)單,但是會(huì)有兩個(gè)主要問(wèn)題:

  1. 效率不高,標(biāo)記和清除的效率都很低;
  2. 會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導(dǎo)致以后程序在分配較大的對(duì)象時(shí),由于沒(méi)有充足的連續(xù)內(nèi)存而提前觸發(fā)一次 GC 動(dòng)作。
    復(fù)制算法:為了解決效率問(wèn)題,復(fù)制算法將可用內(nèi)存按容量劃分為相等的兩部分,然后每次只使用其中的一塊,當(dāng)一塊內(nèi)存用完時(shí),就將還存活的對(duì) 象復(fù)制到第二塊內(nèi)存上,然后一次性清楚完第一塊內(nèi)存,再將第二塊上的 對(duì)象復(fù)制到第一塊告希。但是這種方式,內(nèi)存的代價(jià)太高,每次基本上都要浪 費(fèi)一般的內(nèi)存扑浸。
    于是將該算法進(jìn)行了改進(jìn),內(nèi)存區(qū)域不再是按照 1:1 去劃分,而 是將內(nèi)存劃分為 8:1:1 三部分,較大那份內(nèi)存交 Eden 區(qū),其余 是兩塊較小的內(nèi)存區(qū)叫 Survior 區(qū)。每次都會(huì)優(yōu)先使用 Eden 區(qū), 若 Eden 區(qū)滿,就將對(duì)象復(fù)制到第二塊內(nèi)存區(qū)上,然后清除 Eden 區(qū),如果此時(shí)存活的對(duì)象太多,以至于 Survivor 不夠時(shí),會(huì)將這 些對(duì)象通過(guò)分配擔(dān)保機(jī)制復(fù)制到老年代中燕偶。(java 堆又分為新生代和老年代)
    標(biāo)記 - 整理:該算法主要是為了解決標(biāo)記 - 清除,產(chǎn)生大量?jī)?nèi)存 碎片的問(wèn)題;當(dāng)對(duì)象存活率較高時(shí),也解決了復(fù)制算法的效率問(wèn)題喝噪。 它的不同之處就是在清除對(duì)象的時(shí)候現(xiàn)將可回收對(duì)象移動(dòng)到一端, 然后清除掉端邊界以外的對(duì)象,這樣就不會(huì)產(chǎn)生內(nèi)存碎片了。
    分代收集:現(xiàn)在的虛擬機(jī)垃圾收集大多采用這種方式,它根據(jù)對(duì)象的生存周期,將堆分為新生代和老年代指么。在新生代中,由于對(duì)象生存期短,每次回 收都會(huì)有大量對(duì)象死去,那么這時(shí)就采用復(fù)制算法酝惧。 老年代里的對(duì)象存活率較高,沒(méi)有額外的空間進(jìn)行分配擔(dān)保。

20伯诬、什么是類加載器?類加載器有哪些?

實(shí)現(xiàn)通過(guò)類的權(quán)限定名獲取該類的二進(jìn)制字節(jié)流的代碼塊叫做類加載器晚唇。 主要有一下四種類加載器:

  • 啟動(dòng)類加載器(BootstrapClassLoader)用來(lái)加載Java核 心類庫(kù),無(wú)法被
    Java 程序直接引用。
  • 擴(kuò)展類加載器(extensions class loader):它用來(lái)加載 Java 的擴(kuò)展庫(kù)盗似。Java 虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄哩陕。該類 加載器在此目錄里面查找并加載 Java 類。
  • 系統(tǒng)類加載器(system class loader):它根據(jù) Java 應(yīng)用 的類路徑(CLASSPATH)來(lái)加載 Java 類桥言。一般來(lái)說(shuō),Java 應(yīng)用的類都是由它來(lái)完成加載的萌踱。可以通過(guò) ClassLoader.getSystemClassLoader() 來(lái)獲取它号阿。
  • 用戶自定義類加載器,通過(guò)繼承 java.lang.ClassLoader 類 的方式實(shí)現(xiàn)并鸵。

21、類加載器雙親委派模型機(jī)制?

當(dāng)一個(gè)類收到了類加載請(qǐng)求時(shí),不會(huì)自己先去加載這個(gè)類,而是將其委派給父類,由父類去加載,如果此時(shí)父類不能加載,反饋給子類,由子類去完成類的加載扔涧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末园担,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子枯夜,更是在濱河造成了極大的恐慌弯汰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件湖雹,死亡現(xiàn)場(chǎng)離奇詭異咏闪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)摔吏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)鸽嫂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纵装,“玉大人,你說(shuō)我怎么就攤上這事据某∠鹇Γ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵癣籽,是天一觀的道長(zhǎng)挽唉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)筷狼,這世上最難降的妖魔是什么瓶籽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桑逝,結(jié)果婚禮上棘劣,老公的妹妹穿的比我還像新娘。我一直安慰自己楞遏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布预鬓。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼酸役。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼勺届,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼养泡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起杖挣,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肩榕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體株汉,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筐乳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乔妈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝙云。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唆鸡,死狀恐怖帝牡,靈堂內(nèi)的尸體忽然破棺而出源武,到底是詐尸還是另有隱情复凳,我是刑警寧澤姆怪,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布声邦,位于F島的核電站邀泉,受9級(jí)特大地震影響买窟,放射性物質(zhì)發(fā)生泄漏唯灵。R本人自食惡果不足惜贾铝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埠帕。 院中可真熱鬧垢揩,春花似錦、人聲如沸搞监。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)琐驴。三九已至俘种,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绝淡,已是汗流浹背宙刘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牢酵,地道東北人悬包。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像馍乙,于是被迫代替她去往敵國(guó)和親布近。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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