日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

通過實例解析Java class文件編譯加載過程

瀏覽:91日期:2022-08-28 10:34:03

一、Java從編碼到執行

首先我們來看一下Java是如何從編碼到執行的呢? 我們有一個x.java文件通過執行javac命令可以變成x.class文件,當我們調用Java命令的時候class文件會被裝載到內存中,這個過程叫做classloader。一般情況下我們自己寫代碼的時候會用到Java的類庫,所以在加載的時候也會把Java類庫相關的類也加載到內存中。裝載完成之后會調用字節碼解釋器和JIT即時編譯器來進行解釋和編譯,編譯完之后由執行引擎開始執行,執行引擎下面對應的就是操作系統硬件了。下圖是大體的流程:

通過實例解析Java class文件編譯加載過程

Java叫做跨平臺的語言,JVM可以稱之為跨語言的平臺;

有個問題:java是解釋執行還是編譯執行?答:解釋和編譯是可以混合的,特別常用的代碼或則是代碼用到的次數特別多的時候,會把一個即時編譯做成本地編譯,這樣會很大程度上的提高效率。

Java虛擬機是如何做到這么多語言都可以在上面運行,關鍵在于class文件,任何語言只要能編譯成class文件,并且符合class文件的規范你就可以放在Java虛擬機上去運行。

二、詳解class文件的加載過程

接下來主要講的是一個class文件是怎么從硬盤上到內存中,并開始執行的。

類加載主要有三個過程:loading 、linking 、initializing;其中linking又分為三個步驟:verification 、preparation 、resolution;

通過實例解析Java class文件編譯加載過程

1、首先Loading是什么意思呢?是把一個class問價load到內存中去;

2、接下來是Linking分為了三小步:

verification 是用來校驗加載進來的class文件是否符合class文件標準,如果不符合直接就會被拒絕了; preparation 是將class文件靜態變量賦默認值而不是初始值,例如static int i =8;這個步驟并不是將i賦值為8,而是賦值為默認值0; resolution 是把class文件常量池中用到的符號引用轉換成直接內存地址,可以訪問到的內容;

3、initializing 成為初始化,靜態變量在這個時候才會被賦值為初始值;

下面為類加載過程的簡化圖:

通過實例解析Java class文件編譯加載過程

類加載器的加載過程是分成不同的層次來加載的,不同的類加載器來加載不同的class文件, Bootstrap >Extension>Application>Custom(自定義類加載器)

1、第一個類加載器的層次為:Bootstrap 稱為啟動類加載器,是Java類加載層次中最頂層的類加載器,負責加載JDK中的核心類庫。

2、第二個類加載器的層次為:Extension 是用來加載擴展類的,主要負責加載Java的擴展類庫,默認加載JAVA_HOME/jre/lib/ext/目錄下的所有jar包。

3、第三個類加載器的層次為:Application又稱為系統類加載器,負責在JVM啟動時,加載來自在命令java中的classpath或者java.class.path系統屬性或者CLASSPATH操作系統屬性所指定的JAR類包和類路徑。

4、第三個類加載器的層次為:CustomClassLoader(自定義加載器)

package com.example.demo.classloader;public class ClassLoaderScope { public static void main(String[] args) { System.out.println('-------------------Bootstrap加載類-------------------'); String property = System.getProperty('sun.boot.class.path'); String s = property.replaceAll(';', System.lineSeparator()); System.out.println(s); System.out.println('-------------------Ext加載類-------------------'); String property1 = System.getProperty('java.ext.dirs'); String s1 = property1.replaceAll(';', System.lineSeparator()); System.out.println(s1); System.out.println('-------------------App加載類-------------------'); String property2 = System.getProperty('java.class.path'); String s2 = property2.replaceAll(';', System.lineSeparator()); System.out.println(s2); }} /**輸出結果只截取了部分*/ //E:JDKjdk1.8jrelibresources.jar //E:JDKjdk1.8jrelibrt.jar //E:JDKjdk1.8jrelibsunrsasign.jar //E:JDKjdk1.8jrelibjsse.jar //E:JDKjdk1.8jrelibjce.jar //E:JDKjdk1.8jrelibcharsets.jar //E:JDKjdk1.8jrelibjfr.jar //E:JDKjdk1.8jreclasses //---------------------------------------------- //E:JDKjdk1.8jrelibext //C:WindowsSunJavalibext //---------------------------------------------- //E:JDKjdk1.8jrelibcharsets.jar //E:JDKjdk1.8jrelibdeploy.jar //E:JDKjdk1.8jrelibextaccess-bridge-64.jar //E:JDKjdk1.8jrelibextcldrdata.jar //E:JDKjdk1.8jrelibextdnsns.jar //E:JDKjdk1.8jrelibextjaccess.jar //E:JDKjdk1.8jrelibextjfxrt.jar

特別注意一點這個的層級關系并沒有繼承的關系在里面,只是單單純純的語法上的繼承;

下圖為類加載的一個全過程:

用比較通俗的話來解釋這個過程,當有一個類需要被加載時,首先要判斷這個類是否已經被加載到內存,判斷加載與否的過程是有順序的,如果有自己定義的類加載器,會先到custom class loader 的cache(緩存)中去找是否已經加載,若已加載直接返回結果,否則到App的cache中查找,如果已經存在直接返回,如果不存在,到Extension中查找,存在直接返回,不存在繼續向父加載器中尋找直到Bootstrap頂層,如果依然沒找到,那就是沒有加載器加載過這個類,需要委派對應的加載器來加載,先看看這個類是否在自己的加載范圍內,如果是直接加載返回結果,若不是繼續向下委派,以此類推直到最下級,如果最終也沒能加載,就會直接拋異常ClassNotFoundException,這就是雙親委派模式。

通過實例解析Java class文件編譯加載過程

理解雙親委派模式:

1、父加載器:不是類加載器的加載器,也不是類加載器的父類加載器(此處意思是沒有父類與子類之間的繼承關系)。

package com.example.demo.classloader;/** * 驗證了父加載器不是加載器的加載器 */public class ParentAndChild { public static void main(String[] args) { //AppClassLoader ClassLoader classLoader = ParentAndChild.class.getClassLoader(); System.out.println(classLoader); //null 這里AppClassLoader的加載器不是ExtClassLoader 而是Bootstrap ClassLoader appclassLoader = ParentAndChild.class.getClassLoader().getClass().getClassLoader(); System.out.println(appclassLoader); //ExtClassLoader AppClassLoader的父加載器是ExtClassLoader ClassLoader parent = ParentAndChild.class.getClassLoader().getParent(); System.out.println(parent); //null ClassLoader parentparent = ParentAndChild.class.getClassLoader().getParent().getParent(); System.out.println(parentparent); //null ClassLoader parentparentparent = ParentAndChild.class.getClassLoader().getParent().getParent().getParent(); System.out.println(parentparent); /**輸出結果*/ //sun.misc.Launcher$AppClassLoader@18b4aac2 //null //sun.misc.Launcher$ExtClassLoader@23fc625e //null //Exception in thread 'main' java.lang.NullPointerException at com.example.demo.classloader.ParentAndChild.main(ParentAndChild.java:22) }}

2、雙親委派:其工作原理的是,如果一個類加載器收到了類加載請求,并不會直接去加載,而是自下而上的向頂層類加載器查找是否已經被加載了,如果被加載就不用進行加載,如果未被加載過,則會自上而下的檢查是否屬于自己加載的范圍,如果屬于則加載,如果不屬于則向下委托,直到類被加載進來才能叫做成功,如果加載不成功就會拋異常classnotfoundexeption,這就叫做雙親委派。

3、為什么要搞雙親委派模式?

主要是為了安全,這里可以使用反證法,如果任何類加載器都可以把class加載到內存中,我們就可以自定義類加載器來加載Java.lang.string。在打包時可以把密碼存儲為String對象,偷偷摸摸的把密碼發送到自己的郵箱,這樣會造成安全問題。

三、自定義類加載器

package com.example.demo.classloader;public class ClassLoaderByHand { public static void main(String[] args) throws ClassNotFoundException { Class<?> clazz = ClassLoaderByHand.class.getClassLoader().loadClass('com.example.demo.threaddemo.juc_002.Account'); String name = clazz.getName(); System.out.println(name); }} /** * 輸出結果 */ //com.example.demo.threaddemo.juc_002.Account

代碼運行結果可以看出,就是你要加載一個類你只要調用classLoader中的loadClass()方法就能把這個類加載到內存中,加載完成之后會給你返回一個Class類的對象。

在硬盤上找到這個類的源碼,把它load到內存,與此同時生成一個Class對象,上述的小程序是通過ClassLoaderByHand 找到他的加載器AppClassLoader 然后調用它的loadClass()方法,讓它幫我們把Account類加載進來,返回一個clazz對象,使用clazz.getName()方法正常返回Account類。

什么時候我們需要自己定義去加載一個類?

熱部署時就是先把之前加載的類給干掉 ,然后使用的自定義類加載器來進行重新加載

spring的動態代理,一個新的class 當需要的時候就會把它load到內存中

我們還是來看一下源碼吧,加載過程最主要的還是ClassLoader中的loaderClass()方法:

結合上面給的類加載過程的圖解一起看會更容易一些;

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { /** * 在加載之前先調用findLoadedClass()方法查看是否已經加載過此類 * 若加載過 返回該對象 * 如果未加載則返回null 進行下一步 */ // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) {long t0 = System.nanoTime();try { //判斷有無父加載器 如果不為空說明還未到頂層Bootstrap遞歸調用loadClass() if (parent != null) { c = parent.loadClass(name, false); } else { //如果沒有父加載器說明調用的加載器為Bootstrap Class Loader, 在此加載器內存中查找是否已經加載 c = findBootstrapClassOrNull(name); }} catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader}//若以上的操作都沒成功加載此類if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); //調用自己的findClass() c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment();} } if (resolve) {resolveClass(c); } return c; } }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩黄色大片网站| 亚洲精品美女| 国产乱码精品一区二区三区亚洲人| 蜜桃视频一区二区三区| 亚洲一级大片| 综合激情五月婷婷| 日韩精品成人| 麻豆一区二区三| 日韩大片在线观看| 99国产精品久久久久久久| 亚洲免费观看高清完整版在线观| 欧美精品三级在线| 国产精品国产一区| 亚州av乱码久久精品蜜桃| 水蜜桃久久夜色精品一区的特点| 日韩一区二区三区精品视频第3页| 久久精品凹凸全集| 日本一二区不卡| 伊人成人网在线看| 日本一区中文字幕| 久久a爱视频| 蜜桃精品在线| 在线观看一区| 久久精品日韩欧美| 亚洲精品2区| 国产剧情在线观看一区| 国产美女高潮在线观看| 久久亚洲欧美| 精品国产欧美| 羞羞答答国产精品www一本| 国产精品欧美在线观看| 欧美国产91| 国产乱码精品一区二区亚洲| 亚洲v在线看| 日本三级亚洲精品| 国产精选在线| 亚洲一区激情| 成人午夜亚洲| 亚洲精品乱码| 在线日韩中文| 国产精品久久久久av蜜臀| 亚洲夜间福利| 国产精品入口久久| 伊人久久亚洲美女图片| 国产精品免费大片| 宅男噜噜噜66国产日韩在线观看| 麻豆精品新av中文字幕| 久久成人一区| 荡女精品导航| 深夜福利一区| 国产一区二区三区精品在线观看| 亚洲综合精品四区| 国产aa精品| 日韩欧美在线精品| 欧美日韩在线播放视频| 欧美aⅴ一区二区三区视频| 蜜桃av一区| 久久亚洲在线| 日韩av自拍| 久久av日韩| 蜜桃视频一区二区| 久久一区二区三区喷水| 精品国产不卡| 91精品一区| 亚洲欧洲美洲国产香蕉| 国产综合精品| 福利视频一区| 久久中文精品| 欧美天堂在线| 婷婷精品在线| 蜜桃传媒麻豆第一区在线观看 | 激情91久久| 国产精品久久观看| 国产精品久久久久久久久久白浆 | 在线日韩av| 成人午夜网址| 国产精品白浆| 亚洲区欧美区| 蜜臀av国产精品久久久久| 欧美 日韩 国产精品免费观看| 国产在线看片免费视频在线观看| 欧美激情视频一区二区三区免费 | 四虎影视精品| 国产一区日韩| 久久久久久夜| 97精品国产福利一区二区三区| 久久影院一区二区三区| 国产精品色婷婷在线观看| 国产精品啊v在线| 欧美xxxx性| 麻豆久久一区二区| 精品网站999| 精品国产aⅴ| 91欧美在线| 激情亚洲影院在线观看| 午夜影院一区| 色88888久久久久久影院| 国产一区二区三区不卡视频网站| 久久爱www成人| 电影91久久久| 激情综合五月| av资源亚洲| 97精品视频在线看| 久久青青视频| 亚洲天堂资源| 激情六月综合| 亚洲一级淫片| 欧美激情网址| 久久精品电影| 国产农村妇女精品一二区| 亚洲免费毛片| 欧美激情福利| 成人国产精选| 国产一区欧美| 蘑菇福利视频一区播放| 日本亚洲三级在线| 欧美日韩一区二区三区不卡视频| 国产福利资源一区| 精品国产一区二区三区噜噜噜| 国内精品麻豆美女在线播放视频| 日本精品黄色| av亚洲免费| 日韩一区中文| 国产成人黄色| 日韩网站在线| 国产精品一区二区三区www| 伊人久久在线| 国产精品腿扒开做爽爽爽挤奶网站| 亚洲2区在线| 精品美女久久| 亚洲综合精品| 国产亚洲一卡2卡3卡4卡新区| 国产网站在线| 亚洲精品在线国产| 色综合狠狠操| 偷拍亚洲精品| 日韩不卡视频在线观看| 亚洲精品影视| 精品三级久久| 日本久久一区| 99成人在线视频| 日韩精品午夜视频| 成人午夜亚洲| 日韩中出av| 欧美日韩精品一区二区视频| 日韩avvvv在线播放| 成人看片网站| 清纯唯美亚洲综合一区| 999视频精品| 国产精品视频3p| 国产精品外国| 久久uomeier| 日本亚洲视频| 在线日韩电影| 国产精品porn| 久久大逼视频| 欧美日韩视频免费观看| 婷婷五月色综合香五月| 91精品啪在线观看国产18| 国产三级精品三级在线观看国产| 欧美+亚洲+精品+三区| 久久不见久久见免费视频7| 国产亚洲毛片| 高清不卡亚洲| 国产日韩1区| 在线一区二区三区视频| 欧洲亚洲一区二区三区| 美女尤物国产一区| 日韩在线视频一区二区三区| 欧美日韩四区| 999国产精品| а√在线中文在线新版| 日韩1区2区3区| 国产日韩综合| 久久要要av| 视频二区不卡| 麻豆国产精品视频| 日韩av影院| 亚洲精品美女91| 蜜臀av一区二区三区| 激情久久婷婷| 久久国产直播| 日本蜜桃在线观看视频| 久久精品国产999大香线蕉| 欧美日韩一区自拍| 日韩毛片网站| 中文精品电影| 国产精品三上| 亚洲免费婷婷| 亚洲综合另类| 亚洲欧美日韩精品一区二区| 免费国产自久久久久三四区久久| 日韩国产一区| 日韩在线观看一区| 国产精品亚洲一区二区三区在线观看| 国产成人精品一区二区免费看京 | 国产免费久久| 国产日韩在线观看视频| 久久国产免费看| 欧美午夜网站|