亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java程序員面試BAT大廠,逃脫不了JVM,7月最新20道JVM面試題

發布時間:2020-06-13 19:00:00 來源:網絡 閱讀:283 作者:架構師追風 欄目:編程語言

很多人說JVM是不是真的要學?面試官都會問JVM的問題嗎?很重要嗎?
的確很重要。
隨著互聯網的發展,高并發高可用、快速響應成為軟件的必須,而JVM與這些有著密切關聯。
我們在盡情享受Java虛擬機帶來好處的同時,還應該去了解和思考“這些技術特性是如何實現的”,去了解最底層的原理。只有熟悉JVM,你才能在遇到OutOfMemory等異常時,不會束手無策,不會一臉懵逼的上網找解決辦法,最后就算改了幾個啟動參數解決了問題,也還是云里霧里。
其實,“為什么學Java虛擬機”這個問題,就和“為什么要學習數據結構和算法”是一個道理:工欲善其事,必先利其器。可以說,Java虛擬機就是每一位Java工程師進階加薪的利器,你想往上升,你想深入技術,不想一直停留在簡單開發,或者你在做Java性能分析、調優工作時,那么,Java虛擬機絕對是一把助力的利劍。
Java程序員面試BAT大廠,逃脫不了JVM,7月最新20道JVM面試題

1.內存模型以及分區,需要詳細到每個區放什么。
JVM 分為堆區和棧區,還有方法區,初始化的對象放在堆里面,引用放在棧里面,class類信息常量池(static常量和static變量)等放在方法區
new:
方法區:主要是存儲類信息,常量池(static常量和static變量),編譯后的代碼(字節碼)等數據

堆:初始化的對象,成員變量 (那種非static的變量),所有的對象實例和數組都要在堆上分配

棧:棧的結構是棧幀組成的,調用一個方法就壓入一幀,幀上面存儲局部變量表,操作數棧,方法出口等信息,局部變量表存放的是8大基礎類型加上一個應用類型,所以還是一個指向地址的指針

本地方法棧:主要為Native方法服務

程序計數器:記錄當前線程執行的行號

2.堆里面的分區:Eden,survival (from+ to),老年代,各自的特點。
堆里面分為新生代和老生代(java8取消了永久代,采用了Metaspace),新生代包含Eden+Survivor區,survivor區里面分為from和to區,內存回收時,如果用的是復制算法,從from復制到to,當經過一次或者多次GC之后,存活下來的對象會被移動到老年區,當JVM內存不夠用的時候,會觸發Full GC,清理JVM老年區

當新生區滿了之后會觸發YGC,先把存活的對象放到其中一個Survice 區,然后進行垃圾清理。因為如果僅僅清理需要刪除的對象,這樣會導致內存碎 片,因此一般會把Eden 進行完全的清理,然后整理內存。那么下次GC 的時候, 就會使用下一個Survive,這樣循環使用。如果有特別大的對象,新生代放不下, 就會使用老年代的擔保,直接放到老年代里面。因為JVM 認為,一般大對象的存 活時間一般比較久遠。
Java程序員面試BAT大廠,逃脫不了JVM,7月最新20道JVM面試題

3.對象創建方法,對象的內存分配,對象的訪問定位。
new 一個對象

4.GC的兩種判定方法:
引用計數法:指的是如果某個地方引用了這個對象就+1,如果失效了就-1,當為0就會回收但是JVM沒有用這種方式,因為無法判定相互循環引用(A引用B,B引用A)的情況

引用鏈法: 通過一種GC ROOT的對象(方法區中靜態變量引用的對象等-static變量)來判斷,如果有一條鏈能夠到達GC ROOT就說明,不能到達GC ROOT就說明可以回收

5.SafePoint是什么

比如GC的時候必須要等到Java線程都進入到safepoint的時候VMThread才能開始執行GC,
循環的末尾 (防止大循環的時候一直不進入safepoint,而其他線程在等待它進入safepoint)

方法返回前

調用方法的call之后

拋出異常的位置
Java程序員面試BAT大廠,逃脫不了JVM,7月最新20道JVM面試題

6.GC的三種收集方法:標記清除、標記整理、復制算法的原理與特點,分別用在什么地方,如果讓你優化收集方法,有什么思路?
先標記,標記完畢之后再清除,效率不高,會產生碎片

復制算法:分為8:1的Eden區和survivor區,就是上面談到的YGC

標記整理:標記完畢之后,讓所有存活的對象向一端移動

7.GC收集器有哪些?CMS收集器與G1收集器的特點
并行收集器:串行收集器使用一個單獨的線程進行收集,GC時服務有停頓時間

串行收集器:次要回收中使用多線程來執行

CMS收集器是基于“標記—清除”算法實現的,經過多次標記才會被清除

G1從整體來看是基于“標記—整理”算法實現的收集器,從局部(兩個Region之間)上來看是基于“復制”算法實現的

8.Minor GC與Full GC分別在什么時候發生?
新生代內存不夠用時候發生MGC也叫YGC,JVM內存不夠的時候發生FGC

9.幾種常用的內存調試工具:jmap、jstack、jconsole、jhat

jstack 可以看當前棧的情況,jmap 查看內存,jhat 進行 dump 堆的信息

mat(eclipse 的也要了解一下)

10.類加載的幾個過程
加載、驗證、準備、解析、初始化。然后是使用和卸載了
通過全限定名來加載生成 class 對象到內存中,然后進行驗證這個 class 文件,包括文
件格式校驗、元數據驗證,字節碼校驗等。準備是對這個對象分配內存。解析是將符
號引用轉化為直接引用(指針引用),初始化就是開始執行構造器的代碼

11.JVM內存分哪幾個區,每個區的作用是什么?
java 虛擬機主要分為以下一個區:
方法區:

  1. 有時候也成為永久代,在該區內很少發生垃圾回收,但是并不代表不發生 GC,在這里
    進行的 GC 主要是對方法區里的常量池和對類型的卸載
  2. 方法區主要用來存儲已被虛擬機加載的類的信息、常量、靜態變量和即時編譯器編譯后
    的代碼等數據。
  3. 該區域是被線程共享的。
  4. 方法區里有一個運行時常量池,用于存放靜態編譯產生的字面量和符號引用。該常量池
    具有動態性,也就是說常量并不一定是編譯時確定,運行時生成的常量也會存在這個常量
    池中。
    虛擬機棧:
  5. 虛擬機棧也就是我們平常所稱的棧內存,它為 java 方法服務,每個方法在執行的時候都
    會創建一個棧幀,用于存儲局部變量表、操作數棧、動態鏈接和方法出口等信息。
  6. 虛擬機棧是線程私有的,它的生命周期與線程相同。
  7. 局部變量表里存儲的是基本數據類型、returnAddress 類型(指向一條字節碼指令的地
    址)和對象引用,這個對象引用有可能是指向對象起始地址的一個指針,也有可能是代表
    對象的句柄或者與對象相關聯的位置。局部變量所需的內存空間在編譯器間確定
    4.操作數棧的作用主要用來存儲運算結果以及運算的操作數,它不同于局部變量表通過索
    引來訪問,而是壓棧和出棧的方式
    5.每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是為了
    支持方法調用過程中的動態連接.動態鏈接就是將常量池中的符號引用在運行期轉化為直接
    引用。
    本地方法棧
    本地方法棧和虛擬機棧類似,只不過本地方法棧為 Native 方法服務。

    java 堆是所有線程所共享的一塊內存,在虛擬機啟動時創建,幾乎所有的對象實例都在這
    里創建,因此該區域經常發生垃圾回收操作。
    程序計數器
    內存空間小,字節碼解釋器工作時通過改變這個計數值可以選取下一條需要執行的字節碼
    指令,分支、循環、跳轉、異常處理和線程恢復等功能都需要依賴這個計數器完成。該內
    存區域是唯一一個 java 虛擬機規范沒有規定任何 OOM 情況的區域。

12.如和判斷一個對象是否存活?(或者GC對象的判定方法)
判斷一個對象是否存活有兩種方法:

  1. 引用計數法
    所謂引用計數法就是給每一個對象設置一個引用計數器,每當有一個地方引用這個對象
    時,就將計數器加一,引用失效時,計數器就減一。當一個對象的引用計數器為零時,說
    明此對象沒有被引用,也就是“死對象”,將會被垃圾回收.
    引用計數法有一個缺陷就是無法解決循環引用問題,也就是說當對象 A 引用對象 B,對象
    B 又引用者對象 A,那么此時 A,B 對象的引用計數器都不為零,也就造成無法完成垃圾回
    收,所以主流的虛擬機都沒有采用這種算法。
    2.可達性算法(引用鏈法)
    該算法的思想是:從一個被稱為 GC Roots 的對象開始向下搜索,如果一個對象到 GC
    Roots 沒有任何引用鏈相連時,則說明此對象不可用。
    在 java 中可以作為 GC Roots 的對象有以下幾種:

虛擬機棧中引用的對象
方法區類靜態屬性引用的對象
方法區常量池引用的對象
本地方法棧 JNI 引用的對象
雖然這些算法可以判定一個對象是否能被回收,但是當滿足上述條件時,一個對象比不一
定會被回收。當一個對象不可達 GC Root 時,這個對象并
不會立馬被回收,而是出于一個死緩的階段,若要被真正的回收需要經歷兩次標記
如果對象在可達性分析中沒有與 GC Root 的引用鏈,那么此時就會被第一次標記并且進行
一次篩選,篩選的條件是是否有必要執行 finalize()方法。當對象沒有覆蓋 finalize()方法
或者已被虛擬機調用過,那么就認為是沒必要的。
如果該對象有必要執行 finalize()方法,那么這個對象將會放在一個稱為 F-Queue 的對隊
列中,虛擬機會觸發一個 Finalize()線程去執行,此線程是低優先級的,并且虛擬機不會承
諾一直等待它運行完,這是因為如果 finalize()執行緩慢或者發生了死鎖,那么就會造成 F-
Queue 隊列一直等待,造成了內存回收系統的崩潰。GC 對處于 F-Queue 中的對象進行
第二次被標記,這時,該對象將被移除”即將回收”集合,等待回收。

13.簡述java垃圾回收機制?
在 java 中,程序員是不需要顯示的去釋放一個對象的內存的,而是由虛擬機自行執行。在
JVM 中,有一個垃圾回收線程,它是低優先級的,在正常情況下是不會執行的,只有在虛
擬機空閑或者當前堆內存不足時,才會觸發執行,掃面那些沒有被任何引用的對象,并將
它們添加到要回收的集合中,進行回收。

14.java中垃圾收集的方法有哪些?

  1. 標記-清除:
    這是垃圾收集算法中最基礎的,根據名字就可以知道,它的思想就是標記哪些要被
    回收的對象,然后統一回收。這種方法很簡單,但是會有兩個主要問題:1.效率不
    高,標記和清除的效率都很低;2.會產生大量不連續的內存碎片,導致以后程序在
    分配較大的對象時,由于沒有充足的連續內存而提前觸發一次 GC 動作。
  2. 復制算法:
    為了解決效率問題,復制算法將可用內存按容量劃分為相等的兩部分,然后每次只
    使用其中的一塊,當一塊內存用完時,就將還存活的對象復制到第二塊內存上,然
    后一次性清楚完第一塊內存,再將第二塊上的對象復制到第一塊。但是這種方式,
    內存的代價太高,每次基本上都要浪費一般的內存。
    于是將該算法進行了改進,內存區域不再是按照 1:1 去劃分,而是將內存劃分為
    8:1:1 三部分,較大那份內存交 Eden 區,其余是兩塊較小的內存區叫 Survior 區。
    每次都會優先使用 Eden 區,若 Eden 區滿,就將對象復制到第二塊內存區上,然
    后清除 Eden 區,如果此時存活的對象太多,以至于 Survivor 不夠時,會將這些對
    象通過分配擔保機制復制到老年代中。(java 堆又分為新生代和老年代)
  3. 標記-整理
    該算法主要是為了解決標記-清除,產生大量內存碎片的問題;當對象存活率較高
    時,也解決了復制算法的效率問題。它的不同之處就是在清除對象的時候現將可回
    收對象移動到一端,然后清除掉端邊界以外的對象,這樣就不會產生內存碎片了。
  4. 分代收集
    現在的虛擬機垃圾收集大多采用這種方式,它根據對象的生存周期,將堆分為新生
    代和老年代。在新生代中,由于對象生存期短,每次回收都會有大量對象死去,那
    么這時就采用復制算法。老年代里的對象存活率較高,沒有額外的空間進行分配擔
    保,所以可以使用標記-整理 或者 標記-清除。

15.java內存模型
java 內存模型(JMM)是線程間通信的控制機制.JMM 定義了主內存和線程之間抽象關系。
線程之間的共享變量存儲在主內存(main memory)中,每個線程都有一個私有的本地
內存(local memory),本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是
JMM 的一個抽象概念,并不真實存在。它涵蓋了緩存,寫緩沖區,寄存器以及其他的硬
件和編譯器優化。Java 內存模型的抽象示意圖如下:
從上圖來看,線程 A 與線程 B 之間如要通信的話,必須要經歷下面 2 個步驟:

  1. 首先,線程 A 把本地內存 A 中更新過的共享變量刷新到主內存中去。
  2. 然后,線程 B 到主內存中去讀取線程 A 之前已更新過的共享變量。

16.java類加載過程?
java 類加載需要經歷一下 7 個過程:
加載
加載時類加載的第一個過程,在這個階段,將完成一下三件事情:

  1. 通過一個類的全限定名獲取該類的二進制流。
  2. 將該二進制流中的靜態存儲結構轉化為方法去運行時數據結構。
  3. 在內存中生成該類的 Class 對象,作為該類的數據訪問入口。
    驗證
    驗證的目的是為了確保 Class 文件的字節流中的信息不回危害到虛擬機.在該階段主要完成
    以下四鐘驗證:
  4. 文件格式驗證:驗證字節流是否符合 Class 文件的規范,如主次版本號是否在當前虛擬
    機范圍內,常量池中的常量是否有不被支持的類型.
  5. 元數據驗證:對字節碼描述的信息進行語義分析,如這個類是否有父類,是否集成了不
    被繼承的類等。
  6. 字節碼驗證:是整個驗證過程中最復雜的一個階段,通過驗證數據流和控制流的分析,
    確定程序語義是否正確,主要針對方法體的驗證。如:方法中的類型轉換是否正確,跳轉
    指令是否正確等。
  7. 符號引用驗證:這個動作在后面的解析過程中發生,主要是為了確保解析動作能正確執
    行。
    準備
    準備階段是為類的靜態變量分配內存并將其初始化為默認值,這些內存都將在方法區中進
    行分配。準備階段不分配類中的實例變量的內存,實例變量將會在對象實例化時隨著對象
    一起分配在 Java 堆中。
    public static int value=123; //在準備階段 value 初始值為 0 。在初始化階段才會變
    為 123 。

解析
該階段主要完成符號引用到直接引用的轉換動作。解析動作并不一定在初始化動作完成之
前,也有可能在初始化之后。
初始化
初始化時類加載的最后一步,前面的類加載過程,除了在加載階段用戶應用程序可以通過
自定義類加載器參與之外,其余動作完全由虛擬機主導和控制。到了初始化階段,才真正
開始執行類中定義的 Java 程序代碼。

17. 簡述java類加載機制?
虛擬機把描述類的數據從 Class 文件加載到內存,并對數據進行校驗,解析和初始化,最
終形成可以被虛擬機直接使用的 java 類型。

18. 類加載器雙親委派模型機制?
當一個類收到了類加載請求時,不會自己先去加載這個類,而是將其委派給父類,由父類
去加載,如果此時父類不能加載,反饋給子類,由子類去完成類的加載。

19.什么是類加載器,類加載器有哪些?
實現通過類的權限定名獲取該類的二進制字節流的代碼塊叫做類加載器。
主要有一下四種類加載器:

  1. 啟動類加載器(Bootstrap ClassLoader)用來加載 java 核心類庫,無法被 java 程序直接
    引用。
  2. 擴展類加載器(extensions class loader):它用來加載 Java 的擴展庫。Java 虛擬機的
    實現會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類。
  3. 系統類加載器(system class loader):它根據 Java 應用的類路徑(CLASSPATH)
    來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過
    ClassLoader.getSystemClassLoader()來獲取它。
  4. 用戶自定義類加載器,通過繼承 java.lang.ClassLoader 類的方式實現。

20.簡述java內存分配與回收策率以及Minor GC和Major GC

  1. 對象優先在堆的 Eden 區分配。
  2. 大對象直接進入老年代.
  3. 長期存活的對象將直接進入老年代.
    當 Eden 區沒有足夠的空間進行分配時,虛擬機會執行一次 Minor GC.Minor Gc 通
    常發生在新生代的 Eden 區,在這個區的對象生存期短,往往發生 Gc 的頻率較高,
    回收速度比較快;Full Gc/Major GC 發生在老年代,一般情況下,觸發老年代 GC
    的時候不會觸發 Minor GC,但是通過配置,可以在 Full GC 之前進行一次 Minor
    GC 這樣可以加快老年代的回收速度。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

湘乡市| 百色市| 金塔县| 信丰县| 建昌县| 盐池县| 和林格尔县| 迭部县| 德阳市| 枣庄市| 北碚区| 手机| 武汉市| 丹阳市| 罗定市| 麟游县| 黔东| 桓仁| 梁河县| 淳化县| 息烽县| 宜昌市| 西平县| 长垣县| 古田县| 交城县| 民丰县| 淅川县| 白山市| 巧家县| 天长市| 米林县| 嘉定区| 洛浦县| 沂水县| 镇安县| 东阳市| 九寨沟县| 顺平县| 红安县| 曲松县|