類加載與方法調用

1.jvm是啥

jvm 是java語言的運行平臺,寫c/c++就要知道cpu和內存管理,csapp是本好書,那麼,想知道java是怎麼實施內存管理和內存回收的呢,在聊此二者前,先知道java是怎麼在jvm上運行的,爲什麼會有多態、匿名類、static field、final爲什麼很特殊背後的實現原理又是什麼?併發的時候爲什麼要做thread-safe的code,thread-safe 的代碼是指 "the state of an object is always accessible and same to all threads."我自己的理解,有Lock和synchronize機制,建立在這個complex os上的JMM模塊。先從java代碼如何在jvm中表示和被調用的。

從java文件到.class文件,從詞法、語法、語義組織成二進制流文件(可執行目標文件),該文件被加載到run-time data area,你的一個個java文件如A.java,B.java的各個部分,經過loading,verify,prepare,reslove,initialize,最終被分解了,而在heap中存放了最終的java.lang.Class文件,被分解的部分被保存在了一個叫run-time constant pool的地方,那些被分解的部分分別是1.對這個class/interface的描述2.對這個method的描述3.對field的描述等,並且他們表示方式是symbolic reference,那麼你在用他們的時候,用就是比方說我要調用一個方法method1(以下簡稱m1)怎麼個流程呢?

執行m1,首先會resolve這個methodref,就是從run-time constant pool 中取出這個方法的描述,這個methodref中描述了幾部分:1.這個方法屬於哪個class,他會記錄一個classref。2.方法名字,那麼resolve這個method的流程就是先resolve這個class,(resolve這個class的流程就是通過這個classref的symbolic reference去heap中找出對應的java.lang.Class就算是這個class的distinct reference了,這裏可以說明虛擬機不會一開始就將所有的symbolic reference轉爲 distinct reference而是等你去調的時候再做這一步,體現了什麼思想?static,final,private,constructor方法是編譯後已是distinct reference,所以不需要new instance就可以調用static方法,只要Class.m1()即可。final 的線程安全性可具體看link)如果這個class resolve 不throw exception 的話,把這個類記爲c1(否則 ClassNotFound exception),從這個c1裏找m1,找到m1,ok,結束。如果沒有,去c1的superclass找,再沒有,去superclass的superInterface找,再沒有就gg。原文在這裏jvm specification。得到這個m1之後,再checkAuth,有沒有權限訪問這個方法。有這個權限繼續執行,我們還有故事,沒有就再見了。

怎麼執行方法?爲什麼沒有stack、native method stack、pc、frame(method執行在這個上面,計算也是)?爲什麼不提垃圾回收?

2.怎麼調方法

方法解析完之後,可以調用這個方法了,在vm stack上分配一個frame,在frame上保存了local variable table,該frame對應方法在運行時常量池中的引用(支持動態鏈接),operand stack,return address,這裏說下普通的方法分爲instance method 和class method,顧名思義,前者需要有實例才能調到具體的方法,後者只需要根據class的類型就可以調到具體的方法,static就是instance 方法,只需要一個class就可以invoke。前面講解加載類的時候到說了,一些method是在編譯時將符號引用(symbolic reference)轉爲了直接引用(district reference),故不需要實例化到heap再去調。調不同的方法執行的instructions也不同,invokestatic指令爲調static、private、init、constructor方法,invokevirtual指令調實例方法需要傳遞objref--即調用的對象(也就是this,thinking in java講this的時候提到),args參數。而類方法只需要參數不需要調用對象。

接下去就是將參數入棧出棧的過程了,比如將int a = 1,int b =2 ,return a+b*2;執行這段代碼,在棧頂把2壓入棧頂,執行*2的指令,再將1壓入棧頂,執行1+4,並返回結果。這些計算的過程在operand stack進行。

================================================================================================

編輯於2019.03.22

方法調用與多態的理解看這篇文章,需要總結的地方很多。

https://blog.csdn.net/huangrunqing/article/details/51996424

 

雙親委派模型

三種類加載器:1.bootstrap classloader 加載 java_home\lib下的jar包

2.extention classloader 加載 java_home\lib\ext下的jar包

3.application classloader 加載classpath下的所有target下的所有編譯後的文件

除了bootstrap外所有的加載器都要有父加載器,判斷是否已經加載該類,否則通過通過父加載器,沒有就用bootstrap加載器。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章