日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

后台开发人员面试内容——JVM虚拟机(四)

發布時間:2024/9/30 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后台开发人员面试内容——JVM虚拟机(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、Java類加載機制

類從被加載到虛擬機內存中開始,到卸載出內存,它的整個生命周期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initiallization)、使用(Using)和卸載(Unloading)這7個階段。其中驗證、準備、解析3個部分統稱為連接(Linking),這七個階段的發生順序如下圖

1.加載Loading:

1)通過一個類的全限定名來獲取定義此類的二進制字節流。

2)將這個字節流所代表的靜態變量、類信息、常量等內容放入到方法區。

3)在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口。

?

2.驗證Verification:

目的是確保class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身安全,

驗證階段主要包括四個檢驗過程:文件格式驗證、元數據驗證、字節碼驗證和符號引用驗證

?

3.準備Preparation

靜態成員的初始化。準備階段是正式為類變量分配內存并設置其初始值的階段,這些變量所使用的內存都將在方法區中分配。關于這點,有兩個地方注意一下:

1)這時候進行內存分配的僅僅是類變量(被static修飾的變量),而不是實例變量,實例變量將會在對象實例化的時候隨著對象一起分配在Java堆中

2)這個階段賦初始值的變量指的是那些不被final修飾的static變量,比如"public static int value = 123;",value在準備階段過后是0而不是123,給value賦值為123的動作將在初始化階段才進行

?

4.解析Resolution

解析階段是虛擬機常量池內的符號引用替換為直接引用的過程。 Java在編譯階段,會將.java文件編譯成.class文件,在生成的.class文件中,static修飾的靜態變量就是我們常說的符號引用,但是在編譯階段該符號引用并不知道引用類的實際內存地址(虛擬機還沒運行)。直到解析階段,虛擬機加載了該類才能真正解析到具體的內存地址。

?

5.初始化Initialization

初始化階段做的事就是給static變量賦予用戶指定的值以及執行靜態代碼塊

?

二、雙親委派加載

1.類加載器介紹:

從Java開發人員的角度來看,大部分Java程序一般會使用到以下三種系統提供的類加載器:

1)啟動類加載器(Bootstrap ClassLoader):負責加載JAVA_HOME\lib目錄中并且能被虛擬機識別的類庫到JVM內存中,如果名稱不符合的類庫即使放在lib目錄中也不會被加載。該類加載器無法被Java程序直接引用。

2)擴展類加載器(Extension ClassLoader):該加載器主要是負責加載JAVA_HOME\lib\,該加載器可以被開發者直接使用。

3)應用程序類加載器(Application ClassLoader):該類加載器也稱為系統類加載器,它負責加載用戶類路徑(Classpath)上所指定的類庫,開發者可以直接使用該類加載器,如果應用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。?

4)自定義類加載器(必須繼承 ClassLoader)。?

這些類加載器之間的關系如下圖所示:

如上圖所示的類加載器之間的這種層次關系,就稱為類加載器的雙親委派模型(Parent Delegation Model)。該模型要求除了頂層的啟動類加載器外,其余的類加載器都應當有自己的父類加載器。子類加載器和父類加載器不是以繼承(Inheritance)的關系來實現,而是通過組合(Composition)關系來復用父加載器的代碼。

2.雙親委派模型的工作過程為

如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的加載器都是如此,因此所有的類加載請求都會傳給頂層的啟動類加載器,只有當父加載器反饋自己無法完成該加載請求(該加載器的搜索范圍中沒有找到對應的類)時,子加載器才會嘗試自己去加載

3.雙親委派模型?的好處:

使用這種模型來組織類加載器之間的關系的好處是Java類隨著它的類加載器一起具備了一種帶有優先級的層次關系。例如java.lang.Object類,無論哪個類加載器去加載該類,最終都是由啟動類加載器進行加載,因此Object類在程序的各種類加載器環境中都是同一個類。否則的話,如果不使用該模型的話,如果用戶自定義一個java.lang.Object類且存放在classpath中,那么系統中將會出現多個Object類,應用程序也會變得很混亂。如果我們自定義一個rt.jar中已有類的同名Java類,會發現JVM可以正常編譯,但該類永遠無法被加載運行

?

三、JVM運行時數據區

1.堆(Heap)

1)被所有線程共享的一塊內存區域,在虛擬機啟動時創建;

2)用來存儲對象實例;

3)可以通過-Xmx和-Xms控制堆的大小

4) java堆是垃圾收集器管理的主要區域。java堆還可以細分為:新生代(New/Young)、舊生代/年老代(Old/Tenured)

?

2.方法區(Method Area)

1)被所有線程共享的一塊內存區域

2)用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據

?

3.虛擬機棧(VM Stack)

1)線程私有,生命周期與線程相同

2) 存儲方法的局部變量表(基本類型、對象引用)、操作數棧、動態鏈接、方法出口等信息

?

4.本地方法棧(Native?Method?Stack)

與虛擬機棧相似,主要為虛擬機使用到的Native方法服務,在HotSpot虛擬機中直接把本地方法棧與虛擬機棧二合一

?

5.程序計數器(Program?Counter?Register)

1)當前線程所執行的字節碼的行號指示器

2)當前線程私有

?

四、JVM常見配置

-Xss:每個線程的java虛擬機內存大小

1.堆設置

-Xms:初始堆大小

-Xmx:最大堆大小

-XX:NewSize=n:設置年輕代大小

-XX:NewRatio=n:設置年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4

-XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區占整個年輕代的1/5

-XX:MaxPermSize=n:設置持久代大小

2.收集器設置

-XX:+UseSerialGC:設置串行收集器

-XX:+UseParallelGC:設置并行收集器

-XX:+UseParalledlOldGC:設置并行年老代收集器

-XX:+UseConcMarkSweepGC:設置并發收集器

3.垃圾回收統計信息

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename

4.并行收集器設置

-XX:ParallelGCThreads=n:設置并行收集器收集時使用的CPU數。并行收集線程數。

-XX:MaxGCPauseMillis=n:設置并行收集最大暫停時間

-XX:GCTimeRatio=n:設置垃圾回收時間占程序運行時間的百分比。公式為1/(1+n)

5.并發收集器設置

-XX:+CMSIncrementalMode:設置為增量模式。適用于單CPU情況。

-XX:ParallelGCThreads=n:設置并發收集器年輕代收集方式為并行收集時,使用的CPU數。并行收集線程數

?

五、JVM垃圾回收機制

1.Java中的四種引用類型

1)強引用. 這里的o就是一個強引用,也是我們用得最多的引用,在實例化類的時候經常會用到。遇到這類引用,GC(垃圾回收器)是絕對不會回收它的。當遇到內存不足的情況,JVM會拋出OOM異常。所以,在不使用這類對象的時候要注意釋放它,以便讓系統回收

Object o = new Object();

2)軟引用. 這里的s就是一個軟引用,它是用來描述一些有用但非必需的對象。如果一個對象只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存

?

SoftReference<String> s = new SoftReference<>(new String("Hello"));

System.out.println(s.get());

3)弱引用。只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存

WeakReference<String> w = new WeakReference<>(new String("Hello"));

System.out.println(w.get());

System.gc();

System.out.println(w.get());

4)虛引用。與其他幾種引用都不同,虛引用并不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用,一樣,在任何時候都可能被垃圾回收器回收。 它唯一的作用就是就是用于追蹤,讓我們能夠在這個對象被回收的時候收到一個通知。

ReferenceQueue<String> queue = new ReferenceQueue<>();

PhantomReference<String> pr = new PhantomReference<>(new String("Hello"), queue);

System.out.println(pr.get());

?

2.如何判斷對象需要被回收

1)引用計數法。 在對象內部會有一個引用計數器,一旦某個地方引用它時,計數器就加1。 計數器表示的是對象的人氣指數,也就是有多少程序引用了這個對象(被引用數)。下圖是引用計數法中的對象。

、

2)可達性分析法。 所謂可達性分析就是通過一系列被稱為“GC Roots”的點作為起始點,從這些節點開始向下搜索,搜索的路徑稱為引用鏈,當一個對象到GC Roots不可達的時候,則證明此對象是可回收的

?

3.垃圾回收算法

回收機制——隔代收集法

新生代

復制法:新生代活躍對象多,先將內存分為兩個部分,From區和To區,兩部分大小相等。對象分配時,只會在From區進行分配。復制算法可以分兩步,第一步為類似標記清除算法的標記,在From區中,找出所有活動的對象。區別在于第二步。復制算法會把這些活動的對象,復制到To區中,再將原有的From區全部清空,并交換兩部分內存的職責,即一次GC后,原有的From區會成為To區,To區相反

優點:效率高 、高速分配、不會發生碎片化;GC后的內存空間是連續的。

缺點:堆使用效率低下,把堆二等分, 真正存放新對象的內存區域會變少,只有一半堆能夠存放對象

老年代(永久代):

標記-整理法:分為標記和整理兩個階段: 標記所有從根節點開始的遍歷到的存活對象,讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內存

標記—清除法:分為標記和清除兩個階段: 標記所有從根節點開始的遍歷到的存活對象,在標記完成后,清除所有未被標記的對象

優點:有效利用堆,能夠在整個堆中進行操作

缺點:壓縮花費時間,清楚和壓縮都會搜索堆,浪費時間,沒有壓縮的話會產生碎片化問題,對象存儲不連續。

4.垃圾收集器

?

名稱

工作區域

單線程/多線程

垃圾收集算法

描述

Serial收集器

新生代

單線程

復制算法

進行垃圾收集時,必須暫停其他所有的工作線程,直到它收集結束

ParNew收集器

(Serial收集器的多線程版本)

新生代

多線程

復制算法

并行:指多條垃圾收集線程并行工作,但此時用戶線程仍然處于等待狀態;

并發:指用戶線程與垃圾收集線程同時執行?

Parallel Scavenge收集器

新生代

多線程

復制算法

吞吐量優先收集器

目標:控制吞吐量

Serial Old收集器

老年代

單線程

標記整理算法

主要意義也是在于給Client模式下的虛擬機使用

Parallel Old收集器

老年代

多線程

標記整理算法

Parallel Old?是Parallel Scavenge收集器的老年代版本

1.6之后,“吞吐量優先“收集器組合:Parallel Scavenge + Parallel Old

CMS收集器

老年代

多線程

標記-清除算法

目標:最短回收停頓時間

優點:并發收集,低停頓

缺點:CPU資源敏感;無法處理浮動垃圾;內存碎片問題

5.內存分配策略

Minor GC 和 Full GC

  • Minor GC:回收新生代,因為新生代對象存活時間很短,因此 Minor GC 會頻繁執行,執行的速度一般也會比較快。
  • Full GC:回收老年代和新生代,老年代對象其存活時間長,因此 Full GC 很少執行,執行速度會比 Minor GC 慢很多

1)對象優先在Eden上分配,當Eden上內存不夠時,發起Minor?GC

2)大對象和長期存活的對象進入老年代

3)? 長期存活的對象將進入老年代

3)調用System.gc()時,建議虛擬機執行Full?GC,老年代空間不足也會執行Full?GC

?

總結

以上是生活随笔為你收集整理的后台开发人员面试内容——JVM虚拟机(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。