<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java jvm 類加載 反射

          共 8523字,需瀏覽 18分鐘

           ·

          2020-10-29 23:59

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          ? 作者?|??吳楠予

          來源 |? urlify.cn/E3euIb

          66套java從入門到精通實戰(zhàn)課程分享

          Java 底層

          jvm,類加載,反射

          Java語言是跨平臺語言,一段java代碼,經(jīng)過編譯成class文件后,能夠在不同系統(tǒng)的服務(wù)器上運(yùn)行;因為java語言中有虛擬機(jī)jvm,才有了跨平臺,java為了實現(xiàn)跨平臺,在jvm上投入了很大的研發(fā)開發(fā)資源。jvm是java的底層,本文學(xué)習(xí)探討下java的jvm及關(guān)聯(lián)的類加載和反射知識

          JVM

          JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,JVM是一種用于計算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計算機(jī),是通過在實際的計算機(jī)上仿真模擬各種計算機(jī)功能來實現(xiàn)的。

          Java語言的一個非常重要的特點就是與平臺的無關(guān)性。而使用Java虛擬機(jī)是實現(xiàn)這一特點的關(guān)鍵。一般的高級語言如果要在不同的平臺上運(yùn)行,至少需要編譯成不同的目標(biāo)代碼。而引入Java語言虛擬機(jī)后,Java語言在不同平臺上運(yùn)行時不需要重新編譯。Java語言使用模式Java虛擬機(jī)屏蔽了與具體平臺相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺上不加修改地運(yùn)行。Java虛擬機(jī)在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機(jī)器指令執(zhí)行。[1]

          jvm的構(gòu)成

          jvm周期:是在java程序執(zhí)行時運(yùn)行,程序結(jié)束時停止

          jvm的基本結(jié)構(gòu)有:類加載子系統(tǒng)、本地方法棧、Java棧、方法區(qū)、Java堆、pc寄存器,垃圾回收,執(zhí)行引擎

          類加載子系統(tǒng)

          java是面向?qū)ο笳Z言,邏輯代碼中的類文件執(zhí)行邏輯前,是需要jvm讀取class文件并校驗初始化后才能使用的,包括變量,方法,構(gòu)造。

          類加載系統(tǒng)可以認(rèn)為是在使用到j(luò)ava對像時(抽象),對java對象字節(jié)碼的讀取加載預(yù)編譯(具體),之后不再加載(讀取校驗一次)。

          Java棧

          棧是先進(jìn)后出的結(jié)構(gòu),java棧時一塊線程私有的內(nèi)存空間,可以理解為一個java線程對應(yīng)一個java棧,棧和線程密切關(guān)聯(lián),棧包含線程運(yùn)行的實時信息,如當(dāng)前運(yùn)行方法地址,方法中的瞬時變量等信息

          方法區(qū)

          在一個jvm實例的內(nèi)部,類型信息被存儲在一個稱為方法區(qū)的內(nèi)存邏輯區(qū)中。類型信息是由類加載器在類加載時從類文件中提取出來的。類(靜態(tài))變量也存儲在方法區(qū)中。

          Java堆

          java堆是和應(yīng)用程序關(guān)系最為密切的內(nèi)存空間,幾乎所有的對象都存放在堆上。并且java堆是完全自動化管理的,通過垃圾回收機(jī)制,垃圾對象會被自動清理,而不需要顯示的釋放。

          pc寄存器

          存放計算機(jī)下一步要執(zhí)行的指令的地址,

          垃圾回收

          因為程序運(yùn)行沒創(chuàng)建一個對象都需要使用硬件的內(nèi)存資源,不能無限使用,jvm的垃圾回收能夠自動回收不再使用的java對象,使內(nèi)存空間有效利用。垃圾回收線程是后臺執(zhí)行的,不需要認(rèn)為回收內(nèi)存垃圾,即使有垃圾回收方法調(diào)用,但并不能控制jvm如何去將一個對象失效回收。

          執(zhí)行引擎

          Java 字節(jié)碼指令指向特定邏輯得本地機(jī)器碼,而JVM 解釋執(zhí)行Java字節(jié)碼指令時,會直接調(diào)用字節(jié)碼指向得本地機(jī)器碼;

          java底層由C語言編寫,執(zhí)行java程序時,jvm每讀取一個字節(jié)碼指令動作,執(zhí)行引擎就解析解釋執(zhí)行本地系統(tǒng)對應(yīng)的本地機(jī)器碼。

          類加載

          虛擬機(jī)把描述類的數(shù)據(jù)從 Class 文件加載到內(nèi)存,并對數(shù)據(jù)進(jìn)行校驗、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的 Java 類型,這就是虛擬機(jī)的類加載機(jī)制。

          在Java語言里面,類型的加載、連接和初始化過程都是在程序運(yùn)行期間完成的

          雙親委派機(jī)制

          作為軟件開發(fā)語言,java在安全方面也有很高的要求,所以類加載是有一套規(guī)則的,jre是java運(yùn)行時的環(huán)境,包括很多基本類,如java.lang.String 是字符串類,這個類很基礎(chǔ)也很重要,那在加載的時候不能允許加載的String類被篡改,java保證類加載安全,首先看是否已經(jīng)加載,如果沒有查看核心庫是否有此類,沒有此類才會去擴(kuò)展環(huán)境找類文件加載,這種機(jī)制保證了類在加載時的唯一性和安全性。

          java類加載一般來說是詢問自己的parentClassLoader 加載,如果沒有加載成功,才自己加載,加載順序是自上而下

          java.lang.ClassLoader 加載類方法

          protected?Class?loadClass(String?name,?boolean?resolve)
          ????????throws?ClassNotFoundException
          ????{
          ????????synchronized?(getClassLoadingLock(name))?{
          ????????????//?First,?check?if?the?class?has?already?been?loaded
          ????????????Class?c?=?findLoadedClass(name);?//0.是否已加載
          ????????????if?(c?==?null)?{
          ????????????????long?t0?=?System.nanoTime();
          ????????????????try?{
          ????????????????????if?(parent?!=?null)?{
          ????????????????????????c?=?parent.loadClass(name,?false);?//1.沒有加載,首先通過父類加載器加載
          ????????????????????}?else?{
          ????????????????????????c?=?findBootstrapClassOrNull(name);?//1.沒有父類加載器時加載方式
          ????????????????????}
          ????????????????}?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();
          ????????????????????c?=?findClass(name);
          ?????//如果父類沒有加載到類,則使用findClass方法去加載類(這個方法可以重寫自定義)
          ????????????????????//?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重要的技術(shù)點,在框架開發(fā),AOP切面編程代理等方面都需要反射方面的技術(shù)去實現(xiàn)。

          Java反射機(jī)制主要提供了以下功能:

          • 在運(yùn)行時判斷任意一個對象所屬的類。

          • 在運(yùn)行時構(gòu)造任意一個類的對象。

          • 在運(yùn)行時判斷任意一個類所具有的成員變量和方法。

          • 在運(yùn)行時調(diào)用任意一個對象的方法。

          • 生成動態(tài)代理。

          反射相關(guān)的類

          Class 類的字節(jié)碼對象

          Field 類的屬性

          Method 類的方法

          Constructor 類的構(gòu)造方法

          Annotation 類(方法字段)的注解

          反射的使用

          一般使用

          模擬事務(wù)的注解

          @Target({ElementType.TYPE,ElementType.METHOD})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Inherited
          public?@interface?defTransaction?{

          }

          普通封裝對象

          public?interface?People?{

          ?String?getName();
          ?void?setName(String?name);
          ?Integer?getAge();
          ?void?setAge(Integer?age);
          ?BigDecimal?getMoney();
          ?void?setMoney(BigDecimal?money);
          ?@defTransaction
          ?void?addMoney(BigDecimal?addNum);
          ?@defTransaction
          ?void?subTractMoney(BigDecimal?subNum);
          ?
          }

          public?class?TestPeople?implements?People{
          ?
          ?//?姓名
          ?public?String?name;
          ?
          ?//?年齡
          ?private?Integer?age;
          ?
          ?//?錢
          ?private?BigDecimal?money;
          ?
          ?public?String?getName()?{
          ??return?name;
          ?}
          ?
          ?public?void?setName(String?name)?{
          ??this.name?=?name;
          ?}
          ?public?Integer?getAge()?{
          ??return?age;
          ?}
          ?public?void?setAge(Integer?age)?{
          ??this.age?=?age;
          ?}
          ?public?BigDecimal?getMoney()?{
          ??return?money;
          ?}
          ?public?void?setMoney(BigDecimal?money)?{
          ??this.money?=?money;
          ?}

          ?@Override
          ?public?void?addMoney(BigDecimal?addNum)?{
          ??this.money?=?this.money.add(addNum);
          ??
          ?}

          ?@Override
          ?public?void?subTractMoney(BigDecimal?subNum)?{
          ??this.money?=?this.money.subtract(subNum);
          ?}??
          }

          反射測試類

          public?class?ReflectTest?{

          ?public?static?void?main(String[]?args)?{
          ??//?普通對象創(chuàng)建?使用new
          ??People?testPeople?=?new?TestPeople();
          ??testPeople.setName("Frank");
          ??testPeople.setAge(18);
          ??testPeople.setMoney(new?BigDecimal(10));
          ??System.out.println("json:"?+?JsonUtil.objectToJson(testPeople));
          ??
          ??//?反射創(chuàng)建對象?class.newInstance()
          ??ClassLoader?contextClassLoader?=?Thread.currentThread().getContextClassLoader();
          ??try?{
          ???Class?clazz?=?contextClassLoader.loadClass("com.domoment.leaves.common.util.reflect.TestPeople");
          ???if(clazz?!=?null)?{
          ?????Object?people?=?clazz.newInstance();
          ?????System.out.println("newInstance?start?json:"?+?JsonUtil.objectToJson(people));
          ?????
          ?????//?通過反射執(zhí)行方法
          ?????Method?setName?=?clazz.getMethod("setName",?String.class);
          ?????setName.invoke(people,?"inoverFrank");
          ?????
          ?????
          ?????System.out.println("newInstance?end?json:"?+?JsonUtil.objectToJson(people));
          ?????
          ???}
          ??}?catch?(Exception?e)?{
          ???e.printStackTrace();
          ??}
          ?}
          }

          使用反射實現(xiàn)代理

          代理類DefProxy (People是被代理類)

          public?class?DefProxy?implements?InvocationHandler{

          ??//?這個就是我們要代理的真實對象
          ????private?Object?subject;
          ????
          ????//????構(gòu)造方法,給我們要代理的真實對象賦初值
          ????public?DefProxy(Object?subject){
          ????????this.subject?=?subject;
          ????}
          ????
          ?@Override
          ?public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
          ??Annotation[]?annotations?=?method.getDeclaredAnnotations();
          ??boolean?transactionOpen?=?false;
          ??for?(Annotation?annotation?:?annotations)?{
          ???if(annotation?instanceof?defTransaction)?{
          ????transactionOpen?=?true;
          ????break;
          ???}
          ??}
          ??if(transactionOpen)?{?//當(dāng)方法上有?defTransaction?注解時,執(zhí)行方法前開啟事務(wù)
          ???System.out.println("open?Transaction");
          ??}
          ??System.out.println("proxy:"?+?method.getName());
          ??Object?result?=?method.invoke(subject,?args);
          ??
          ??if(transactionOpen)?{?//當(dāng)方法上有?defTransaction?注解時,執(zhí)行方法后關(guān)閉事務(wù)
          ???System.out.println("close?Transaction");
          ??}
          ??return?result;
          ?}

          }

          代理測試代碼

          public?class?ReflectTest?{

          ?public?static?void?main(String[]?args)?{
          ??//?反射創(chuàng)建對象
          ??ClassLoader?contextClassLoader?=?Thread.currentThread().getContextClassLoader();
          ??try?{
          ???Class?clazz?=?contextClassLoader.loadClass("com.domoment.leaves.common.util.reflect.TestPeople");
          ???if(clazz?!=?null)?{
          ?????Object?people?=?clazz.newInstance();
          ?????System.out.println("newInstance?start?json:"?+?JsonUtil.objectToJson(people));
          ?????
          ?????
          ?????Method?setName?=?clazz.getMethod("setName",?String.class);
          ?????setName.invoke(people,?"inoverFrank");
          ?????
          ?????System.out.println("newInstance?end?json:"?+?JsonUtil.objectToJson(people));
          ?????
          ?????InvocationHandler?handler?=?new?DefProxy(people);
          ?????
          ?????????????????//?構(gòu)造代理對象
          ?????People?proxyPeople?=?(People)Proxy.
          ???????newProxyInstance(handler.getClass().getClassLoader(),?people.getClass().getInterfaces(),?handler);

          ?????proxyPeople.setName("proxySetFrank");
          ?????proxyPeople.setAge(20);
          ?????proxyPeople.setMoney(new?BigDecimal(999));
          ?????System.out.println("proxyPeople?end?json:"?+?JsonUtil.objectToJson(people));
          ?????proxyPeople.addMoney(new?BigDecimal(20));
          ?????System.out.println("proxyPeople?add?json:"?+?JsonUtil.objectToJson(people));
          ?????proxyPeople.subTractMoney(new?BigDecimal(17));
          ?????System.out.println("proxyPeople?end?json:"?+?JsonUtil.objectToJson(people));
          ?????
          ???}
          ??}?catch?(Exception?e)?{
          ???e.printStackTrace();
          ??}
          ?}
          }

          控制臺打印

          newInstance?start?json:{}
          newInstance?end?json:{"name":"inoverFrank"}
          proxy:setName
          proxy:setAge
          proxy:setMoney
          proxyPeople?end?json:{"name":"proxySetFrank","age":20,"money":999}
          open?Transaction
          proxy:addMoney
          close?Transaction
          proxyPeople?add?json:{"name":"proxySetFrank","age":20,"money":1019}
          open?Transaction
          proxy:subTractMoney
          close?Transaction
          proxyPeople?end?json:{"name":"proxySetFrank","age":20,"money":1002}

          可以看到方法上有 defTransaction 注解的時候,

          方法執(zhí)行前 打印 open Transaction

          方法執(zhí)行后 打印 close Transaction

          這是模擬,真實場景就可以將打印改為代理時擴(kuò)展方法,如數(shù)據(jù)庫操作時候,開啟關(guān)閉事務(wù)




          粉絲福利:實戰(zhàn)springboot+CAS單點登錄系統(tǒng)視頻教程免費領(lǐng)取

          ???

          ?長按上方微信二維碼?2 秒
          即可獲取資料



          感謝點贊支持下哈?

          瀏覽 56
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  美女操逼图日韩无码 | 天天插伊人| 久热久| 免费日皮视频在线观看 | 国产免费一区二区三区最新不卡 |