亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

30道有趣的JVM面試題(小結(jié))

  發(fā)布時間:2020-11-26 17:22:17   作者:全棧小劉   我要評論
這篇文章主要介紹了30道有趣的JVM面試題(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前段時間在忙大數(shù)據(jù),也對市場技術(shù)有了一個新的理解,學(xué)到老,學(xué)到老嘛。今天來和大家分享一下JVM常見的面試題,今天來和大家分享一下。大多都是大廠的實戰(zhàn)面試題,來和小劉看一下吧!

1、JVN內(nèi)存結(jié)構(gòu)

方法區(qū)和對是所有線程共享的內(nèi)存區(qū)域;而java棧、本地方法棧和程序員計數(shù)器是運行是線程私有的內(nèi)存區(qū)域。

  • Java堆(Heap),是Java虛擬機所管理的內(nèi)存中最大的一塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內(nèi)存。
  • 方法區(qū)(Method Area),方法區(qū)(Method Area)與Java堆一樣,是各個線程共享的內(nèi)存區(qū)域,它用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。
  • 程序計數(shù)器(Program Counter Register),程序計數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。
  • JVM棧(JVM Stacks),與程序計數(shù)器一樣,Java虛擬機棧(Java Virtual Machine Stacks)也是線程私有的,它的生命周期與線程相同。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每一個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過程。
  • 本地方法棧(Native Method Stacks),本地方法棧(Native Method Stacks)與虛擬機棧所發(fā)揮的作用是非常相似的,其區(qū)別不過是虛擬機棧為虛擬機執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則是為虛擬機使用到的Native方法服務(wù)。

2、對象分配規(guī)則

  • 對象優(yōu)先分配在Eden區(qū),如果Eden區(qū)沒有足夠的空間時,虛擬機執(zhí)行一次Minor GC。
  • 大對象直接進入老年代(大對象是指需要大量連續(xù)內(nèi)存空間的對象)。這樣做的目的是避免在Eden區(qū)和兩個Survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)。
  • 長期存活的對象進入老年代。虛擬機為每個對象定義了一個年齡計數(shù)器,如果對象經(jīng)過了1次Minor GC那么對象會進入Survivor區(qū),之后每經(jīng)過一次Minor GC那么對象的年齡加1,知道達到閥值對象進入老年區(qū)。
  • 動態(tài)判斷對象的年齡。如果Survivor區(qū)中相同年齡的所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象可以直接進入老年代。
  • 空間分配擔(dān)保。每次進行Minor GC時,JVM會計算Survivor區(qū)移至老年區(qū)的對象的平均大小,如果這個值大于老年區(qū)的剩余值大小則進行一次Full GC,如果小于檢查HandlePromotionFailure設(shè)置,如果true則只進行Monitor GC,如果false則進行Full GC。

 3、解釋內(nèi)存中的棧(stack)、堆(heap)和靜態(tài)區(qū)(static area)的用法

通常我們定義一個基本數(shù)據(jù)類型的變量,一個對象的引用,還有就是函數(shù)調(diào)用的現(xiàn)場保存都使用內(nèi)存中的??臻g;而通過new關(guān)鍵字和構(gòu)造器創(chuàng)建的對象放在堆空間;程序中的字面量(literal)如直接書寫的100、"hello"和常量都是放在靜態(tài)區(qū)中。??臻g操作起來最快但是棧很小,通常大量的對象都是放在堆空間,理論上整個內(nèi)存沒有被其他進程使用的空間甚至硬盤上的虛擬內(nèi)存都可以被當(dāng)成堆空間來使用。

String str = new String("hello");

上面的語句中變量str放在棧上,用new創(chuàng)建出來的字符串對象放在堆上,而"hello"這個字面量放在靜態(tài)區(qū)。

4、Perm Space中保存什么數(shù)據(jù)?會引起OutOfMemory嗎?

Perm Space中保存的是加載class文件。

會引起OutOfMemory,出現(xiàn)異??梢栽O(shè)置 -XX:PermSize 的大小。JDK 1.8后,字符串常量不存放在永久帶,而是在堆內(nèi)存中,JDK8以后沒有永久代概念,而是用元空間替代,元空間不存在虛擬機中,二是使用本地內(nèi)存。

5、什么是類的加載

類的加載指的是將類的.class文件中的二進制數(shù)據(jù)讀入到內(nèi)存中,將其放在運行時數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆區(qū)創(chuàng)建一個java.lang.Class對象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。類的加載的最終產(chǎn)品是位于堆區(qū)中的Class對象,Class對象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向Java程序員提供了訪問方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)的接口。

類加載器

  • 啟動類加載器:Bootstrap ClassLoader,負責(zé)加載存放在JDK\jre\lib(JDK代表JDK的安裝目錄,下同)下,或被-Xbootclasspath參數(shù)指定的路徑中的,并且能被虛擬機識別的類庫
  • 擴展類加載器:Extension ClassLoader,該加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負責(zé)加載DK\jre\lib\ext目錄中,或者由java.ext.dirs系統(tǒng)變量指定的路徑中的所有類庫(如javax.*開頭的類),開發(fā)者可以直接使用擴展類加載器。
  • 應(yīng)用程序類加載器:Application ClassLoader,該類加載器由sun.misc.Launcher$AppClassLoader來實現(xiàn),它負責(zé)加載用戶類路徑(ClassPath)所指定的類,開發(fā)者可以直接使用該類加載器

雙親委派機制:類加載器收到類加載請求,自己不加載,向上委托給父類加載,父類加載不了,再自己加載。優(yōu)勢就是避免Java核心API篡改。

6、如何⾃定義⼀個類加載器?你使⽤過哪些或者你在什么場景下需要⼀個⾃ 定義的類加載器嗎?

自定義類加載的意義:

  • 加載特定路徑的class文件
  • 加載一個加密的網(wǎng)絡(luò)class文件
  • 熱部署加載class文件

7、描述一下JVM加載class文件的原理機制?

JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現(xiàn)的,Java中的類加載器是一個重要的Java運行時系統(tǒng)組件,它負責(zé)在運行時查找和裝入類文件中的類。

由于Java的跨平臺性,經(jīng)過編譯的Java源程序并不是一個可執(zhí)行程序,而是一個或多個類文件。當(dāng)Java程序需要使用某個類時,JVM會確保這個類已經(jīng)被加載、連接(驗證、準備和解析)和初始化。

類的加載是指把類的.class文件中的數(shù)據(jù)讀入到內(nèi)存中,通常是創(chuàng)建一個字節(jié)數(shù)組讀入.class文件,然后產(chǎn)生與所加載類對應(yīng)的Class對象。加載完成后,Class對象還不完整,所以此時的類還不可用。當(dāng)類被加載后就進入連接階段,這一階段包括驗證、準備(為靜態(tài)變量分配內(nèi)存并設(shè)置默認的初始值)和解析(將符號引用替換為直接引用)三個步驟。最后JVM對類進行初始化,包括:1)如果類存在直接的父類并且這個類還沒有被初始化,那么就先初始化父類;2)如果類中存在初始化語句,就依次執(zhí)行這些初始化語句。類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統(tǒng)加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程采取了父親委托機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其他的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能為力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。

下面是關(guān)于幾個類加載器的說明:

  • bootstrap:一般用本地代碼實現(xiàn),負責(zé)加載JVM基礎(chǔ)核心類庫(rt.jar);
  • Extension:從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類庫,它的父加載器是Bootstrap;
  • System:又叫應(yīng)用類加載器,其父類是Extension。它是應(yīng)用最廣泛的類加載器。它從環(huán)境變量classpath或者系統(tǒng)屬性java.class.path所指定的目錄中記載類,是用戶自定義加載器的默認父加載器。

 8、Java對象創(chuàng)建過程

  • JVM遇到一條新建對象的指令時首先去檢查這個指令的參數(shù)是否能在常量池中定義到一個類的符號引用。然后加載這個類(類加載過程在后邊講)
  • 為對象分配內(nèi)存。一種辦法"指針碰撞"、一種辦法"空閑列表",最終常用的辦法"本地線程緩沖分配(TLAB)"
  • 將除對象頭外的對象內(nèi)存空間初始化為0
  • 對對象頭進行必要設(shè)置

 9、類的生命周期

類的生命周期包括這幾個部分,加載、連接、初始化、使用和卸載,其中前三部是類的加載的過程,如下圖:

  • 加載,查找并加載類的二進制數(shù)據(jù),在Java堆中也創(chuàng)建一個java.lang.Class類的對象
  • 連接,連接又包含三塊內(nèi)容:驗證、準備、初始化。 1)驗證,文件格式、元數(shù)據(jù)、字節(jié)碼、符號引用驗證; 2)準備,為類的靜態(tài)變量分配內(nèi)存,并將其初始化為默認值; 3)解析,把類中的符號引用轉(zhuǎn)換為直接引用
  • 初始化,為類的靜態(tài)變量賦予正確的初始值
  • 使用,new出對象程序中使用
  • 卸載,執(zhí)行垃圾回收

 10、Java 中會存在內(nèi)存泄漏嗎,請簡單描述。

理論上Java因為有垃圾回收機制(GC)不會存在內(nèi)存泄露問題(這也是Java被廣泛使用于服務(wù)器端編程的一個重要原因);然而在實際開發(fā)中,可能會存在無用但可達的對象,這些對象不能被GC回收,因此也會導(dǎo)致內(nèi)存泄露的發(fā)生。例如hibernate的Session(一級緩存)中的對象屬于持久態(tài),垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,如果不及時關(guān)閉(close)或清空(flush)一級緩存就可能導(dǎo)致內(nèi)存泄露。下面例子中的代碼也會導(dǎo)致內(nèi)存泄露。

import java.util.Arrays;
import java.util.EmptyStackException;
public class MyStack {
    private T[] elements;
    private int size = 0;
    private static final int INIT_CAPACITY = 16;
    public MyStack() {
        elements = (T[]) new Object[INIT_CAPACITY];
    }
    public void push(T elem) {
        ensureCapacity();
        elements[size++] = elem;
    }
    public T pop() {
        if(size == 0)
            throw new EmptyStackException();
        return elements[--size];
    }
    private void ensureCapacity() {
        if(elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

上面的代碼實現(xiàn)了一個棧(先進后出(FILO))結(jié)構(gòu),乍看之下似乎沒有什么明顯的問題,它甚至可以通過你編寫的各種單元測試。 然而其中的pop方法卻存在內(nèi)存泄露的問題,當(dāng)我們用pop方法彈出棧中的對象時,該對象不會被當(dāng)作垃圾回收,即使使用棧的程序不再引用這些對象,因為棧內(nèi)部維護著對這些對象的過期引用(obsolete reference)。在支持垃圾回收的語言中,內(nèi)存泄露是很隱蔽的,這種內(nèi)存泄露其實就是無意識的對象保持。 如果一個對象引用被無意識的保留起來了,那么垃圾回收器不會處理這個對象,也不會處理該對象引用的其他對象,即使這樣的對象只有少數(shù)幾個,也可能會導(dǎo)致很多的對象被排除在垃圾回收之外,從而對性能造成重大影響,極端情況下會引發(fā)Disk Paging(物理內(nèi)存與硬盤的虛擬內(nèi)存交換數(shù)據(jù)),甚至造成OutOfMemoryError。

11、GC是什么?為什么要有GC?

GC是垃圾收集的意思,內(nèi)存處理是編程人員容易出現(xiàn)問題的地方,忘記或者錯誤的內(nèi)存回收會導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動監(jiān)測對象是否超過作用域從而達到自動回收內(nèi)存的目的,Java語言沒有提供釋放已分配內(nèi)存的顯示操作方法。 Java程序員不用擔(dān)心內(nèi)存管理,因為垃圾收集器會自動進行管理。要請求垃圾收集,可以調(diào)用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉顯示的垃圾回收調(diào)用。 垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個單獨的低優(yōu)先級的線程運行,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進行垃圾回收。 在Java誕生初期,垃圾回收是Java最大的亮點之一,因為服務(wù)器端的編程需要有效的防止內(nèi)存泄露問題,然而時過境遷,如今Java的垃圾回收機制已經(jīng)成為被詬病的東西。移動智能終端用戶通常覺得iOS的系統(tǒng)比Android系統(tǒng)有更好的用戶體驗,其中一個深層次的原因就在于Android系統(tǒng)中垃圾回收的不可預(yù)知性。

補充:垃圾回收機制有很多種,包括:分代復(fù)制垃圾回收、標記垃圾回收、增量垃圾回收等方式。標準的Java進程既有棧又有堆。棧保存了原始型局部變量,堆保存了要創(chuàng)建的對象。Java平臺對堆內(nèi)存回收和再利用的基本算法被稱為標記和清除,但是Java對其進行了改進,采用"分代式垃圾收集"。這種方法會跟Java對象的生命周期將堆內(nèi)存劃分為不同的區(qū)域,在垃圾收集過程中,可能會將對象移動到不同區(qū)域:

  • 伊甸園(Eden):這是對象最初誕生的區(qū)域,并且對大多數(shù)對象來說,這里是它們唯一存在過的區(qū)域。
  • 幸存者樂園(Survivor):從伊甸園幸存下來的對象會被挪到這里。
  • 終身頤養(yǎng)園(Tenured):這是足夠老的幸存對象的歸宿。年輕代收集(Minor-GC)過程是不會觸及這個地方的。當(dāng)年輕代收集不能把對象放進終身頤養(yǎng)園時,就會觸發(fā)一次完全收集(Major-GC),這里可能還會牽扯到壓縮,以便為大對象騰出足夠的空間。

與垃圾回收相關(guān)的JVM參數(shù):

  • -Xms / -Xmx — 堆的初始大小 / 堆的最大大小
  • -Xmn — 堆中年輕代的大小
  • -XX:-DisableExplicitGC — 讓System.gc()不產(chǎn)生任何作用
  • -XX:+PrintGCDetails — 打印GC的細節(jié)
  • -XX:+PrintGCDateStamps — 打印GC操作的時間戳
  • -XX:NewSize / XX:MaxNewSize — 設(shè)置新生代大小/新生代最大大小
  • -XX:NewRatio — 可以設(shè)置老生代和新生代的比例
  • -XX:PrintTenuringDistribution — 設(shè)置每次新生代GC后輸出幸存者樂園中對象年齡的分布
  • -XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設(shè)置老年代閥值的初始值和最大值
  • -XX:TargetSurvivorRatio:設(shè)置幸存區(qū)的目標使用率

 12、做GC時,⼀個對象在內(nèi)存各個Space中被移動的順序是什么?

標記清除法,復(fù)制算法,標記整理、分代算法。

新生代一般采用復(fù)制算法 GC,老年代使用標記整理算法。

垃圾收集器:串行新生代收集器、串行老生代收集器、并行新生代收集器、并行老年代收集器。

CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種并發(fā)收集器,采用的是Mark-Sweep算法。

13、你知道哪些垃圾回收算法?

GC最基礎(chǔ)的算法有三種: 標記 -清除算法、復(fù)制算法、標記-壓縮算法,我們常用的垃圾回收器一般都采用分代收集算法。

  • 標記-清除算法,"標記-清除"(Mark-Sweep)算法,如它的名字一樣,算法分為"標記"和"清除"兩個階段:首先標記出所有需要回收的對象,在標記完成后統(tǒng)一回收掉所有被標記的對象。
  • 復(fù)制算法,"復(fù)制"(Copying)的收集算法,它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。
  • 標記-壓縮算法,標記過程仍然與"標記-清除"算法一樣,但后續(xù)步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內(nèi)存
  • 分代收集算法,"分代收集"(Generational Collection)算法,把Java堆分為新生代和老年代,這樣就可以根據(jù)各個年代的特點采用最適當(dāng)?shù)氖占惴ā?/li>

 14、垃圾回收器

  •  Serial收集器,串行收集器是最古老,最穩(wěn)定以及效率高的收集器,可能會產(chǎn)生較長的停頓,只使用一個線程去回收。
  • ParNew收集器,ParNew收集器其實就是Serial收集器的多線程版本。
  • Parallel收集器,Parallel Scavenge收集器類似ParNew收集器,Parallel收集器更關(guān)注系統(tǒng)的吞吐量。
  • Parallel Old 收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和"標記-整理"算法
  • CMS收集器,CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。
  • G1收集器,G1 (Garbage-First)是一款面向服務(wù)器的垃圾收集器,主要針對配備多顆處理器及大容量內(nèi)存的機器. 以極高概率滿足GC停頓時間要求的同時,還具備高吞吐量性能特征

15、如何判斷一個對象是否應(yīng)該被回收

判斷對象是否存活一般有兩種方式:

  • 引用計數(shù):每個對象有一個引用計數(shù)屬性,新增一個引用時計數(shù)加1,引用釋放時計數(shù)減1,計數(shù)為0時可以回收。此方法簡單,無法解決對象相互循環(huán)引用的問題。
  • 可達性分析(Reachability Analysis):從GC Roots開始向下搜索,搜索所走過的路徑稱為引用鏈。當(dāng)一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的,不可達對象。

 16、JVM的永久代中會發(fā)生垃圾回收么?

垃圾回收不會發(fā)生在永久代,如果永久代滿了或者是超過了臨界值,會觸發(fā)完全垃圾回收(Full GC)。如果你仔細查看垃圾收集器的輸出信息,就會發(fā)現(xiàn)永久代也是被回收的。這就是為什么正確的永久代大小對避免Full GC是非常重要的原因。請參考下Java8:從永久代到元數(shù)據(jù)區(qū) (注:Java8中已經(jīng)移除了永久代,新加了一個叫做元數(shù)據(jù)區(qū)的native內(nèi)存區(qū))

17、引用的分類

  •  強引用:GC時不會被回收
  • 軟引用:描述有用但不是必須的對象,在發(fā)生內(nèi)存溢出異常之前被回收
  • 弱引用:描述有用但不是必須的對象,在下一次GC時被回收
  • 虛引用(幽靈引用/幻影引用):無法通過虛引用獲得對象,用PhantomReference實現(xiàn)虛引用,虛引用用來在GC時返回一個通知。

 18、調(diào)優(yōu)命令

Sun JDK監(jiān)控和故障處理命令有jps jstat jmap jhat jstack jinfo

  • jps,JVM Process Status Tool,顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機進程。
  • jstat,JVM statistics Monitoring是用于監(jiān)視虛擬機運行時狀態(tài)信息的命令,它可以顯示出虛擬機進程中的類裝載、內(nèi)存、垃圾收集、JIT編譯等運行數(shù)據(jù)。
  • jmap,JVM Memory Map命令用于生成heap dump文件
  • jhat,JVM Heap Analysis Tool命令是與jmap搭配使用,用來分析jmap生成的dump,jhat內(nèi)置了一個微型的HTTP/HTML服務(wù)器,生成dump的分析結(jié)果后,可以在瀏覽器中查看
  • jstack,用于生成java虛擬機當(dāng)前時刻的線程快照。
  • jinfo,JVM Configuration info 這個命令作用是實時查看和調(diào)整虛擬機運行參數(shù)。

 19、調(diào)優(yōu)工具

常用調(diào)優(yōu)工具分為兩類,jdk自帶監(jiān)控工具:jconsole和jvisualvm,第三方有:MAT(Memory Analyzer Tool)、GChisto。

  • jconsole,Java Monitoring and Management Console是從java5開始,在JDK中自帶的java監(jiān)控和管理控制臺,用于對JVM中內(nèi)存,線程和類等的監(jiān)控
  • jvisualvm,jdk自帶全能工具,可以分析內(nèi)存快照、線程快照;監(jiān)控內(nèi)存變化、GC變化等。
  • MAT,Memory Analyzer Tool,一個基于Eclipse的內(nèi)存分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查找內(nèi)存泄漏和減少內(nèi)存消耗
  • GChisto,一款專業(yè)分析gc日志的工具

20、jstack 是⼲什么的? jstat 呢?如果線上程序周期性地出現(xiàn)卡頓,你懷疑可 能是 GC 導(dǎo)致的,你會怎么來排查這個問題?線程⽇志⼀般你會看其中的什么 部分?

jstack 用來查詢 Java 進程的堆棧信息。

jvisualvm 監(jiān)控內(nèi)存泄露,跟蹤垃圾回收、執(zhí)行時內(nèi)存、cpu分析、線程分析。

21、Minor GC與Full GC分別在什么時候發(fā)生?

新生代內(nèi)存不夠用時候發(fā)生MGC也叫YGC,JVM內(nèi)存不夠的時候發(fā)生FGC

22、你有沒有遇到過OutOfMemory問題?你是怎么來處理這個問題的?處理 過程中有哪些收獲?

permgen space、heap space 錯誤。

常見的原因

  • 內(nèi)存加載的數(shù)據(jù)量太大:一次性從數(shù)據(jù)庫取太多數(shù)據(jù);
  • 集合類中有對對象的引用,使用后未清空,GC不能進行回收;
  • 代碼中存在循環(huán)產(chǎn)生過多的重復(fù)對象;
  • 啟動參數(shù)堆內(nèi)存值小。

23、JDK 1.8之后Perm Space有哪些變動? MetaSpace⼤⼩默認是⽆限的么? 還是你們會通過什么⽅式來指定⼤⼩?

JDK 1.8后用元空間替代了 Perm Space;字符串常量存放到堆內(nèi)存中。

MetaSpace大小默認沒有限制,一般根據(jù)系統(tǒng)內(nèi)存的大小。JVM會動態(tài)改變此值。

-XX:MetaspaceSize:分配給類元數(shù)據(jù)空間(以字節(jié)計)的初始大?。∣racle邏輯存儲上的初始高水位,the initial high-water-mark)。此值為估計值,MetaspaceSize的值設(shè)置的過大會延長垃圾回收時間。垃圾回收過后,引起下一次垃圾回收的類元數(shù)據(jù)空間的大小可能會變大。

-XX:MaxMetaspaceSize:分配給類元數(shù)據(jù)空間的最大值,超過此值就會觸發(fā)Full GC,此值默認沒有限制,但應(yīng)取決于系統(tǒng)內(nèi)存的大小。JVM會動態(tài)地改變此值。

24、StackOverflow異常有沒有遇到過?⼀般你猜測會在什么情況下被觸發(fā)?如何指定⼀個線程的堆棧⼤⼩?⼀般你們寫多少?

棧內(nèi)存溢出,一般由棧內(nèi)存的局部變量過爆了,導(dǎo)致內(nèi)存溢出。出現(xiàn)在遞歸方法,參數(shù)個數(shù)過多,遞歸過深,遞歸沒有出口。

25. Java四引用

強引用(StrongReference)強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它。當(dāng)內(nèi)存空間不足,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內(nèi)存不足的問題

軟引用(SoftReference)
如果內(nèi)存空間不足了,就會回收這些對象的內(nèi)存。只要垃圾回收器沒有回收它,軟引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關(guān)聯(lián)的引用隊列中

弱引用(WeakReference)
弱引用與軟引用的區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當(dāng)前內(nèi)存空間足夠與否,都會回收它的內(nèi)存。
弱引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關(guān)聯(lián)的引用隊列中

虛引用(PhantomReference)
虛引用在任何時候都可能被垃圾回收器回收,主要用來 跟蹤對象被垃圾回收器回收的活動,被回收時會收到一個系統(tǒng)通知 。虛引用與軟引用和弱引用的一個區(qū)別在于:虛引用 必須 和引用隊列 (ReferenceQueue)聯(lián)合使用。當(dāng)垃圾回收器準備回收一個對象時,如果發(fā)現(xiàn)它還有虛引用,就會在回收對象的內(nèi)存之前,把這個虛引用加入到與之關(guān)聯(lián)的引用隊列中。

26. GC 標記對象的死活

引用計數(shù)法:給對象添加一個引用計數(shù)器,沒當(dāng)被引用的時候,計數(shù)器的值就加一。引用失效的時候減一,當(dāng)計數(shù)器的值為 0 的時候就表示改對象可以被 GC 回收了,弊端:A->B,B->A,那么 AB 將永遠不會被回收了。也就是引用有環(huán)的情況

根搜索算法(可達性算法) GC Roots Tracing:通過一個叫 GC Roots 的對象作為起點,從這些結(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈,當(dāng)一個對象沒有與任何的引用鏈相連的時候則改對象就可以被。 GC 回收回收了Roots 包括:java 虛擬機棧中引用的對象,本地方法棧中引用的對象,方法區(qū)中常量引用的對象,方法區(qū)中靜態(tài)屬性引用的對象

在Java語言里,可作為GC Roots的對象包括以下幾種:

  • 虛擬機棧(棧幀中的本地變量表)中的引用的對象
  • 方法區(qū)中的類靜態(tài)屬性引用的對象
  • 方法區(qū)中的常量引用的對象。
  • 本地方法棧中JNI(即一般說的Native方法)的引用的對象。

27. 引起類加載操作的五個行為

  • 遇到new、getstatic、putstatic或invokestatic這四條字節(jié)碼指令
  • 反射調(diào)用的時候,如果類沒有進行過初始化,則需要先觸發(fā)其初始化
  • 子類初始化的時候,如果其父類還沒初始化,則需先觸發(fā)其父類的初始化
  • 虛擬機執(zhí)行主類的時候(有 main(string[] args))
  • JDK1.7 動態(tài)語言支持

28. Java對象創(chuàng)建時機

  • 使用new關(guān)鍵字創(chuàng)建對象
  • 使用Class類的newInstance方法(反射機制)
  • 使用Constructor類的newInstance方法(反射機制)
  • 使用Clone方法創(chuàng)建對象
  • 使用(反)序列化機制創(chuàng)建對象

到此這篇關(guān)于30道有趣的JVM面試題(小結(jié))的文章就介紹到這了,更多相關(guān)JVM面試題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!

相關(guān)文章

  • 10道JVM常見面試題解析(附答案)

    這篇文章主要介紹了10道JVM常見面試題解析(附答案),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)
    2020-09-04
  • JVM相關(guān)面試題及答案(小結(jié))

    這篇文章主要介紹了JVM相關(guān)面試題及答案(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-09-02
  • 2020面試阿里字節(jié)跳動90%被問到的JVM面試題附答案(史上最全)

    這篇文章主要介紹了2020面試阿里字節(jié)跳動90%被問到的JVM面試題附答案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-06-15
  • 2020年JVM高頻率面試題整理

    這篇文章主要介紹了2020年JVM高頻率面試題整理,真是小編下了血本給大家整理出來的,值得大家收藏,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-09
  • JVM面試題小結(jié)(2020最新版)

    這篇文章主要介紹了JVM面試題小結(jié)(2020最新版),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-02-21
  • 2019年JVM面試都問了什么?(附答案解析)

    這篇文章主要介紹了2019年JVM面試都問了什么?(附答案解析),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-12-04
  • Java研發(fā)面試99題(含答案):JVM+Spring+MySQL+線程池+鎖

    這篇文章主要介紹了Java研發(fā)面試99題,主要包括了JVM,Spring,MySQL,線程池,鎖等,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-07-16
  • 講一講JVM的組成(Java經(jīng)典面試題)

    JVM(Java 虛擬機)算是面試必問的問題的了,而但凡問 JVM 一定會問的第一個問題就是:講一講 JVM 的組成?那本文就注重講一下 JVM 的組成,感興趣的可以了解一下
    2019-04-10

最新評論