大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

面試題首頁 > JVM面試題

JVM面試題

001JDK、JRE、JVM關(guān)系?

JDK (Java Development Kit) : java語言的軟件開發(fā)包。包括Java運(yùn)行時(shí)環(huán)境JRE。
JRE (Java Runtime Environment) :Java運(yùn)行時(shí)環(huán)境,包括JVM。
JVM (Java Virtual Machine) :一種用于計(jì)算機(jī)設(shè)備的規(guī)范。
Java語言在不同平臺(tái)上運(yùn)行時(shí)不需要重新編譯。Java語言使用Java虛擬機(jī)屏蔽了與具體平臺(tái)相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺(tái)上不加修改地運(yùn)行。

002什么是類加載器,類加載器有哪些?

實(shí)現(xiàn)通過類的權(quán)限定名獲取該類的二進(jìn)制字節(jié)流的代碼塊叫做類加載器。
啟動(dòng)類加載器(Bootstrap ClassLoader)用來加載 java 核心類庫(kù),無法被 java 程序直接引用。
擴(kuò)展類加載器(extensions class loader):它用來加載 Java 的擴(kuò)展庫(kù)。Java虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄。該類加載器在此目錄里面查找并加載 Java 類。
系統(tǒng)類加載器(system class loader):它根據(jù) Java 應(yīng)用的類路徑(CLASSPATH) 來加載 Java類。一般來說,Java應(yīng)用的類都是由它來完成加載的??梢酝ㄟ^ClassLoader.getSystemClassLoader()來獲取它。
用戶自定義類加載器,通過繼承 java.lang.ClassLoader 類的方式實(shí)現(xiàn)。

003ClassLoader如何工作的?

ClassLoader 顧名思義就是類加載器。Java源代碼首先被jvm編譯成.class文件。類從被加載到虛擬機(jī)內(nèi)存中開始,直到卸載出內(nèi)存為止,它的整個(gè)生命周期包括了:加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用和卸載這7個(gè)階段。其中,驗(yàn)證、準(zhǔn)備和解析這三個(gè)部分統(tǒng)稱為連接(linking)。
加載:通過一個(gè)類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流,將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中生成一個(gè)代表這個(gè)類的Class對(duì)象,作為方法去這個(gè)類的各種數(shù)據(jù)的訪問入口;
驗(yàn)證:驗(yàn)證是連接階段的第一步,這一階段的目的是確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬自身的安全;
準(zhǔn)備:準(zhǔn)備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段,這些變量所使用的內(nèi)存都將在方法去中進(jìn)行分配。這時(shí)候進(jìn)行內(nèi)存分配的僅包括類變量(static),而不包括實(shí)例變量,實(shí)例變量將會(huì)在對(duì)象實(shí)例化時(shí)隨著對(duì)象一起分配在Java堆中。
解析:解析階段是虛擬機(jī)將常量池內(nèi)的符號(hào)(Class文件內(nèi)的符號(hào))引用替換為直接引用(指針)的過程。
初始化:初始化階段是類加載過程的最后一步,開始執(zhí)行類中定義的Java程序代碼(字節(jié)碼)。

004靜態(tài)代碼塊在程序中的執(zhí)行順序?

父類靜態(tài)域——》子類靜態(tài)域——》父類成員初始化——》父類構(gòu)造塊——》父類構(gòu)造方法——》子類成員初始化——》子類構(gòu)造塊——》子類構(gòu)造方法;

005對(duì)象創(chuàng)建的過程?

類加載檢查:虛擬機(jī)遇到一條 new 指令時(shí),首先檢查這個(gè)指令的參數(shù)是否能在常量池中定位到這個(gè)類的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執(zhí)行相應(yīng)的類加載過程。
分配內(nèi)存:在類加載檢查通過后,接下來虛擬機(jī)將為新生對(duì)象分配內(nèi)存。對(duì)象所需的內(nèi)存大小在類加載完成后便可確定,為對(duì)象分配空間的任務(wù)等同于把一塊確定大小的內(nèi)存從 Java 堆中劃分出來。分配方式有 “指針碰撞” 和 “空閑列表” 兩種,選擇那種分配方式由 Java 堆是否規(guī)整決定,而 Java 堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。
初始化零值:內(nèi)存分配完成后,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭),這一步操作保證了對(duì)象的實(shí)例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據(jù)類型所對(duì)應(yīng)的零值。
設(shè)置對(duì)象頭:初始化零值完成之后,虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置,例如這個(gè)對(duì)象是哪個(gè)類的實(shí)例、如何才能找到類的元數(shù)據(jù)信息、對(duì)象的哈希碼、對(duì)象的 GC 分代年齡等信息。 這些信息存放在對(duì)象頭中。 另外,根據(jù)虛擬機(jī)當(dāng)前運(yùn)行狀態(tài)的不同,如是否啟用偏向鎖等,對(duì)象頭會(huì)有不同的設(shè)置方式。
執(zhí)行init方法:在上面工作都完成之后,從虛擬機(jī)的視角來看,一個(gè)新的對(duì)象已經(jīng)產(chǎn)生了,但從 Java 程序的視角來看,對(duì)象創(chuàng)建才剛開始,<init> 方法還沒有執(zhí)行,所有的字段都還為零。所以一般來說,執(zhí)行 new 指令之后會(huì)接著執(zhí)行 <init> 方法,把對(duì)象按照程序員的意愿進(jìn)行初始化,這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來。

006什么是雙親委派機(jī)制?

1.如果一個(gè)類加載器收到了類加載請(qǐng)求,它并不會(huì)自己先加載,而是把這個(gè)請(qǐng)求委托給父類的加載器去執(zhí)行;
2.如果父類加載器還存在其父類加載器,則進(jìn)一步向上委托,依次遞歸,請(qǐng)求最終將到達(dá)頂層的引導(dǎo)類加載器;
3.如果父類加載器可以完成類加載任務(wù),就成功返回,倘若父類加載器無法完成加載任務(wù),子加載器才會(huì)嘗試自己去加載,這就是雙親委派機(jī)制;

007雙親委派機(jī)制的優(yōu)勢(shì)?

避免類的重復(fù)加載,保護(hù)程序安全,防止核心API被隨意篡改。

008如何破壞雙親委派模型?

JNDI(Java Naming and Directory Interface,Java命名和目錄接口)便是最典型的例子。JND需要調(diào)用由獨(dú)立廠商實(shí)現(xiàn)并部署在應(yīng)用程序的ClassPath下的JNDI接口提供者(SPI,Service Provider Interface)的代碼,但啟動(dòng)類加載器不可能“認(rèn)識(shí)”這些代碼那該怎么辦?
為了解決這個(gè)問題,Java設(shè)計(jì)團(tuán)隊(duì)只好引入了一個(gè)不太優(yōu)雅的設(shè)計(jì):線程上下文類加載器(Thread Context ClassLoader)。這個(gè)類加載器可以通過java.lang.Thread類的 setContextClassLoaser()方法進(jìn)行設(shè)置。有了線程上下文類加載器,JNDI服務(wù)使用這個(gè)線程上下文類加載器去加載所需要的SPI代碼,也就是父類加載器請(qǐng)求子類加載器去完成類加載的動(dòng)作,這種行為實(shí)際上就是打通了雙親委派模型的層次結(jié)構(gòu)來逆向使用類加載器,實(shí)際上已經(jīng)違背了雙親委派模型的一般性原則。Java中所有涉及SPI的加載動(dòng)作基本上都采用這種方式,例如JNDI、JDBC、JCE、JAXB和JBI等。
例如JDBC在rt里面定義了這個(gè)SPI,那MySQL有MySQL的JDBC實(shí)現(xiàn),Oracle有Oracle的JDBC實(shí)現(xiàn),反正我java不管你內(nèi)部如何實(shí)現(xiàn)的,反正你們都得統(tǒng)一按我這個(gè)來,這樣我們java開發(fā)者才能容易的調(diào)用數(shù)據(jù)庫(kù)操作。所以因?yàn)檫@樣那就不得不違反這個(gè)約束啊,Bootstrap ClassLoader就得委托子類來加載數(shù)據(jù)庫(kù)廠商們提供的具體實(shí)現(xiàn)。因?yàn)樗氖种荒苊?lt;JAVA_HOME>\lib中,其他的它無能為力,這就違反了自下而上的委托機(jī)制了。

009可不可以自己寫個(gè)String類?

不可以。因?yàn)樵陬惣虞d中,會(huì)根據(jù)雙親委派機(jī)制去尋找當(dāng)前java.lang.String是否已被加載。由于啟動(dòng)類加載器已在啟動(dòng)時(shí)候加載了所以不會(huì)再次加載,因此使用的String是已在java核心類庫(kù)加載過的String,而不是新定義的String。

010什么是字節(jié)碼?

Java源程序.java通過編譯器編譯成字節(jié)碼.class文件,也就是計(jì)算機(jī)可以識(shí)別的二進(jìn)制文件。

011字節(jié)碼文件組成結(jié)構(gòu)是什么?

根據(jù) Java 虛擬機(jī)規(guī)范的規(guī)定,class 文件格式采用一種類似于 C 語言的偽結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù),這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號(hào)數(shù)和表。

無符號(hào)數(shù)屬于基礎(chǔ)數(shù)據(jù)類型,以 u1、u2、u4、u8 來分別代表 1 個(gè)字節(jié)、2 個(gè)字節(jié)、4 個(gè)字節(jié)和 8 個(gè)字節(jié)的無符號(hào)數(shù),無符號(hào)數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或者按照 UTF-8 編碼構(gòu)成的字符串值。
是由多個(gè)無符號(hào)數(shù)或者其他表作為數(shù)據(jù)項(xiàng)構(gòu)成的復(fù)合數(shù)據(jù)結(jié)構(gòu),所有表都習(xí)慣性地以 _info 結(jié)尾。表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù),整個(gè) class 文件本質(zhì)上就是一張表。

012對(duì)象的finalization機(jī)制。

Java語言提供了對(duì)象終止(finalization)機(jī)制來允許開發(fā)人員提供對(duì)象被銷毀之前的自定義處理邏輯。當(dāng)垃圾回收器發(fā)現(xiàn)沒有引用指向一個(gè)對(duì)象,即:垃圾回收此對(duì)象之前,總會(huì)先調(diào)用這個(gè)對(duì)象的finalize()方法,finalize()只會(huì)被調(diào)用一次。finalize() 方法允許在子類中被重寫,用于在對(duì)象被回收時(shí)進(jìn)行資源釋放。通常在這個(gè)方法中進(jìn)行一些資源釋放和清理的工作,比如關(guān)閉文件、套接字和數(shù)據(jù)庫(kù)連接等。

013如何判斷兩個(gè)class對(duì)象是否相同?

在JVM中表示兩個(gè)class對(duì)象是否為同一個(gè)類存在兩個(gè)必要條件:
1)類的完整類名必須一致,包括包名。
2)加載這個(gè)類的ClassLoader(指ClassLoader實(shí)例對(duì)象)必須相同。

014類的主動(dòng)使用有哪些?

主動(dòng)使用,分為七種情況:
1)創(chuàng)建類的實(shí)例
2)訪問某個(gè)類或接口的靜態(tài)變量,或者對(duì)該靜態(tài)變量賦值
3)調(diào)用類的靜態(tài)方法I
4)反射(比如:Class.forName(“com.atguigu.Test”))
5)初始化一個(gè)類的子類
6)Java虛擬機(jī)啟動(dòng)時(shí)被標(biāo)明為啟動(dòng)類的類
7)JDK7開始提供的動(dòng)態(tài)語言支持:java.lang.invoke.MethodHandle實(shí)例的解析結(jié)果REF getStatic、REF putStatic、REF invokeStatic句柄對(duì)應(yīng)的類沒有初始化,則初始化
除了以上七種情況,其他使用Java類的方式都被看作是對(duì)類的被動(dòng)使用,都不會(huì)導(dǎo)致類的初始化。

015深拷貝和淺拷貝區(qū)別?

淺拷貝:只是增加了一個(gè)指針指向已存在的內(nèi)存地址,
深拷貝:是增加了一個(gè)指針并且申請(qǐng)了一個(gè)新的內(nèi)存,使這個(gè)增加的指針指向這個(gè)新的內(nèi)存,使用深拷貝的情況下,釋放內(nèi)存的時(shí)候不會(huì)因?yàn)槌霈F(xiàn)淺拷貝時(shí)釋放同一個(gè)內(nèi)存的錯(cuò)誤。
淺復(fù)制:僅僅是指向被復(fù)制的內(nèi)存地址,如果原地址發(fā)生改變,那么淺復(fù)制出來的對(duì)象也會(huì)相應(yīng)的改變。
深復(fù)制:在計(jì)算機(jī)中開辟一塊新的內(nèi)存地址用于存放復(fù)制的對(duì)象。

016啟動(dòng)程序如何查看加載了哪些類,以及加載順序?

java -XX:+TraceClassLoading 具體類
Java -verbose 具體類

017JDK1.6、JDK1.7、JDK1.8 內(nèi)存模型演變?

JDK1.7相對(duì)于JDK1.6,主要的變化就是將永久代中的字符串常量池移到堆內(nèi)存中,交由堆管理。我們知道堆是JVM內(nèi)存管理的主要區(qū)域,那么將字符串常量池放到堆內(nèi)存中更方便高效的對(duì)字符串常量進(jìn)行管理和垃圾回收。
而JDK1.8相對(duì)于JDK1.7來說,主要區(qū)別有兩點(diǎn),一是將虛擬機(jī)棧和本地方法棧合二為一了,二是移除永久代,增加了元數(shù)據(jù)區(qū),元數(shù)據(jù)區(qū)使用本地內(nèi)存,只受計(jì)算機(jī)內(nèi)存大小的限制。而永久代使用的還是堆內(nèi)存空間,受堆內(nèi)存大小的限制。

018什么是程序計(jì)數(shù)器?

記錄正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址。為了線程切換后能恢復(fù)到正確的位置,每個(gè)線程都需要一個(gè)獨(dú)立的程序計(jì)數(shù)器,各個(gè)線程之間互不影響,獨(dú)立存儲(chǔ),這也就是所謂的“線程私有區(qū)域”。

019什么是虛擬機(jī)棧?

描述方法執(zhí)行的內(nèi)存模型,每個(gè)方法在執(zhí)行時(shí)都會(huì)創(chuàng)建一個(gè)棧幀,每個(gè)棧幀存放的是局部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接,方法出口等信息,方法被調(diào)用到執(zhí)行完成對(duì)應(yīng)的是一個(gè)棧幀從入棧到出棧的過程。是線程私有的。

020什么是本地方法棧?

為虛擬機(jī)使用到的Native方法服務(wù)。注在HotSpot虛擬機(jī)中直接就把本地方法棧和虛擬機(jī)棧合二為一了。

021什么是方法區(qū)?

存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。在jdk1.8中已經(jīng)去除了永久代,改用只受計(jì)算機(jī)本地內(nèi)存大小限制的元空間來實(shí)現(xiàn)方法區(qū),元空間參數(shù)(-XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=1024M)。

022什么是運(yùn)行時(shí)常量池?

運(yùn)行時(shí)常量池是方法區(qū)的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項(xiàng)信息是常量池,用于存放編譯器生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。

023Java 8 中 PermGen 為什么被移出 HotSpot JVM了?

1. 由于PermGen內(nèi)存經(jīng)常會(huì)溢出,引發(fā)惱人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的開發(fā)者希望這一塊內(nèi)存可以更靈活地被管理,不要再經(jīng)常出現(xiàn)這樣的 OOM。
2. 移除 PermGen 可以促進(jìn) HotSpot JVM 與 JRockit VM 的融合,因?yàn)?JRockit 沒有永久代。

024i++和++i的底層區(qū)別?

i++:剛開始學(xué)java時(shí)候,i++先使用i,然后再自加1,為什么是這樣呢?
底層步驟:
1.從局部變量表取出 i 并壓入操作數(shù)棧。(入棧)
2.然后對(duì)局部變量表中的i自增1,將操作棧棧頂值取出使用。(自加1,出棧)
3.最后使用操作數(shù)棧的棧頂值更新局部變量表,如此線程從操作棧讀到的是自增之前的值。(更新)
++i:剛開始學(xué)java時(shí)候,++i先自加1然后再使用i,為什么是這樣呢?
----------------------------------------------------------
底層步驟:
1.先對(duì)局部變量表的 i 自增 1。(自加1)
2.然后取出并壓入操作數(shù)棧。(入棧)
3.再將操作棧棧頂值取出使用。(出棧)
4.最后使用棧頂值更新局部變量表,線程從操作棧讀到的是自增之后的值。(更新)
--------------------------------------------
之前之所以說 i++ 不是原子操作,即使使用 volatile 修飾也不是線程安全,就是因?yàn)榭赡?i 被從局部變量表取出,壓入操作數(shù)棧,操作數(shù)棧中自增,使用棧頂值更新局部變量表(寄存器更新寫入內(nèi)存),其中分為 3 步,volatile 保證可見性,保證每次從局部變量表讀取的都是最新的值,但可能這 3 步可能被另一個(gè)線程的 3 步打斷,產(chǎn)生數(shù)據(jù)互相覆蓋問題,從而導(dǎo)致 i 的值比預(yù)期的小。

025什么時(shí)候拋出StackOverflowError?

如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,則拋出StackOverflowError。

026什么情況下會(huì)出現(xiàn)堆內(nèi)存溢出?

堆內(nèi)存存儲(chǔ)對(duì)象實(shí)例。我們只要不斷地創(chuàng)建對(duì)象。并保證gc roots到對(duì)象之間有可達(dá)路徑來避免垃圾回收機(jī)制清除這些對(duì)象。就會(huì)在對(duì)象數(shù)量到達(dá)最大。堆容量限制后,產(chǎn)生內(nèi)存溢出異常。

027如何實(shí)現(xiàn)一個(gè)堆內(nèi)存溢出?

public class Cat {
    public static void main(String[] args) {
        List list = new ArrayList();
        while (true) {
            list.add(new Cat());
        }
    }
}

028什么情況下會(huì)發(fā)生棧內(nèi)存溢出?

1.棧是線程私有的,棧的生命周期和線程一樣,每個(gè)方法在執(zhí)行的時(shí)候就會(huì)創(chuàng)建一個(gè)棧幀,它包含局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息,局部變量表又包括基本數(shù)據(jù)類型和對(duì)象的引用;
2.當(dāng)線程請(qǐng)求的棧深度超過了虛擬機(jī)允許的最大深度時(shí),會(huì)拋出StackOverFlowError異常,方法遞歸調(diào)用肯可能會(huì)出現(xiàn)該問題;
3.調(diào)整參數(shù)-xss去調(diào)整jvm棧的大小;

029堆是分配對(duì)象的唯一選擇么?

在Java虛擬機(jī)中,對(duì)象是在Java堆中分配內(nèi)存的,這是一個(gè)普遍的常識(shí)。但是,有一種特殊情況,那就是如果經(jīng)過逃逸分析(Escape Analysis)后發(fā)現(xiàn),一個(gè)對(duì)象并沒有逃逸出方法的話,那么就可能被優(yōu)化成棧上分配。這樣就無需在堆上分配內(nèi)存,也無須進(jìn)行垃圾回收了。這也是最常見的堆外存儲(chǔ)技術(shù)。
1)當(dāng)一個(gè)對(duì)象在方法中被定義后,對(duì)象只在方法內(nèi)部使用,則認(rèn)為沒有發(fā)生逃逸。
2)當(dāng)一個(gè)對(duì)象在方法中被定義后,它被外部方法所引用,則認(rèn)為發(fā)生逃逸。例如作為調(diào)用參數(shù)傳遞到其他地方中。

030運(yùn)行時(shí)數(shù)據(jù)區(qū),是否存在Error和GC?

運(yùn)行時(shí)數(shù)據(jù)區(qū) 是否存在 是否存在
程序計(jì)數(shù)器
虛擬機(jī)棧
本地方法棧
方法區(qū) 是(OOM)

031什么是GC機(jī)制?

Java GC(Garbage Collection)垃圾回收機(jī)制,是Java與C++/C的主要區(qū)別。JVM通過GC來回收堆和方法區(qū)中的內(nèi)存,這個(gè)過程是自動(dòng)執(zhí)行的。因此作為Java開發(fā)者,不需要專門去編寫內(nèi)存回收和垃圾清理代碼,也不需要處理內(nèi)存泄露和溢出的問題。雖然java不需要開發(fā)人員顯示的分配和回收內(nèi)存,這對(duì)開發(fā)人員確實(shí)降低了不少編程難度,但也可能帶來一些副作用:
1.有可能不知不覺浪費(fèi)了很多內(nèi)存;
2.JVM花費(fèi)過多時(shí)間來進(jìn)行內(nèi)存回收;
3.內(nèi)存泄露;
Java GC機(jī)制主要完成3件事:確定哪些內(nèi)存需要回收;確定什么時(shí)候需要執(zhí)行GC;如何執(zhí)行GC。

032如和判斷一個(gè)對(duì)象是否存活?

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í),說明此對(duì)象沒有被引用,也就是“死對(duì)象”,將會(huì)被垃圾回收.
引用計(jì)數(shù)法有一個(gè)缺陷就是無法解決循環(huán)引用問題,也就是說當(dāng)對(duì)象 A 引用對(duì)象 B,對(duì)象B 又引用者對(duì)象 A,那么此時(shí) A,B 對(duì)象的引用計(jì)數(shù)器都不為零,也就造成無法完成垃圾回收,所以主流的虛擬機(jī)都沒有采用這種算法。
2.可達(dá)性算法(引用鏈法)
該算法的思想是:從一個(gè)被稱為 GC Roots的對(duì)象開始向下搜索,如果一個(gè)對(duì)象到 GCRoots 沒有任何引用鏈相連時(shí),則說明此對(duì)象不可用。
在 java 中可以作為 GC Roots 的對(duì)象有以下幾種:
(1)虛擬機(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)記
(2)如果對(duì)象在可達(dá)性分析中沒有與 GC Root 的引用鏈,那么此時(shí)就會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是是否有必要執(zhí)行 finalize()方法。當(dāng)對(duì)象沒有覆蓋 finalize()方法或者已被虛擬機(jī)調(diào)用過,那么就認(rèn)為是沒必要的。
(3)如果該對(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ì)造成 FQueue 隊(duì)列一直等待,造成了內(nèi)存回收系統(tǒng)的崩潰。GC 對(duì)處于 F-Queue 中的對(duì)象進(jìn)行第二次被標(biāo)記,這時(shí),該對(duì)象將被移除”即將回收”集合,等待回收。

033垃圾回收方式?

GC按照回收區(qū)域又分為兩大種類型:部分收集和整堆收集。
部分收集(Partial GC):不是完整收集整個(gè)Java堆的垃圾收集。其中又分為:
1. 新生代收集(Minor GC/Young GC):只是新生代的垃圾收集
當(dāng)年輕代空間不足時(shí),就會(huì)觸發(fā)MinorGC,這里的年輕代滿指的是Eden代滿,Survivor滿不會(huì)引發(fā)GC。
2. 老年代收集(MajorGC/o1dGC):只是老年代的圾收集。
3. 混合收集(MixedGC):收集整個(gè)新生代以及部分老年代的垃圾收集。
整堆收集(FullGC):收集整個(gè)java堆和方法區(qū)的垃圾收集。

034描述下GC過程。

1.在初始階段,新創(chuàng)建的對(duì)象被分配到Eden區(qū),S0和S1的兩塊空間都為空。
2.當(dāng)Eden區(qū)滿了的時(shí)候,Minor GC 被觸發(fā) 。經(jīng)過掃描與標(biāo)記,不存活的對(duì)象被回收,存活的對(duì)象被復(fù)制到S0,并且存活的對(duì)象年齡都增大一歲。
3.當(dāng)Eden區(qū)又滿的時(shí)候,Minor GC再次被觸發(fā)。此時(shí)Eden區(qū) 和 S0區(qū)存活的對(duì)象要復(fù)制到S1。需要注意的是,此時(shí)Eden區(qū)和S0區(qū)被清空,S0中的對(duì)象復(fù)制到S1后其年齡要加1。
4.當(dāng)Eden區(qū)再次又滿的時(shí)候,MinorGC則重復(fù)上面過程,將Eden區(qū) 和 S1區(qū)存活的對(duì)象復(fù)制到S0。此時(shí)Eden區(qū)和S1區(qū)被清空,S0中的對(duì)象復(fù)制到S1后其年齡要加1。
5.經(jīng)過幾次Minor GC之后,當(dāng)存活對(duì)象的年齡達(dá)到一個(gè)閾值之后(-XX:MaxTenuringThreshold默認(rèn)是15),就會(huì)被從年輕代Promotion到老年代。
6.新生代 GC(Minor GC):指發(fā)生新生代的的垃圾收集動(dòng)作,Minor GC 非常頻繁,回收速度一般也比較快。
7.老年代 GC(Major GC/Full GC):指發(fā)生在老年代的 GC,出現(xiàn)了 Major GC 經(jīng)常會(huì)伴隨至少一次的 Minor GC(并非絕對(duì)),Major GC 的速度一般會(huì)比 Minor GC 的慢 10 倍以上。

035解釋強(qiáng)、軟、弱、虛引用?

JDK1.2 以前,一個(gè)對(duì)象只有被引用和沒有被引用兩種狀態(tài)。后來,Java 對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)4 種,這 4 種引用強(qiáng)度依次逐漸減弱。

036垃圾回收算法有哪些?

一共有 4 種:標(biāo)記-清除算法、復(fù)制算法、標(biāo)記整理算法、分代收集算法;

037什么是標(biāo)記-清除算法?

最基礎(chǔ)的收集算法是“標(biāo)記-清除”(Mark-Sweep)算法,分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。

038標(biāo)記-清除算法的缺點(diǎn)?

● 效率問題,標(biāo)記和清除兩個(gè)過程的效率都不高;
● 空間問題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對(duì)象時(shí),無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

039什么是復(fù)制算法?

它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。這樣使得每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效。只是這種算法的代價(jià)是將內(nèi)存縮小為了原來的一半。復(fù)制算法的執(zhí)行過程如下圖:

一般虛擬機(jī)都采用這種算法來回收新生代,因?yàn)樾律械膶?duì)象 98% 是“朝生夕死”的,所以并不需要按照 1:1 的比例來劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的 Eden 空間和兩塊較小的 Survivor 空間,每次使用 Eden 和其中一塊 Survivor 。當(dāng)回收時(shí),將 Eden 和 Survivor 中還存活著的對(duì)象一次性地復(fù)制到另外一塊 Survivor 空間上,最后清理掉 Eden 和剛才用過的 Survivor 空間。HotSpot 虛擬機(jī)默認(rèn) Eden:Survivor = 8:1,也就是每次新生代中可用內(nèi)存空間為整個(gè)新生代容量的 90%(其中一塊Survivor不可用),只有 10% 的內(nèi)存會(huì)被“浪費(fèi)”。當(dāng)然如果另外一塊 Survivor 空間沒有足夠空間存放上一次新生代收集下來的存活對(duì)象時(shí),這些對(duì)象將直接通過分配擔(dān)保機(jī)制進(jìn)入老年代。

040復(fù)制算法缺點(diǎn)?

復(fù)制算法適合年輕代,不適合老年代。因?yàn)樵趯?duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作,效率將會(huì)變低。更關(guān)鍵的是復(fù)制算法需要有額外的空間進(jìn)行分配擔(dān)保,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都 100% 存活的極端情況。

041什么是標(biāo)記-整理算法

根據(jù)老年代的特點(diǎn),有人提出了另外一種“標(biāo)記-整理”(Mark-Compact)算法,標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。

042什么是分代收集算法?

"分代收集"(Generational Collection)算法是根據(jù)對(duì)象存活周期的不同將內(nèi)存劃分為幾塊并采用不同的垃圾收集算法。一般是把 Java 堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴?。在新生代中,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集。而老年代中因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用“標(biāo)記—清理”或者“標(biāo)記—整理”算法來進(jìn)行回收。

043Stop The World是什么意思?

進(jìn)行垃圾收集時(shí),必須暫停其他所有工作線程,Sun將這種事情叫做"Stop The World"。

044什么情況下新生代對(duì)象會(huì)晉升到老年代?

如果新生代的垃圾收集器為Serial和ParNew,并且設(shè)置了-XX:PretenureSizeThreshold參數(shù),當(dāng)對(duì)象大于這個(gè)參數(shù)值時(shí),會(huì)被認(rèn)為是大對(duì)象,直接進(jìn)入老年代。
Young GC后,如果對(duì)象太大無法進(jìn)入Survivor區(qū),則會(huì)通過分配擔(dān)保機(jī)制進(jìn)入老年代。
對(duì)象每在Survivor區(qū)中“熬過”一次Young GC,年齡就增加1歲,當(dāng)它的年齡增加到一定程度(默認(rèn)為15歲,可以通過-XX:MaxTenuringThreshold設(shè)置),就將會(huì)被晉升到老年代中。
如果在Survivor區(qū)中相同年齡所有對(duì)象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對(duì)象就可以直接進(jìn)入老年代,無須等到MaxTenuringThreshold中要求的年齡。

045新生代中Eden區(qū)和Survivor區(qū)的默認(rèn)比例?

在HotSpot虛擬機(jī)中,Eden區(qū)和Survivor區(qū)的默認(rèn)比例為8:1:1,即-XX:SurvivorRatio=8,其中Survivor分為From Survivor和ToSurvivor,因此Eden此時(shí)占新生代空間的80%。

046Minor GC ,Major GC,F(xiàn)ull GC是什么?

Minor GC是當(dāng)年輕代空間不足時(shí),就會(huì)觸發(fā)MinorGC,這里的年輕代滿指的是Eden代滿,Survivor滿不會(huì)引發(fā)GC(每次Minor GC會(huì)清理年輕代的內(nèi)存)。因?yàn)镴ava對(duì)象大多都具備朝生夕滅的特性,所以Minor GC非常頻繁,一般回收速度也比較快。這一定義既清晰又易于理解。Minor GC會(huì)引發(fā)STW,暫停其它用戶的線程,等垃圾回收結(jié)束,用戶線程才恢復(fù)運(yùn)行
Major GC指發(fā)生在老年代的GC,對(duì)象從老年代消失時(shí),我們說"Major Gc"或"Full GC"發(fā)生了。出現(xiàn)了MajorGc,經(jīng)常會(huì)伴隨至少一次的Minor GC(但非絕對(duì)的,在Paralle1 Scavenge收集器的收集策略里就有直接進(jìn)行MajorGC的策略選擇過程),也就是在老年代空間不足時(shí),會(huì)先嘗試觸發(fā)MinorGc。如果之后空間還不足,則觸發(fā)Major GC,Major GC的速度一般會(huì)比MinorGc慢1e倍以上,STW的時(shí)間更長(zhǎng),如果Major GC后,內(nèi)存還不足,就報(bào)OOM了;
Full GC是對(duì)年輕代和老年代都進(jìn)行垃圾回收,F(xiàn)ull GC 是開發(fā)或調(diào)優(yōu)中盡量要避免的,這樣暫時(shí)時(shí)間會(huì)短一些。

047Minor GC和Full GC的觸發(fā)條件?

Minor GC觸發(fā)條件: 當(dāng)Eden區(qū)滿時(shí),觸發(fā)Minor GC。
Full GC觸發(fā)條件:
(1)調(diào)用System.gc時(shí),系統(tǒng)建議執(zhí)行Full GC,但是不必然執(zhí)行
(2)老年代空間不足
(3)方法區(qū)空間不足
(4)通過Minor GC后進(jìn)入老年代的平均大小大于老年代的可用內(nèi)存
(5)由Eden區(qū)、From Space區(qū)向To Sp3ace區(qū)復(fù)制時(shí),對(duì)象大小大于To Space可存,則把該對(duì)象轉(zhuǎn)存到老年代,且老年代的可用內(nèi)存小于該對(duì)象大??;

048垃圾收集器有哪些?

049Serial垃圾收集器?

最基本的垃圾收集器,使用復(fù)制算法,單線程,雖然收集垃圾時(shí)需要暫停其他所有的工作線程,但簡(jiǎn)單高效,是 java 虛擬機(jī)運(yùn)行在 Client 模式下默認(rèn)的新生代垃圾收集器。
在HotSpot虛擬機(jī)中,使用-XX:+UseSerialGC參數(shù)可以指定年輕代和老年代都使用串行收集器。等價(jià)于新生代用Serial GC,且老年代用Serial Old GC。

050ParNew 垃圾收集器?

是 Serial 收集器的多線程版本 ,除了多線程進(jìn)行GC外,其他與Serial一樣,默認(rèn)開啟和 CPU 數(shù)目相同的線程數(shù) 。是很多 java虛擬機(jī)運(yùn)行在 Server 模式下新生代的默認(rèn)垃圾收集器。
1)可以通過選項(xiàng)"-XX:+UseParNewGC"手動(dòng)指定使用ParNew收集器執(zhí)行內(nèi)存回收任務(wù)。它表示年輕代使用并行收集器,不影響老年代
2)這里的多線程指的是垃圾收集時(shí),多線程并行,并不是垃圾收集與程序運(yùn)行并行
3)收集垃圾時(shí),也需要暫停其他所有工作線程,然后多線程收集垃圾。
4)單CPU環(huán)境下,因?yàn)榫€程切換,性能較差。

051Parallel Scavenge 收集器?

關(guān)注程序的吞吐量,即吞吐量?jī)?yōu)先。主要適用于在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。 自適應(yīng)調(diào)節(jié)策略也是 ParallelScavenge 收集器與 ParNew 收集器的一個(gè)重要區(qū)別。
1)吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間) ; 吞吐量?jī)?yōu)先,意味著在單位時(shí)間內(nèi),STW的時(shí)間最短;與之相對(duì)應(yīng)的 低延遲 就是暫停時(shí)間優(yōu)先,盡可能讓單次STW時(shí)間最短;這兩個(gè)無法同時(shí)實(shí)現(xiàn)。
2)收集垃圾時(shí),也需要暫停其他所有工作線程,然后多線程收集垃圾。
3)參數(shù)配置
-XX:+UseParallelGC 手動(dòng)指定年輕代使用Parallel并行收集器執(zhí)行內(nèi)存回收任務(wù)。 
-XX:+UseParallelOldGC 手動(dòng)指定老年代都是使用并行回收收集器。 
-XX:ParallelGCThreads 設(shè)置年輕代并行收集器的線程數(shù)。一般地,最好與CPU數(shù)量相等,以避免過多的線程數(shù)影響垃圾收集性能。  
-XX:MaxGCPauseMillis 設(shè)置垃圾收集器最大停頓時(shí)間(即STw的時(shí)間),單位是毫秒。 為了盡可能地把停頓時(shí)間控制在MaxGCPauseMills以內(nèi),收集器在工作時(shí)會(huì)調(diào)整Java堆大小或者其他一些參數(shù)。對(duì)于用戶來講,停頓時(shí)間越短體驗(yàn)越好。但是在服務(wù)器端,我們注重高并發(fā),整體的吞吐量。所以服務(wù)器端適合Parallel進(jìn)行控制。該參數(shù)使用需謹(jǐn)慎。 
-XX:GCTimeRatio 垃圾收集時(shí)間占總時(shí)間的比例(=1/(N+1))。用于衡量吞吐量的大小。 取值范圍(0, 100)。默認(rèn)值99,也就是垃圾回收時(shí)間不超過1%。與前一個(gè)-XX:MaxGCPauseMillis參數(shù)有一定矛盾性。暫停時(shí)間越長(zhǎng),Radio參數(shù)就容易超過設(shè)定的比例。  
-XX:+UseAdaptivesizePolicy 設(shè)置Parallel Scavenge收集器具有自適應(yīng)調(diào)節(jié)策略 。在這種模式下,年輕代的大小、Eden和Survivor的比例、晉升老年代的對(duì)象年齡等參數(shù)會(huì)被自動(dòng)調(diào)整,已達(dá)到在堆大小、吞吐量和停頓時(shí)間之間的平衡點(diǎn)。在手動(dòng)調(diào)優(yōu)比較困難的場(chǎng)合,可以直接使用這種自適應(yīng)的方式,僅指定虛擬機(jī)的最大堆、目標(biāo)的吞吐量(GCTimeRatio)和停頓時(shí)間(MaxGCPauseMills,讓虛擬機(jī)自己完成調(diào)優(yōu)工作。

052Serial Old?

1)是Serial的老年代版本,收集垃圾時(shí)也需要暫停其他所有的工作線程。
2)是Client模式下默認(rèn)的老年代垃圾收集器
3)Server模式下,搭配新生代的Parallel Scavenge 收集器使用(在 JDK1.5 之前版本中)。同時(shí)也作為老年代中使用 CMS 收集器的后備垃圾收集方案(當(dāng)CMS發(fā)生Concurrent Mode Failure)。

053Parallel Old收集器?

1)Parallel Scavenge的老年代版本
2)吞吐量?jī)?yōu)先,意味著在單位時(shí)間內(nèi),STW的時(shí)間最短;與之相對(duì)應(yīng)的 低延遲 就是暫停時(shí)間優(yōu)先,盡可能讓單次STW時(shí)間最短;這兩個(gè)無法同時(shí)實(shí)現(xiàn)。
3)若相同對(duì)于吞吐量要求較高,可以Parallel Scavenge搭配Parallel Old使用。

054介紹CMS垃圾收集器的特點(diǎn)?

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。目前很大一部分的Java應(yīng)用集中在互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端上,這類應(yīng)用尤其重視服務(wù)的響應(yīng)速度,希望系統(tǒng)停頓時(shí)間最短,以給用戶帶來較好的體驗(yàn)。CMS收集器就非常符合這類應(yīng)用的需求。
從名字(包含“Mark Sweep”)上就可以看出,CMS收集器是基于“標(biāo)記—清除”算法實(shí)現(xiàn)的,它的運(yùn)作過程可以分為6個(gè)步驟,包括:初始標(biāo)記、并發(fā)標(biāo)記、預(yù)處理、重新標(biāo)記、并發(fā)清除、重置。
CMS是一款優(yōu)秀的收集器,它的主要優(yōu)點(diǎn)在名字上已經(jīng)體現(xiàn)出來了:并發(fā)收集、低停頓,但是CMS還遠(yuǎn)達(dá)不到完美的程度,它有以下3個(gè)明顯的缺點(diǎn):
(1)CMS收集器對(duì)CPU資源非常敏感。
(2)CMS收集器無法處理浮動(dòng)垃圾(Floating Garbage),可能出現(xiàn)“Concurrent Mode Failure”失敗而導(dǎo)致另一次Full GC的產(chǎn)生。
(3)CMS是一款基于“標(biāo)記—清除”算法實(shí)現(xiàn)的收集器,這意味著收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生。

055介紹下G1垃圾收集器的特點(diǎn)?

G1(Garbage-First)收集器是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一。G1是一款面向服務(wù)端應(yīng)用的垃圾收集器。與其他GC收集器相比,G1具備如下特點(diǎn):并行與并發(fā)、分代收集、空間整合、可預(yù)測(cè)的停頓。
在G1之前的其他收集器進(jìn)行收集的范圍都是整個(gè)新生代或者老年代,而G1不再是這樣。使用G1收集器時(shí),Java堆的內(nèi)存布局就與其他收集器有很大差別,它將整個(gè)Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域,雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續(xù))的集合。
G1收集器之所以能建立可預(yù)測(cè)的停頓時(shí)間模型,是因?yàn)樗梢杂杏?jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集。G1跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大?。ɑ厥账@得的空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值),在后臺(tái)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的Region(這也就是Garbage-First名稱的來由)。這種使用Region劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了G1收集器在有限的時(shí)間內(nèi)可以獲取盡可能高的收集效率。
Mixed GC是G1垃圾收集器特有的收集方式,Mixed GC大致可劃分為全局并發(fā)標(biāo)記(global concurrent marking)和拷貝存活對(duì)象(evacuation)兩個(gè)大部分:
global concurrent marking是基于SATB形式的并發(fā)標(biāo)記,包括以下4個(gè)階段:初始標(biāo)記(Initial Marking)、并發(fā)標(biāo)記(Concurrent Marking)、最終標(biāo)記(Final Marking)、清理(Clean Up)。Evacuation階段是全暫停的。它負(fù)責(zé)把一部分region里的活對(duì)象拷貝到空region里去,然后回收原本的region的空間。

056垃圾收集器的比較圖。

垃圾收集器 分類 作用位置 使用算法 特點(diǎn) 適用場(chǎng)景
Serial 串行 新生代 復(fù)制算法 響應(yīng)速度優(yōu)先 適用于單CPU環(huán)境下的client模式
ParNew 并行 新生代 復(fù)制算法 響應(yīng)速度優(yōu)先 多CPU環(huán)境Server模式下與CMS配合使用
Parallel 并行 新生代 復(fù)制算法 吞吐量?jī)?yōu)先 適用于后臺(tái)運(yùn)算而不需要太多交互的場(chǎng)景
Serial Old 串行 老年代 標(biāo)記-整理(壓縮)算法 響應(yīng)速度優(yōu)先 適用于單CPU環(huán)境下的Client模式
Paraller Old  并行 老年代 標(biāo)記-整理(壓縮)算法 標(biāo)記-整理(壓縮)算法 適用于后臺(tái)運(yùn)算而不需要太多交互的場(chǎng)景
CMS 并發(fā) 老年代 標(biāo)記-清除算法 響應(yīng)速度優(yōu)先 適用于互聯(lián)網(wǎng)或B/S業(yè)務(wù)
G1 并發(fā)、并行 新生代、老年代 標(biāo)記-整理(壓縮)算法 響應(yīng)速度優(yōu)先 響應(yīng)速度優(yōu)先

057JVM性能調(diào)優(yōu)的原則有哪些?

1)多數(shù)的Java應(yīng)用不需要在服務(wù)器上進(jìn)行GC優(yōu)化;
2)多數(shù)導(dǎo)致GC問題的Java應(yīng)用,都不是因?yàn)槲覀儏?shù)設(shè)置錯(cuò)誤,而是代碼問題;
3)在應(yīng)用上線前,先考慮將JVM參數(shù)設(shè)置到最優(yōu);
4)減少對(duì)象創(chuàng)建的數(shù)量;
5)減少全局變量和大對(duì)象;
6)GC優(yōu)化是最后不得已才使用的手段,在實(shí)際應(yīng)用中,分析GC情況優(yōu)化代碼比優(yōu)化GC參數(shù)要多得多;

058什么情況下需要JVM調(diào)優(yōu)?

通過看監(jiān)控中的jvm是否有fgc,頻繁fgc才需要優(yōu)化(頻繁fgc需要抓緊改配置)

059JVM常用性能調(diào)優(yōu)工具有哪些?

1)JDK的命令行工具
Sun JDK監(jiān)控和故障處理命令有jps、jstat、jmap、jhat、jstack、jinfo
jps(虛擬機(jī)進(jìn)程狀況工具):顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機(jī)進(jìn)程。    jstat(虛擬機(jī)統(tǒng)計(jì)信息監(jiān)視工具):用于監(jiān)視虛擬機(jī)運(yùn)行時(shí)狀態(tài)信息的命令,它可以顯示出虛擬機(jī)進(jìn)程中的類裝載、內(nèi)存、垃圾收集、JIT編譯等運(yùn)行數(shù)據(jù)。    jinfo(Java配置信息工具):jinfo的作用是實(shí)時(shí)地查看和調(diào)整虛擬機(jī)各項(xiàng)參數(shù)。
jmap(Java內(nèi)存映像工具):dump堆到文件,可用于對(duì)文件的分析。    
jhat(虛擬機(jī)堆轉(zhuǎn)儲(chǔ)快照分析工具):jhat命令與jmap搭配使用,來分析jmap生成的堆 轉(zhuǎn)儲(chǔ)快照。jhat內(nèi)置了一個(gè)微型的HTTP/HTML服務(wù)器,生成dump文件的分析結(jié)果后,可以在瀏覽器中查看。
jstack(Java堆棧跟蹤工具):jstack命令用于生成虛擬機(jī)當(dāng)前時(shí)刻的線程快照。線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧 的集合,生成線程快照的主要目的是定位線程出現(xiàn)長(zhǎng)時(shí)間停頓的原因,如線程間死鎖、死循 環(huán)、請(qǐng)求外部資源導(dǎo)致的長(zhǎng)時(shí)間等待等都是導(dǎo)致線程長(zhǎng)時(shí)間停頓的常見原因。線程出現(xiàn)停頓 的時(shí)候通過jstack來查看各個(gè)線程的調(diào)用堆棧,就可以知道沒有響應(yīng)的線程到底在后臺(tái)做些 什么事情,或者等待著什么資源。
2)JConsole
Jconsole(Java Monitoring and Management Console)是從java5開始,在JDK中自帶的java監(jiān)控和管理控制臺(tái),用于對(duì)JVM中內(nèi)存,線程和類等的監(jiān)控,是一個(gè)基于JMX(java management extensions)的GUI性能監(jiān)測(cè)工具。jconsole使用jvm的擴(kuò)展機(jī)制獲取并展示虛擬機(jī)中運(yùn)行的應(yīng)用程序的性能和資源消耗等信息。
概覽:包括堆內(nèi)存使用情況、線程、類、CPU使用情況四項(xiàng)信息的曲線圖。
3)VisualVM
VisualVM(All-in-One Java Troubleshooting Tool)是功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序之一,曾經(jīng)在很長(zhǎng)一段時(shí)間內(nèi)是Oracle官方主力發(fā)展的虛擬機(jī)故障處理工具。
相比一些第三方工具,VisualVM有一個(gè)很大的優(yōu)點(diǎn):不需要被監(jiān)視的程序基于特殊Agent去運(yùn)行,因此它的通用性很強(qiáng),對(duì)應(yīng)用程序?qū)嶋H性能的影響也較小,使得它可以直接應(yīng)用在生產(chǎn)環(huán)境中。
Visual GC 是常常使用的一個(gè)功能,需要通過插件按照,可以明顯的看到年輕代、老年代的內(nèi)存變化,以及gc頻率、gc的時(shí)間等!

060出現(xiàn)OutOfMemoryError(OOM)原因?

觸發(fā) java.lang.OutOfMemoryError:最常見的原因就是應(yīng)用程序需要的堆空間需要的是大的,但是 JVM 提供的卻是小的,從而導(dǎo)致內(nèi)存溢出。這個(gè)解決方法就是提供大的堆空間即可。
除此之外還有復(fù)雜的原因:內(nèi)存泄露。特定的編程錯(cuò)誤會(huì)導(dǎo)致你的應(yīng)用程序不停的消耗更多的內(nèi)存,每次使用有內(nèi)存泄漏風(fēng)險(xiǎn)的功能就會(huì)留下一些不能被回收的對(duì)象到堆空間中,隨著時(shí)間的推移,泄漏的對(duì)象會(huì)消耗所有的堆空間,最終觸發(fā)java.lang.OutOfMemoryError: Java heap space 錯(cuò)誤。

061OutOfMemoryError(OOM)的解決方案?

1.確保有足夠的堆空間來正常運(yùn)行你的應(yīng)用程序,在 JVM 的啟動(dòng)配置中增加如下配置:-Xmx1024m。
2.流量/數(shù)據(jù)量峰值:應(yīng)用程序在設(shè)計(jì)之初均有用戶量和數(shù)據(jù)量的限制,某一時(shí)刻,當(dāng)用戶數(shù)量或數(shù)據(jù)量突然達(dá)到一個(gè) 峰 值 , 并 且 這 個(gè) 峰 值 已 經(jīng) 超 過 了 設(shè) 計(jì) 之 初 預(yù) 期 的 閾 值 , 那 么 以 前 正 常 的 功 能 將 會(huì) 停 止 , 并 觸 發(fā)java.lang.OutOfMemoryError
3.Java heap space 異常解決方案,如果你的應(yīng)用程序確實(shí)內(nèi)存不足,增加堆內(nèi)存會(huì)解決 GC overhead limit 問題,就如下面這樣,給你的應(yīng)用程序 1G 的堆內(nèi)存:java -Xmx1024m com.yourcompany.YourClass。

目錄

001JDK、JRE、JVM關(guān)系? 002什么是類加載器,類加載器有哪些? 003ClassLoader如何工作的? 004靜態(tài)代碼塊在程序中的執(zhí)行順序? 005對(duì)象創(chuàng)建的過程? 006什么是雙親委派機(jī)制? 007雙親委派機(jī)制的優(yōu)勢(shì)? 008如何破壞雙親委派模型? 009可不可以自己寫個(gè)String類? 010什么是字節(jié)碼? 011字節(jié)碼文件組成結(jié)構(gòu)是什么? 012對(duì)象的finalization機(jī)制。 013如何判斷兩個(gè)class對(duì)象是否相同? 014類的主動(dòng)使用有哪些? 015深拷貝和淺拷貝區(qū)別? 016啟動(dòng)程序如何查看加載了哪些類,以及加載順序? 017JDK1.6、JDK1.7、JDK1.8 內(nèi)存模型演變? 018什么是程序計(jì)數(shù)器? 019什么是虛擬機(jī)棧? 020什么是本地方法棧? 021什么是方法區(qū)? 022什么是運(yùn)行時(shí)常量池? 023Java 8 中 PermGen 為什么被移出 HotSpot JVM了? 024i++和++i的底層區(qū)別? 025什么時(shí)候拋出StackOverflowError? 026什么情況下會(huì)出現(xiàn)堆內(nèi)存溢出? 027如何實(shí)現(xiàn)一個(gè)堆內(nèi)存溢出? 028什么情況下會(huì)發(fā)生棧內(nèi)存溢出? 029堆是分配對(duì)象的唯一選擇么? 030運(yùn)行時(shí)數(shù)據(jù)區(qū),是否存在Error和GC? 031什么是GC機(jī)制? 032如和判斷一個(gè)對(duì)象是否存活? 033垃圾回收方式? 034描述下GC過程。 035解釋強(qiáng)、軟、弱、虛引用? 036垃圾回收算法有哪些? 037什么是標(biāo)記-清除算法? 038標(biāo)記-清除算法的缺點(diǎn)? 039什么是復(fù)制算法? 040復(fù)制算法缺點(diǎn)? 041什么是標(biāo)記-整理算法 042什么是分代收集算法? 043Stop The World是什么意思? 044什么情況下新生代對(duì)象會(huì)晉升到老年代? 045新生代中Eden區(qū)和Survivor區(qū)的默認(rèn)比例? 046Minor GC ,Major GC,F(xiàn)ull GC是什么? 047Minor GC和Full GC的觸發(fā)條件? 048垃圾收集器有哪些? 049Serial垃圾收集器? 050ParNew 垃圾收集器? 051Parallel Scavenge 收集器? 052Serial Old? 053Parallel Old收集器? 054介紹CMS垃圾收集器的特點(diǎn)? 055介紹下G1垃圾收集器的特點(diǎn)? 056垃圾收集器的比較圖。 057JVM性能調(diào)優(yōu)的原則有哪些? 058什么情況下需要JVM調(diào)優(yōu)? 059JVM常用性能調(diào)優(yōu)工具有哪些? 060出現(xiàn)OutOfMemoryError(OOM)原因? 061OutOfMemoryError(OOM)的解決方案?
返回頂部
主站蜘蛛池模板: 在线观看偷拍视频一区 | 伊人精品视频在线观看 | 午夜在线播放免费高清观看 | a级做爰视频在线观看 | ww欧美| 欧美aaaaa一级毛片在线 | 99精品免费在线观看 | 国产一级特黄a大片99 | 好爽毛片一区二区三区四区 | 久久久久久网址 | 人人干人人草 | 亚洲视频在线免费播放 | 色狠狠一区二区 | 国产黄网永久免费 | 麻豆国产96在线 | 中国 | 老司机深夜福利影院 | 亚洲啪视频 | 国产精品久久久久激情影院 | 看欧美毛片一级毛片 | 精品伦理| 天天碰天天操 | 国产大尺度福利视频在线 | 精品一区二区视频在线观看 | 黄色四虎影院 | 久久国产欧美日韩高清专区 | 国产精品伦理久久久久久 | 欧美 xx性 在线 | 国产欧美日韩精品综合 | 久草日韩| 亚洲视频在线播放 | 伊人久久国产免费观看视频 | 成年男女免费视频观看性 | 午夜精品久久久久久久 | 欧美成人免费xxx大片 | 久久久久国产精品 | 亚洲精品第一国产综合高清 | 不卡在线播放 | 日本tv欧美tv天堂 | 亚洲精品色婷婷在线影院麻豆 | 91精品视频网 | 久久网免费视频 |