java main方法背后的故事?(转)
jvm java 看似一種語(yǔ)言,實(shí)則一個(gè)巨大的體系的王國(guó),開(kāi)發(fā)這么多年了,還是沒(méi)有搞懂,我以為我懂了,可是過(guò)了一段時(shí)間又忘了,所以說(shuō)還是沒(méi)懂
1、main方法說(shuō)起
編譯完我們的java文件后,需要有個(gè)一含有main方法的類(lèi),java 命令將指示操作系統(tǒng)啟動(dòng)一個(gè)jvm進(jìn)程
這個(gè)jvm進(jìn)程啟動(dòng)后,尋找那個(gè)main地方開(kāi)始執(zhí)行程序
java [JVM_Options] ClassName_with_main [args_separate_space]
main方法的簽名必須是 pubic static void main(String[] args)?why?
簡(jiǎn)單點(diǎn):
首先,main方法是JVM(java虛擬機(jī))自動(dòng)調(diào)用
JVM調(diào)用main方法的位置自然不會(huì)在某個(gè)類(lèi)中、或某個(gè)包中,因此只有當(dāng)main方法在公有級(jí)別上時(shí),才對(duì)JVM可見(jiàn),所以mian方法需要public修飾,
main方法所在的類(lèi)也需要public修飾符。
由于main方法是所有程序的入口,也就是main被調(diào)用時(shí)沒(méi)有任何對(duì)象創(chuàng)建,不通過(guò)對(duì)象調(diào)用某一方法,只有將該方法定義為靜態(tài)方法,所以main方法是一個(gè)靜態(tài)方法,既需要static修飾。
JVM對(duì)于java程序已經(jīng)是最底層,由它調(diào)用的方法的返回值已經(jīng)沒(méi)有任何地方可去,因此,main方法返回值為空,既需用void修飾。
至于main方法的參數(shù)String[ ] arg我們現(xiàn)在已經(jīng)很少有機(jī)會(huì)去用它了,它用于在接受命令行傳入的參數(shù)
?2、執(zhí)行main方法之前發(fā)生了神馬
可以參看?jvm源碼分析? ? ?
首先要明確 jvm進(jìn)程 是操作系統(tǒng)的進(jìn)程,該進(jìn)程是多線(xiàn)程機(jī)制的
我們明確兩種線(xiàn)程:
jvm線(xiàn)程:指jvm自行管理的線(xiàn)程,我們?cè)诔绦蛑袩o(wú)法操控,多是守護(hù)類(lèi)型的
java線(xiàn)程:指從java技術(shù)角度看 jvm、我們?cè)诔绦蛑杏肨hread類(lèi)或Runnable接口編寫(xiě)產(chǎn)生的線(xiàn)程,可操控的線(xiàn)程
至于 java線(xiàn)程 在 jvm里面是怎么實(shí)現(xiàn)的,怎么對(duì)應(yīng)到os級(jí)別的線(xiàn)程的,請(qǐng)看 ?http://my.oschina.net/jingxing05/blog/275334
明確兩類(lèi)不同的線(xiàn)程之后,執(zhí)行main方法之前:?LoadJavaVM
jvm進(jìn)程啟動(dòng)了多個(gè)jvm線(xiàn)程(很可能是錯(cuò)的,如有,請(qǐng)賜教):
jvm線(xiàn)程:
-
啟動(dòng) VM Thread, 單例的,所有線(xiàn)程之始祖!這個(gè)線(xiàn)程自輪詢(xún)loop從對(duì)一個(gè)隊(duì)列中取操作任務(wù),來(lái)產(chǎn)生其他線(xiàn)程
-
根據(jù)jvm抽象規(guī)范,可能有執(zhí)行引擎線(xiàn)程,GC線(xiàn)程,classloader線(xiàn)程
在jvm自身啟動(dòng)和初始化之后,會(huì)
ContinueInNewThread(JavaMain, threadStackSize, (void*)&args);
即啟動(dòng)一個(gè)叫main的線(xiàn)程來(lái)執(zhí)行 ?入口的main方法,main線(xiàn)程雖然不是我們手動(dòng)生出的線(xiàn)程,但ta還是一個(gè)非守護(hù)線(xiàn)程
3、main執(zhí)行過(guò)程
-
加載類(lèi)
執(zhí)行main方法時(shí),jvm進(jìn)程發(fā)現(xiàn)main所在類(lèi)沒(méi)有在方法區(qū),于是開(kāi)始進(jìn)行classload
類(lèi)加載完的最后一步是 根據(jù)情況決定 ?是不是要進(jìn)行類(lèi)的初始化
在main執(zhí)行之前,必須先對(duì)類(lèi)進(jìn)行初始化。初始化類(lèi)的變量,還有靜態(tài)代碼塊。初始化的時(shí)候還要先初始化它的父類(lèi)。每個(gè)類(lèi)都有一個(gè)隱含的父類(lèi)Object。?
初始化的順序:類(lèi)變量和靜態(tài)塊按序,先父后子
類(lèi)的初始化過(guò)程發(fā)生時(shí)刻:?
1. T是一個(gè)類(lèi),當(dāng)T的一個(gè)實(shí)例創(chuàng)建的時(shí)候,也就是T t = new T();?
2. T的一個(gè)靜態(tài)方法被調(diào)用的時(shí)候,也就是 T.staticField();?
3. T的靜態(tài)屬性被賦值的時(shí)候,T.staticField = o;?
4. T的一個(gè)靜態(tài)屬性被使用的時(shí)候,也就是 Object o = T.staticField; 但是它不是常量。?
5. T is a top level class , and an assert statement ?lexically nested?
within T ?is executed. (不懂,求解)?
-
執(zhí)行main方法
將方法需要的參數(shù),局部變量,本地方法,操作數(shù)等以 棧幀的結(jié)構(gòu) push到 main線(xiàn)程的堆棧區(qū),然后執(zhí)行引擎線(xiàn)程開(kāi)始執(zhí)行,執(zhí)行完畢,將該棧幀 pop掉。main線(xiàn)程的堆棧區(qū)沒(méi)有棧幀時(shí),main線(xiàn)程消退。
-
卸載類(lèi)對(duì)象
這一步是個(gè)優(yōu)化的步驟,釋放一些方法區(qū)的內(nèi)存,jvm自己決定要不要這一步,一般不會(huì)去卸載方法區(qū)的
-
程序退出
?
1. 所有的非daemon線(xiàn)程都終止了?
2. 某個(gè)線(xiàn)程調(diào)用了類(lèi)Runtime或者System的exit方法
main程序執(zhí)行圖
?
?
類(lèi)加載詳細(xì)過(guò)程
?
jvm中的一些線(xiàn)程可參看?http://ifeve.com/jvm-thread/
http://my.oschina.net/jingxing05/blog/282867?p={{currentPage+1}}
總結(jié)
以上是生活随笔為你收集整理的java main方法背后的故事?(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android源码解析--SwipeMe
- 下一篇: 关于缓存的几篇好文章