jvm原始碼解讀--20 結合jvm原始碼理解 java 設計模式 模板方法
阿新 • • 發佈:2021-06-25
write by 張豔濤
前言:
在學習jvm之前,看過設計模式的書,知道模板方法的設計模式,今天在看java併發程式設計的藝術裡面關於AbstractQueuedSynchronizer 用法,這個就使用了模板方法了,開始沒注意到,回想過去的設計模式的知識,才看清楚了,那麼模板方法的原理是什麼呢?結合jvm虛擬機器原理? 我想答案是多型
那麼,現在寫一篇分析過程,來解析這個過程
新進一個Man類 和一個Person類
package com.zyt.java_concurrency_in_practice.templatemode; public class Man extends Person{ @Overrideprotected void sleep() { System.out.println("子類在執行 Sleep~~~~"); } public static void main(String[] args) { Man man = new Man(); man.sayHi(); } } //========= package com.zyt.java_concurrency_in_practice.templatemode; public abstract class Person { protected voidsleep(){ System.out.println("父類,在執行sleeping 方法"); }; protected void sayHi(){ sleep(); } }
列印執行結果
子類在執行 Sleep~~~~
Process finished with exit code 0
這個問題關鍵點是在父類方法裡面的sleep()方法是子類的方法,不是父類的sleep方法!!!
關鍵點是呼叫方法,會有一個this物件的引數,比如說 子類物件.function() ;那麼 this 就是子類物件,static 方法 沒有this物件
那麼就來解析模板方法的實現原理
public static void main(String[] args) { Man man = new Man(); man.sayHi(); } ========================================== 0 new #5 <com/zyt/java_concurrency_in_practice/templatemode/Man> 3 dup 4 invokespecial #6 <com/zyt/java_concurrency_in_practice/templatemode/Man.<init>> 7 astore_1 8 aload_1 9 invokevirtual #7 <com/zyt/java_concurrency_in_practice/templatemode/Man.sayHi> 12 return
逐句分析
- 編號0的第一句是新建物件 man,現在這個man物件在運算元棧上
- dup 是在運算元棧上覆制man物件
- invokespecial init 是呼叫初始化方法,返回時候會消耗一個dup出來的man物件
- 編號7將man物件儲存在本地變量表裡面
- 編號8 將 位置為1的變數載入到運算元棧上
- 編號9 呼叫Man.sayHi方法
進入到父類方法執行
public abstract class Person { protected void sleep(){ System.out.println("父類,在執行sleeping 方法"); }; protected void sayHi(){ sleep(); } } //===============sayHi()========== 0 aload_0 1 invokevirtual #2 <com/zyt/java_concurrency_in_practice/templatemode/Person.sleep> 4 return
呼叫新方法,會準備新的棧結構,而且會服用運算元棧,和本地變量表
這裡的話,應該會將子類的運算元棧中的man物件,複用為父類方法的本地變量表變數
- 那麼編號為0 的aload_0就是載入子類的man物件(在本地變量表中),到新的運算元棧
- 那麼呼叫 #2 Person.sleep父類的sleep方法,其中的引數是子類的man物件,那麼實際上呼叫的就是子類的sleep方法
- 子類有一個JVM虛表,先排列父類方法,接著排列子類方法,如果子類重寫父類方法sleep,那麼子類的虛表的父類部分的sleep方法會設定為子類方法,從而執行的是子類方法,若未重寫,則方法父類方法