摘要:執(zhí)行引擎作用執(zhí)行字節(jié)碼,或者執(zhí)行本地方法運(yùn)行時數(shù)據(jù)區(qū)其實(shí)就是指在運(yùn)行期間,其對內(nèi)存空間的劃分和分配。
雖是讀書筆記,但是如轉(zhuǎn)載請注明出處https://uestc-dpz.github.io
..拒絕伸手復(fù)制黨
Java 虛擬機(jī) Java 虛擬機(jī)(Java virtual machine,JVM)是運(yùn)行 Java 程序必不可少的機(jī)制。JVM實(shí)現(xiàn)了Java語言最重要的特征:即平臺無關(guān)性。原理:編譯后的 Java 程序指令并不直接在硬件系統(tǒng)的 CPU 上執(zhí)行,而是由 JVM 執(zhí)行。JVM屏蔽了與具體平臺相關(guān)的信息,使Java語言編譯程序只需要生成在JVM上運(yùn)行的目標(biāo)字節(jié)碼(.class),就可以在多種平臺上不加修改地運(yùn)行。Java 虛擬機(jī)在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機(jī)器指令執(zhí)行。因此實(shí)現(xiàn)java平臺無關(guān)性。它是 Java 程序能在多平臺間進(jìn)行無縫移植的可靠保證,同時也是 Java 程序的安全檢驗(yàn)引擎(還進(jìn)行安全檢查)。
JVM 是 編譯后的 Java 程序(.class文件)和硬件系統(tǒng)之間的接口 ( 編譯后:javac 是收錄于 JDK 中的 Java 語言編譯器。該工具可以將后綴名為. java 的源文件編譯為后綴名為. class 的可以運(yùn)行于 Java 虛擬機(jī)的字節(jié)碼。)
JVM architecture:
圖片摘自 http://javapapers.com/java/ja...
JVM = 類加載器 classloader + 執(zhí)行引擎 execution engine + 運(yùn)行時數(shù)據(jù)區(qū)域 runtime data area
classloader 把硬盤上的class 文件加載到JVM中的運(yùn)行時數(shù)據(jù)區(qū)域, 但是它不負(fù)責(zé)這個類文件能否執(zhí)行,而這個是 執(zhí)行引擎 負(fù)責(zé)的。
作用:裝載.class文件
classloader 有兩種裝載class的方式 (時機(jī)):
隱式:運(yùn)行過程中,碰到new方式生成對象時,隱式調(diào)用classLoader到JVM
顯式:通過class.forname()動態(tài)加載
雙親委派模型(Parent Delegation Model):
類的加載過程采用雙親委托機(jī)制,這種機(jī)制能更好的保證 Java 平臺的安全。
該模型要求除了頂層的Bootstrap class loader啟動類加載器外,其余的類加載器都應(yīng)當(dāng)有自己的父類加載器。子類加載器和父類加載器不是以繼承(Inheritance)的關(guān)系來實(shí)現(xiàn),而是通過組合(Composition)關(guān)系來復(fù)用父加載器的代碼。每個類加載器都有自己的命名空間(由該加載器及所有父類加載器所加載的類組成,在同一個命名空間中,不會出現(xiàn)類的完整名字(包括類的包名)相同的兩個類;在不同的命名空間中,有可能會出現(xiàn)類的完整名字(包括類的包名)相同的兩個類)
雙親委派模型的工作過程為:
1.當(dāng)前 ClassLoader 首先從自己已經(jīng)加載的類中查詢是否此類已經(jīng)加載,如果已經(jīng)加載則直接返回原來已經(jīng)加載的類。
每個類加載器都有自己的加載緩存,當(dāng)一個類被加載了以后就會放入緩存, 等下次加載的時候就可以直接返回了。
2.當(dāng)前 classLoader 的緩存中沒有找到被加載的類的時候,委托父類加載器去加載,父類加載器采用同樣的策略,首先查看自己的緩存,然后委托父類的父類去加載,一直到 bootstrap ClassLoader.
當(dāng)所有的父類加載器都沒有加載的時候,再由當(dāng)前的類加載器加載,并將其放入它自己的緩存中,以便下次有加載請求的時候直接返回。
使用這種模型來組織類加載器之間的關(guān)系的好處:
主要是為了安全性,避免用戶自己編寫的類動態(tài)替換 Java 的一些核心類,比如 String,同時也避免了重復(fù)加載,因?yàn)?JVM 中區(qū)分不同類,不僅僅是根據(jù)類名,相同的 class 文件被不同的 ClassLoader 加載就是不同的兩個類,如果相互轉(zhuǎn)型的話會拋java.lang.ClassCaseException.
類加載器 classloader 是具有層次結(jié)構(gòu)的,也就是父子關(guān)系。其中,Bootstrap 是所有類加載器的父親。如下圖所示:
Bootstrap class loader: 父類
當(dāng)運(yùn)行 java 虛擬機(jī)時,這個類加載器被創(chuàng)建,它負(fù)責(zé)加載虛擬機(jī)的核心類庫,如 java.lang.* 等。例如 java.lang.Object 就是由根類加載器加載的。需要注意的是,這個類加載器不是用 java 語言寫的,而是用 C/C++ 寫的。
Extension class loader:
這個加載器加載出了基本 API 之外的一些拓展類。
AppClass Loader:
加載應(yīng)用程序和程序員自定義的類。
除了以上虛擬機(jī)自帶的加載器以外,用戶還可以定制自己的類加載器(User-defined Class Loader)。Java 提供了抽象類 java.lang.ClassLoader,所有用戶自定義的類加載器應(yīng)該繼承 ClassLoader 類。
這是JVM分工自治生態(tài)系統(tǒng)的一個很好的體現(xiàn)。
http://www.importnew.com/6581...
執(zhí)行引擎作用: 執(zhí)行字節(jié)碼,或者執(zhí)行本地方法
runtime data areaJVM 運(yùn)行時數(shù)據(jù)區(qū) (JVM Runtime Area) 其實(shí)就是指 JVM 在運(yùn)行期間,其對JVM內(nèi)存空間的劃分和分配。JVM在運(yùn)行時將數(shù)據(jù)劃分為了6個區(qū)域來存儲。
程序員寫的所有程序都被加載到運(yùn)行時數(shù)據(jù)區(qū)域中,不同類別存放在heap, java stack, native method stack, PC register, method area.
下面對各個部分的功能和存儲的內(nèi)容進(jìn)行描述:
1、PC程序計(jì)數(shù)器:一塊較小的內(nèi)存空間,可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器, NAMELY存儲每個線程下一步將執(zhí)行的JVM指令,如該方法為native的,則PC寄存器中不存儲任何信息。Java 的多線程機(jī)制離不開程序計(jì)數(shù)器,每個線程都有一個自己的PC,以便完成不同線程上下文環(huán)境的切換。
2、java虛擬機(jī)棧:與 PC 一樣,java 虛擬機(jī)棧也是線程私有的。每一個 JVM 線程都有自己的 java 虛擬機(jī)棧,這個棧與線程同時創(chuàng)建,它的生命周期與線程相同。虛擬機(jī)棧描述的是Java 方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。每一個方法被調(diào)用直至執(zhí)行完成的過程就對應(yīng)著一個棧幀在虛擬機(jī)棧中從入棧到出棧的過程。
3、本地方法棧:與虛擬機(jī)棧的作用相似,虛擬機(jī)棧為虛擬機(jī)執(zhí)行執(zhí)行java方法服務(wù),而本地方法棧則為虛擬機(jī)使用到的本地方法服務(wù)。
4、Java堆:被所有線程共享的一塊存儲區(qū)域,在虛擬機(jī)啟動時創(chuàng)建,它是JVM用來存儲對象實(shí)例以及數(shù)組值的區(qū)域,可以認(rèn)為Java中所有通過new創(chuàng)建的對象的內(nèi)存都在此分配。
Java堆在JVM啟動的時候就被創(chuàng)建,堆中儲存了各種對象,這些對象被自動管理內(nèi)存系統(tǒng)(Automatic Storage Management System,也即是常說的 “Garbage Collector(垃圾回收器)”)所管理。這些對象無需、也無法顯示地被銷毀。
JVM將Heap分為兩塊:新生代New Generation和舊生代Old Generation
Note:
堆在JVM是所有線程共享的,因此在其上進(jìn)行對象內(nèi)存的分配均需要進(jìn)行加鎖,這也是new開銷比較大的原因。
鑒于上面的原因,Sun Hotspot JVM為了提升對象內(nèi)存分配的效率,對于所創(chuàng)建的線程都會分配一塊獨(dú)立的空間,這塊空間又稱為TLAB
TLAB僅作用于新生代的Eden Space,因此在編寫Java程序時,通常多個小的對象比大的對象分配起來更加高效
5、方法區(qū)
方法區(qū)和堆區(qū)域一樣,是各個線程共享的內(nèi)存區(qū)域,它用于存儲每一個類的結(jié)構(gòu)信息,例如運(yùn)行時常量池,成員變量和方法數(shù)據(jù),構(gòu)造函數(shù)和普通函數(shù)的字節(jié)碼內(nèi)容,還包括一些在類、實(shí)例、接口初始化時用到的特殊方法。當(dāng)開發(fā)人員在程序中通過Class對象中的getName、isInstance等方法獲取信息時,這些數(shù)據(jù)都來自方法區(qū)。
方法區(qū)也是全局共享的,在虛擬機(jī)啟動時候創(chuàng)建。在一定條件下它也會被GC。這塊區(qū)域?qū)?yīng)Permanent Generation 持久代。 XX:PermSize指定大小。
6、運(yùn)行時常量池
其空間從方法區(qū)中分配,存放的為類中固定的常量信息、方法和域的引用信息。
javapapers
Java garbage collection is an automatic process to manage the runtime memory used by programs. By doing it automatic JVM relieves the programmer of the overhead of assigning and freeing up memory resources in a program.
java 與 C語言相比的一個優(yōu)勢是,可以通過自己的JVM自動分配和回收內(nèi)存空間。
何為GC?
垃圾回收機(jī)制是由垃圾收集器Garbage Collection GC來實(shí)現(xiàn)的,GC是后臺的守護(hù)進(jìn)程。它的特別之處是它是一個低優(yōu)先級進(jìn)程,但是可以根據(jù)內(nèi)存的使用情況動態(tài)的調(diào)整他的優(yōu)先級。因此,它是在內(nèi)存中低到一定限度時才會自動運(yùn)行,從而實(shí)現(xiàn)對內(nèi)存的回收。這就是垃圾回收的時間不確定的原因。
為何要這樣設(shè)計(jì):因?yàn)镚C也是進(jìn)程,也要消耗CPU等資源,如果GC執(zhí)行過于頻繁會對java的程序的執(zhí)行產(chǎn)生較大的影響(java解釋器本來就不快),因此JVM的設(shè)計(jì)者們選著了不定期的gc。
GC有關(guān)的是: runtime data area 中的 heap(對象實(shí)例會存儲在這里) 和 gabage collector方法。
程序運(yùn)行期間,所有對象實(shí)例存儲在運(yùn)行時數(shù)據(jù)區(qū)域的heap中,當(dāng)一個對象不再被引用(使用),它就需要被收回。在GC過程中,這些不再被使用的對象從heap中收回,這樣就會有空間被循環(huán)利用。
GC為內(nèi)存中不再使用的對象進(jìn)行回收,GC中調(diào)用回收的方法--收集器garbage collector. 由于GC要消耗一些資源和時間,Java 在對對象的生命周期特征(eden or survivor)進(jìn)行分析之后,采用了分代的方式進(jìn)行對象的收集,以縮短GC對應(yīng)用造成的暫停。
在垃圾回收器回收內(nèi)存之前,還需要一些清理工作。
因?yàn)槔厥誫c只能回收通過new關(guān)鍵字申請的內(nèi)存(在堆上),但是堆上的內(nèi)存并不完全是通過new申請分配的。還有一些本地方法(一般是調(diào)用的C方法)。這部分“特殊的內(nèi)存”如果不手動釋放,就會導(dǎo)致內(nèi)存泄露,gc是無法回收這部分內(nèi)存的。
所以需要在finalize中用本地方法(native method)如free操作等,再使用gc方法。顯示的GC方法是system.gc()
方法一:引用計(jì)數(shù)法。簡單但速度很慢。缺陷是:不能處理循環(huán)引用的情況。
方法二:停止-復(fù)制(stop and copy)。效率低,需要的空間大,優(yōu)點(diǎn),不會產(chǎn)生碎片。
方法三:標(biāo)記 - 清除算法 (mark and sweep)。速度較快,占用空間少,標(biāo)記清除后會產(chǎn)生大量的碎片。
JAVA虛擬機(jī)中是如何做的?
java的做法很聰明,我們稱之為"自適應(yīng)"的垃圾回收器,或者是"自適應(yīng)的、分代的、停止-復(fù)制、標(biāo)記-清掃"式垃圾回收器。它會根據(jù)不同的環(huán)境和需要選擇不同的處理方式。
由于GC需要消耗一些資源和時間的,Java在對對象的生命周期特征進(jìn)行分析后,采用了分代的方式來進(jìn)行對象的收集,即按照新生代、舊生代的方式來對對象進(jìn)行收集,以盡可能的縮短GC對應(yīng)用造成的暫停.
heap 的組成有三區(qū)域/世代:(可以理解隨著時間,對象實(shí)例不斷變換heap中的等級,有點(diǎn)像年級)
新生代 Young Generation
Eden Space 任何新進(jìn)入運(yùn)行時數(shù)據(jù)區(qū)域的實(shí)例都會存放在此
S0 Suvivor Space 存在時間較長,經(jīng)過垃圾回收沒有被清除的實(shí)例,就從Eden 搬到了S0
S1 Survivor Space 同理,存在時間更長的實(shí)例,就從S0 搬到了S1
舊生代 Old Generation/tenured
同理,存在時間更長的實(shí)例,對象多次回收沒被清除,就從S1 搬到了tenured
Perm 存放運(yùn)行時數(shù)據(jù)區(qū)的方法區(qū)
Java 不同的世代使用不同的 GC 算法。
Minor collection:
新生代 Young Generation 使用將 Eden 還有 Survivor 內(nèi)的數(shù)據(jù)利用 semi-space 做復(fù)制收集(Copying collection), 并將原本 Survivor 內(nèi)經(jīng)過多次垃圾收集仍然存活的對象移動到 Tenured。
Major collection 則會進(jìn)行 Minor collection,Tenured 世代則進(jìn)行標(biāo)記壓縮收集。
To note that:
這個搬運(yùn)工作都是GC 完成的,這也是garbage collector 的名字來源,而不是叫g(shù)arbage cleaner. GC負(fù)責(zé)在heap中搬運(yùn)實(shí)例,以及收回存儲空間。GC工作原理
JVM 分別對新生代和舊生代采用不同的垃圾回收機(jī)制
何為垃圾?Java中那些不可達(dá)的對象就會變成垃圾。那么什么叫做不可達(dá)?其實(shí)就是沒有辦法再引用到該對象了。主要有以下情況使對象變?yōu)槔?br>1.對非線程的對象來說,所有的活動線程都不能訪問該對象,那么該對象就會變?yōu)槔?br>2.對線程對象來說,滿足上面的條件,且線程未啟動或者已停止。
例如: (1)改變對象的引用,如置為null或者指向其他對象。 Object x=new Object();//object1 Object y=new Object();//object2 x=y;//object1 變?yōu)槔? x=y=null;//object2 變?yōu)槔? (2)超出作用域 if(i==0){ Object x=new Object();//object1 }//括號結(jié)束后object1將無法被引用,變?yōu)槔? (3)類嵌套導(dǎo)致未完全釋放 class A{ A a; } A x= new A();//分配一個空間 x.a= new A();//又分配了一個空間 x=null;//將會產(chǎn)生兩個垃圾 (4)線程中的垃圾 class A implements Runnable{ void run(){ //.... } } //main A x=new A();//object1 x.start(); x=null;//等線程執(zhí)行完后object1才被認(rèn)定為垃圾 這樣看,確實(shí)在代碼執(zhí)行過程中會產(chǎn)生很多垃圾,不過不用擔(dān)心,java可以有效地處理他們。
JVM中將對象的引用分為了四種類型,不同的對象引用類型會造成GC采用不同的方法進(jìn)行回收:
(1)強(qiáng)引用:默認(rèn)情況下,對象采用的均為強(qiáng)引用
(GC不會回收)
(2)軟引用:軟引用是Java中提供的一種比較適合于緩存場景的應(yīng)用
(只有在內(nèi)存不夠用的情況下才會被GC)
(3)弱引用:在GC時一定會被GC回收
(4)虛引用:在GC時一定會被GC回收
想更一進(jìn)步的支持我,請掃描下方的二維碼,你懂的~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64280.html
摘要:看到的只是,而由泛型附加的類型信息對來說是不可見的。然后再加載執(zhí)行類的靜態(tài)變量以及靜態(tài)語句塊。接口中基本數(shù)據(jù)類型為而抽類象不是的。本地方法接口主要是調(diào)用或?qū)崿F(xiàn)的本地方法及返回結(jié)果。用戶自定義類加載器,在程序運(yùn)行期間,通過的子類動態(tài)加載。 編譯機(jī)制 編譯主要是把?.Java文件轉(zhuǎn)換為 .class 文件。其中轉(zhuǎn)換后的 .class 文件就包含了元數(shù)據(jù),方法信息等一些信息。比如說元數(shù)據(jù)就...
學(xué)習(xí)JVM的相關(guān)資料 《深入理解Java虛擬機(jī)——JVM高級特性與最佳實(shí)踐(第2版)》 showImg(https://segmentfault.com/img/bVbsqF5?w=200&h=200); 基于最新JDK1.7,圍繞內(nèi)存管理、執(zhí)行子系統(tǒng)、程序編譯與優(yōu)化、高效并發(fā)等核心主題對JVM進(jìn)行全面而深入的分析,深刻揭示JVM的工作原理。以實(shí)踐為導(dǎo)向,通過大量與實(shí)際生產(chǎn)環(huán)境相結(jié)合的案例展示了解...
摘要:如問到是否使用某框架,實(shí)際是是問該框架的使用場景,有什么特點(diǎn),和同類可框架對比一系列的問題。這兩個方向的區(qū)分點(diǎn)在于工作方向的側(cè)重點(diǎn)不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個核心必考點(diǎn)完全解析(完) 課程預(yù)習(xí) 1.1 課程內(nèi)容分為三個模塊 基礎(chǔ)模塊: 技術(shù)崗位與面試 計(jì)算機(jī)基礎(chǔ) JVM原理 多線程 設(shè)計(jì)模式 數(shù)據(jù)結(jié)構(gòu)與算法 應(yīng)用模塊: 常用工具集 ...
摘要:前段時間,前同事跳槽,機(jī)緣巧合下面了阿里,本來憑著試一試的態(tài)度,卻不料好事成雙,拿到了,而且薪資也了。面就沒啥東西可聊的,基本上就是對此次面試的一個評價定薪等等一些之內(nèi)的話題。如果是現(xiàn)場面試,記得關(guān)注當(dāng)天的天氣,提前查一下路線。 ...
閱讀 2130·2021-11-18 10:07
閱讀 3507·2021-09-04 16:48
閱讀 3214·2019-08-30 15:53
閱讀 1235·2019-08-30 12:55
閱讀 2453·2019-08-29 15:08
閱讀 3149·2019-08-29 15:04
閱讀 2879·2019-08-29 14:21
閱讀 2906·2019-08-29 11:21