中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

JVM面試真題有哪些

發布時間:2021-12-31 14:20:40 來源:億速云 閱讀:127 作者:iii 欄目:大數據

本篇內容主要講解“JVM面試真題有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JVM面試真題有哪些”吧!

第一題:JVM內存相關(百度)

問:JVM內存模型了解嗎,簡單說下

答:

因為這塊內容太多了,許多小伙伴可能記不住這么多,所以下面的答案分為簡答和精答

JVM 運行時內存共分為程序計數器,Java虛擬機棧,本地方法棧,堆,方法區五個部分:

JVM面試真題有哪些

jdk 1.8 同 jdk 1.7 比,最大的差別就是:元數據區取代了永久代。元空間的本質和永久代類似,都是對JVM規范中方法區的實現。不過元空間與永久代之間最大的區別在于:元數據空間并不在虛擬機中,而是使用本地內存

第二題:類加載相關(新浪微博)

問:jvm加載類的過程主要有哪些,具體怎么加載?

答:

簡答:類加載過程即是指JVM虛擬機把.class文件中類信息加載進內存,并進行解析生成對應的class對象的過程。分為五個步驟:加載 -> 驗證 -> 準備 -> 解析 -> 初始化。加載:將外部的 .class 文件加載到Java虛擬機中;驗證:確保加載進來的 calss 文件包含的額信息符合 Java 虛擬機的要求;準備:為類變量分配內存,設置類變量的初始值;解析:將常量池內的符號引用 轉為 直接引用;初始化:初始化類變量和靜態代碼塊。

精答前方預警,內容較長,做好準備

一個Java文件從編碼完成到最終執行,一般主要包括兩個過程:編譯、運行

  • 編譯:即把我們寫好的java文件,通過javac命令編譯成字節碼,也就是我們常說的.class文件。

  • 運行:則是把編譯生成的.class文件交給Java虛擬機(JVM)執行。

而我們所說的類加載過程即是指JVM虛擬機把.class文件中類信息加載進內存,并進行解析生成對應的class對象的過程。

  • 類加載過程

舉個簡單的例子來說,JVM在執行某段代碼時,遇到了class A, 然而此時內存中并沒有class A的相關信息,于是JVM就會到相應的class文件中去尋找class A的類信息,并加載進內存中,這就是我們所說的類加載過程。
由此可見,JVM不是一開始就把所有的類都加載進內存中,而是只有第一次遇到某個需要運行的類時才會加載,且只加載一次。

  • 類加載

類加載的過程主要分為三個部分:加載、鏈接、初始化

而鏈接又可以細分為三個小部分:驗證、準備、解析

  • 加載

簡單來說,加載指的是把class字節碼文件從各個來源通過類加載器裝載入內存中。

這里有兩個重點:

字節碼來源:一般的加載來源包括從本地路徑下編譯生成的.class文件,從jar包中的.class文件,從遠程網絡,以及動態代理實時編譯

類加載器:一般包括啟動類加載器,擴展類加載器,應用類加載器,以及用戶的自定義類加載器。

注:為什么會有自定義類加載器?
一方面是由于java代碼很容易被反編譯,如果需要對自己的代碼加密的話,可以對編譯后的代碼進行加密,然后再通過實現自己的自定義類加載器進行解密,最后再加載。
另一方面也有可能從非標準的來源加載代碼,比如從網絡來源,那就需要自己實現一個類加載器,從指定源進行加載。

  • 驗證

主要是為了保證加載進來的字節流符合虛擬機規范,不會造成安全錯誤。

包括對于文件格式的驗證,比如常量中是否有不被支持的常量?文件中是否有不規范的或者附加的其他信息?

對于元數據的驗證,比如該類是否繼承了被final修飾的類?類中的字段,方法是否與父類沖突?是否出現了不合理的重載?

對于字節碼的驗證,保證程序語義的合理性,比如要保證類型轉換的合理性。

對于符號引用的驗證,比如校驗符號引用中通過全限定名是否能夠找到對應的類?校驗符號引用中的訪問性(private,public等)是否可被當前類訪問?

  • 準備

主要是為類變量(注意,不是實例變量)分配內存,并且賦予初值。

特別需要注意,初值,不是代碼中具體寫的初始化的值,而是Java虛擬機根據不同變量類型的默認初始值。

比如8種基本類型的初值,默認為0;引用類型的初值則為null;常量的初值即為代碼中設置的值,final
static tmp = 456, 那么該階段tmp的初值就是456。

  • 解析

將常量池內的符號引用替換為直接引用的過程。

兩個重點:

符號引用:即一個字符串,但是這個字符串給出了一些能夠唯一性識別一個方法,一個變量,一個類的相關信息。

直接引用:可以理解為一個內存地址,或者一個偏移量。比如類方法,類變量的直接引用是指向方法區的指針;而實例方法,實例變量的直接引用則是從實例的頭指針開始算起到這個實例變量位置的偏移量。

舉個例子來說,現在調用方法hello(),這個方法的地址是1234567,那么hello就是符號引用,1234567就是直接引用。

在解析階段,虛擬機會把所有的類名,方法名,字段名這些符號引用替換為具體的內存地址或偏移量,也就是直接引用。

  • 初始化

這個階段主要是對類變量初始化,是執行類構造器的過程。
換句話說,只對static修飾的變量或語句進行初始化。
如果初始化一個類的時候,其父類尚未初始化,則優先初始化其父類。
如果同時包含多個靜態變量和靜態代碼塊,則按照自上而下的順序依次執行。

  • 總結

類加載過程只是一個類生命周期的一部分,在其前,有編譯的過程,只有對源代碼編譯之后,才能獲得能夠被虛擬機加載的字節碼文件;在其后還有具體的類使用過程,當使用完成之后,還會在方法區垃圾回收的過程中進行卸載。如果想要了解Java類整個生命周期的話,可以自行上網查閱相關資料,這里不再多做贅述。

第三題:JVM內存相關(云從科技)

問:Java 中會存在內存泄漏嗎,請簡單描述

答:

理論上Java因為有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被廣泛使用于服務器端編程的一個重要原因);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收也會發生內存泄露

一個例子就是Hibernate的Session(一級緩存)中的對象屬于持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象。

下面的例子也展示了Java中發生內存泄露的情況:

package com.yuan_more;import java.util.Arrays;import java.util.EmptyStackException;public class MyStack<T> {
    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();
    }

    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);
        }
    }
}

上面的代碼實現了一個棧(先進后出(FILO))結構,乍看之下似乎沒有什么明顯的問題,它甚至可以通過你編寫的各種單元測試。

然而其中的pop方法卻存在內存泄露的問題,當我們用pop方法彈出棧中的對象時,該對象不會被當作垃圾回收,即使使用棧的程序不再引用這些對象,因為棧內部維護著對這些對象的過期引用(obsolete reference)。

在支持垃圾回收的語言中,內存泄露是很隱蔽的,這種內存泄露其實就是無意識的對象保持。

如果一個對象引用被無意識的保留起來了,那么垃圾回收器不會處理這個對象,也不會處理該對象引用的其他對象,即使這樣的對象只有少數幾個,也可能會導致很多的對象被排除在垃圾回收之外,從而對性能造成重大影響,極端情況下會引發Disk Paging(物理內存與硬盤的虛擬內存交換數據),甚至造成OutOfMemoryError。

第四題:垃圾回收相關(滴滴出行)

問:知道 GC 嗎?為什么要有 GC?

答:

GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰。

Java提供的 GC 功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。Java程序員不用擔心內存管理,因為垃圾收集器會自動進行管理

要請求垃圾收集,可以調用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,注意,只是請求,JVM何時進行垃圾回收具有不可預知性

垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低優先級的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。

在Java誕生初期,垃圾回收是Java最大的亮點之一,因為服務器端的編程需要有效的防止內存泄露問題,然而時過境遷,如今Java的垃圾回收機制已經成為被詬病的東西。移動智能終端用戶通常覺得iOS的系統比Android系統有更好的用戶體驗,其中一個深層次的原因就在于Android系統中垃圾回收的不可預知性。

第五題:JVM內存相關(阿里)

問:Hotspot虛擬機中的堆為什么要有新生代和老年代?

答:

因為有的對象壽命長,有的對象壽命短。應該將壽命長的對象放在一個區,壽命短的對象放在一個區。不同的區采用不同的垃圾收集算法。壽命短的區清理頻次高一點,壽命長的區清理頻次低一點,提高效率。

所謂的新生代和老年代是針對于分代收集算法來定義的,新生代又分為Eden和Survivor兩個區。加上老年代就這三個區

數據會首先分配到Eden區當中,當然也有特殊情況,如果是大對象那么會直接放入到老年代(大對象是指需要大量連續內存空間的java對象)。當Eden沒有足夠空間的時候就會觸發jvm發起一次Minor GC。新生代垃圾回收采用的是復制算法

如果對象經過一次Minor GC還存活,并且又能被Survivor空間接受,那么將被移動到Survivor空間當中。并將其年齡設為1,對象在Survivor每熬過一次Minor GC,年齡就加1,當年齡達到一定的程度(默認為15)時,就會被晉升到老年代中了,當然晉升老年代的年齡是可以設置的。如果老年代滿了就執行:Full GC, 因為不經常執行,因此老年代垃圾回收采用了標記-整理(Mark-Compact)算法

到此,相信大家對“JVM面試真題有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

jvm
AI

峡江县| 调兵山市| 称多县| 武宁县| 邹平县| 醴陵市| 汝南县| 花莲市| 双桥区| 天镇县| 平凉市| 梅州市| 延庆县| 潢川县| 中宁县| 漯河市| 镇巴县| 隆化县| 沅江市| 宜宾县| 汉阴县| 富宁县| 凤冈县| 会理县| 班玛县| 兴文县| 屯昌县| 丁青县| 肇庆市| 鄄城县| 新疆| 南康市| 安陆市| 张家口市| 怀仁县| 鄂尔多斯市| 沧州市| 佛冈县| 微博| 广汉市| 昌江|