<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評(píng)論 - 132, 引用 - 0
    數(shù)據(jù)加載中……

    【Eclipse插件開(kāi)發(fā)】Eclipse插件Lazy Start實(shí)現(xiàn)原理分析

             

    Eclipse插件Lazy Start實(shí)現(xiàn)原理分析

                                                                                        朱興zhu_xing@live.cn

           每次提到有關(guān)Eclipse插件啟動(dòng)的問(wèn)題的時(shí)候,腦子中自然的反應(yīng)就是:可以設(shè)定為預(yù)先啟動(dòng)(org.eclipse.ui.startup),否則默認(rèn)的情況下是懶啟動(dòng)(Lazy Start),只有當(dāng)插件中的功能被真正調(diào)用的時(shí)候,插件才會(huì)被啟動(dòng)。可能是人也跟著變懶了,也一直沒(méi)有去留心Eclipse底層是怎么實(shí)現(xiàn)這種懶加載的,只是有個(gè)大致的猜測(cè),估計(jì)又是用hook機(jī)制了。昨天閑著具體看了一下實(shí)現(xiàn),果然是類似的實(shí)現(xiàn)。下面就大致和大家分享一下,說(shuō)的不一定準(zhǔn)確,僅供參考 _~。

           直接進(jìn)入主題,我們的Eclipse實(shí)例啟動(dòng)肯定要構(gòu)造工作區(qū),那么ResourcesPlugin肯定會(huì)被啟動(dòng),我們就在ResourcesPlugin.startup方法設(shè)置一個(gè)斷點(diǎn),調(diào)試棧如下:
        
        

             

        假設(shè)我們對(duì)插件類型加載細(xì)節(jié)不知道,猜測(cè)大致過(guò)程如下:

            1、 DefaultClassLoader加載類型(org.eclipse.core.resources.IContainer

            2、EclipseLazyStarter.preFindLocalClass

            3、 啟動(dòng)資源插件:ResourcesPlugin.startup

             

        補(bǔ)充說(shuō)明:

            1、 org.eclipse.osgi.internal.baseadaptor.DefaultClassLoaderEclipse針對(duì)OSGI類加載實(shí)現(xiàn)的核心角色,也是eclipse插件默認(rèn)的類加載器類型,當(dāng)然,每個(gè)插件有自己獨(dú)立的類加載器實(shí)例來(lái)負(fù)責(zé)類型加載。

            2、 DefaultClassLoader、BundleLoader、ClasspathManager三者協(xié)作,處理類型加載請(qǐng)求(為什么一個(gè)類加載過(guò)程要搞的這么復(fù)雜呢?Eclipse的考慮是什么呢? 大家思考吧~_~)

        
            【EclipseLazyStarter調(diào)用分析】
            我們先大致看一下EclipseLazyStarter.preFindLocalClass方法的代碼實(shí)現(xiàn)

    1 public class EclipseLazyStarter implements ClassLoadingStatsHook, HookConfigurator {
    2     public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
    3         //首先判斷,如果不需要啟動(dòng)則返回
    4          
    5          //如果插件正在啟動(dòng),則設(shè)定5000ms超時(shí)等待;如果超時(shí),直接報(bào)錯(cuò)返回
    6 
    7          //啟動(dòng)插件
    8     }
    9 }
           

        加載類型之前為什么要給回調(diào)一下EclipseLazyStarter. preFindLocalClass,又hook了?我們看了一下EclipseLazyStarter繼承了ClassLoadingStatsHook接口,ClassLoadingStatsHook接口的類型API文檔說(shuō)明了它的作用:

    A ClassLoadingStatsHook hooks into the <code>ClasspathManager</code> class.


            追蹤前面的調(diào)用棧,ClassLoadingStatsHook是在ClasspathManager.findLocalClass中被調(diào)用的:
            
     1 public Class findLocalClass(String classname) throws ClassNotFoundException {
     2         Class result = null;
     3         ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
     4         try {
     5             for (int i = 0; i < hooks.length; i++)
     6                 hooks[i].preFindLocalClass(classname, this);
     7             result = findLocalClassImpl(classname, hooks);
     8             return result;
     9         } finally {
    10             for (int i = 0; i < hooks.length; i++)
    11                 hooks[i].postFindLocalClass(classname, result, this);
    12         }
    13     }

            再接著往下看之前,我們大致已經(jīng)知道來(lái)的Eclipse的插件lazy start是怎么回事了:
            EclipseLazyStarter hook到了插件類加載器的類型加載過(guò)程中了,在類型被加載之前會(huì)回調(diào)EclipseLazyStarter. preFindLocalClass方法:如果類型所在插件還沒(méi)啟動(dòng),啟動(dòng)它;如果正在啟動(dòng),則設(shè)置5000ms的超時(shí),限時(shí)不能完成啟動(dòng),則報(bào)錯(cuò)返回!

       (附加說(shuō)明:頭一段時(shí)間在另外一篇隨筆中,寫了一些編寫插件啟動(dòng)類應(yīng)該注意的點(diǎn),其中有一條就是避免在插件啟動(dòng)方法中干耗時(shí)的事情。這里真正告訴我們了原因:如果超過(guò)5000ms不能完成啟動(dòng)--注意這其中還不包含所依賴插件的啟動(dòng)時(shí)間,那么肯定會(huì)出現(xiàn)類加載超時(shí)的錯(cuò)誤了:
         While loading class "{1}", thread "{0}" timed out waiting ({4}ms) for thread "{2}" to finish starting bundle "{3}". To avoid deadlock, thread "{0}" is proceeding but "{1}" may not be fully initialized.
        )

        【EclipseLazyStarter是如何完成注冊(cè)過(guò)程的?】
        
        過(guò)程簡(jiǎn)要解釋如下:
        1、啟動(dòng)osgi framework,兩種啟動(dòng)方式:如果想利用Eclipse的一些特性,則就以EclipseStarter為入口點(diǎn)啟動(dòng);否則,可以用命令行的方式,以Laucher.main為入口點(diǎn)啟動(dòng)
        2、初始化FrameworkAdaptor(對(duì)應(yīng)eclipse實(shí)現(xiàn)是BaseAdaptor)看一下接口說(shuō)明:
            
    /**
     * FrameworkAdaptor interface to the osgi framework. This class is used to provide
     * platform specific support for the osgi framework.
     *
     * <p>The OSGi framework will call this class to perform platform specific functions.
     *
     * Classes that implement FrameworkAdaptor MUST provide a constructor that takes as a
     * parameter an array of Strings.  This array will contain arguments to be
     * handled by the FrameworkAdaptor.  The FrameworkAdaptor implementation may define the format
     * and content of its arguments.
     *
     * The constructor should parse the arguments passed to it and remember them.
     * The initialize method should perform the actual processing of the adaptor
     * arguments.
     * <p>
     * Clients may implement this interface.
     * </p>
     * 
    @since 3.1
     
    */
          顯而易見(jiàn),F(xiàn)rameworkAdaptor其實(shí)是osgi framework的后門,提供平臺(tái)附加支持。
           
          看一下BaseAdaptor的構(gòu)造函數(shù):
          
     1 /**
     2      * Constructs a BaseAdaptor.
     3      * @param args arguments passed to the adaptor by the framework.
     4      */
     5     public BaseAdaptor(String[] args) {
     6         if (LocationManager.getConfigurationLocation() == null)
     7             LocationManager.initializeLocations();
     8         hookRegistry = new HookRegistry(this);
     9         FrameworkLogEntry[] errors = hookRegistry.initialize();
    10         if (errors.length > 0)
    11             for (int i = 0; i < errors.length; i++)
    12                 getFrameworkLog().log(errors[i]);
    13         // get the storage after the registry has been initialized
    14         storage = getStorage();
    15         // TODO consider passing args to BaseAdaptorHooks
    16     }
          我們看到,調(diào)用了HookRegistry.initialize進(jìn)行初始化
            
        3、初始化HookRegistry,我們直接看一下HookRegistry.initialize方法實(shí)現(xiàn)
            
     1 /**
     2      * Initializes the hook configurators.  The following steps are used to initialize the hook configurators. <p>
     3      * 1. Get a list of hook configurators from all hook configurators properties files on the classpath, 
     4      *    add this list to the overall list of hook configurators, remove duplicates. <p>
     5      * 2. Get a list of hook configurators from the (&quot;osgi.hook.configurators.include&quot;) system property 
     6      *    and add this list to the overall list of hook configurators, remove duplicates. <p>
     7      * 3. Get a list of hook configurators from the (&quot;osgi.hook.configurators.exclude&quot;) system property
     8      *    and remove this list from the overall list of hook configurators. <p>
     9      * 4. Load each hook configurator class, create a new instance, then call the {@link HookConfigurator#addHooks(HookRegistry)} method <p>
    10      * 5. Set this HookRegistry object to read only to prevent any other hooks from being added. <p>
    11      * @return an array of error log entries that occurred while initializing the hooks
    12      */
    13     public FrameworkLogEntry[] initialize() {
    14         ArrayList configurators = new ArrayList(5);
    15         ArrayList errors = new ArrayList(0); // optimistic that no errors will occur
    16         mergeFileHookConfigurators(configurators, errors);
    17         mergePropertyHookConfigurators(configurators);
    18         loadConfigurators(configurators, errors);
    19         // set to read-only
    20         readonly = true;
    21         return (FrameworkLogEntry[]) errors.toArray(new FrameworkLogEntry[errors.size()]);
    22     }

          其中的mergeFileHookConfigurators方法調(diào)用,讀取了一個(gè)名為hookconfigurators.properties的屬性配置文件,在org.eclipse.osgi插件中??匆幌吕锩娴膬?nèi)容:
         
     1 ###############################################################################
     2 # Copyright (c) 20052006 IBM Corporation and others.
     3 # All rights reserved. This program and the accompanying materials
     4 # are made available under the terms of the Eclipse Public License v1.0
     5 # which accompanies this distribution, and is available at
     6 # http://www.eclipse.org/legal/epl-v10.html
     7 #
     8 # Contributors:
     9 #     IBM Corporation - initial API and implementation
    10 ###############################################################################
    11 hook.configurators= \
    12  org.eclipse.osgi.internal.baseadaptor.BaseHookConfigurator,\
    13  org.eclipse.osgi.internal.baseadaptor.DevClassLoadingHook,\
    14  org.eclipse.core.runtime.internal.adaptor.EclipseStorageHook,\
    15  org.eclipse.core.runtime.internal.adaptor.EclipseLogHook,\
    16  org.eclipse.core.runtime.internal.adaptor.EclipseErrorHandler,\
    17  org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorHook,\
    18  org.eclipse.core.runtime.internal.adaptor.EclipseClassLoadingHook,\
    19  org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter,\
    20  org.eclipse.core.runtime.internal.stats.StatsManager,\
    21  org.eclipse.osgi.internal.verifier.SignedBundleHook
    22 


        ^_^,我們的EclipseLazyStarter赫然在列?。?!

         
        回過(guò)頭來(lái)看一下EclipseLazyStarter(繼承ClassLoadingStatsHook)的使用方式:
        BaseAdaptor.getHookRegistry().getClassLoadingStatsHooks()

        前面已經(jīng)看了ClasspathManager中findLocalClass方法的代碼,就是這么調(diào)用ClassLoadingStatsHook policy的(我們的EclipseLazyStarter...)

       【總結(jié)】
        hook了,osgi framework留了個(gè)后門,Eclipse好好的利用了這個(gè)后門~_~

       【附加說(shuō)明】
        1、EclipseLazyStarter只是ClassLoadingStatsHook policy的實(shí)現(xiàn),其實(shí)HookRegsitry中還有其他的hook policy,例如:
        org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook
        org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook
        org.eclipse.osgi.baseadaptor.hooks.BundleFileFactoryHook
        org.eclipse.osgi.baseadaptor.hooks.StorageHook
        org.eclipse.osgi.baseadaptor.hooks.AdaptorHook

        2、大家可以順帶詳細(xì)的看一下HookRegistry、HookConfigurator、BaseAdaptor等

        3、hook這種手法在Eclipse的資源管理中也有比較成功的應(yīng)用,可以看一下
        org.eclipse.core.resources.team.IMoveDeleteHook
        例如cvs、ClearCase等團(tuán)隊(duì)開(kāi)發(fā)管理工具中,都實(shí)現(xiàn)了這種hook,通過(guò)擴(kuò)展點(diǎn)org.eclipse.core.resources.moveDeleteHook動(dòng)態(tài)掛入。大家有興趣可以深入看看,看過(guò)之后應(yīng)該就明白了為什么cvs、ClearCase等一些團(tuán)隊(duì)開(kāi)發(fā)管理工具功能有一些不同了~_~
        
        4、對(duì)osgi感興趣的同學(xué),可以看一下org.eclipse.osgi插件中的代碼,質(zhì)量很高~_~
        亂轟轟的,湊合著看吧



    本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!

    posted on 2008-08-19 18:05 zhuxing 閱讀(2658) 評(píng)論(2)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI

    評(píng)論

    # re: 【Eclipse插件開(kāi)發(fā)】Eclipse插件Lazy Start實(shí)現(xiàn)原理分析  回復(fù)  更多評(píng)論   

    老弟,寫的通俗易懂一點(diǎn)好不好,看得比較暈:)

    鼓勵(lì)一下,很有鉆研精神!
    2008-08-20 21:23 | Always BaNg.

    # re: 【Eclipse插件開(kāi)發(fā)】Eclipse插件Lazy Start實(shí)現(xiàn)原理分析  回復(fù)  更多評(píng)論   

    比較高深,迷茫中。。。。。。
    2008-12-06 09:58 | 楓葉KR

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 好爽…又高潮了免费毛片| 亚洲一级毛片免观看| 成人免费无码精品国产电影| 中文字幕免费不卡二区| 亚洲狠狠婷婷综合久久蜜芽| 亚洲av色福利天堂| 国产亚洲色视频在线| 日本免费无遮挡吸乳视频电影| 国产91免费在线观看| 免费国产成人18在线观看| 亚洲精品视频免费| 久久精品国产亚洲AV天海翼| 精品亚洲AV无码一区二区| 久久亚洲美女精品国产精品| 久久夜色精品国产亚洲| 亚洲片国产一区一级在线观看| 午夜视频免费成人| 免费A级毛片无码免费视| 亚洲第一网站免费视频| 777爽死你无码免费看一二区| 中文字幕免费观看视频| 国产精品99爱免费视频| 午夜在线免费视频 | 七色永久性tv网站免费看| 精品久久久久久无码免费| 国产高清视频免费在线观看 | 亚洲欧美熟妇综合久久久久 | 免费A级毛片无码A∨| 免费无码又爽又刺激网站| 两个人看www免费视频| 成av免费大片黄在线观看| 国产伦精品一区二区免费| 中文字幕免费在线看线人动作大片| 永久免费无码网站在线观看个| 日本高清免费中文在线看| 成年网在线观看免费观看网址| 无遮挡免费一区二区三区 | 亚洲精品白浆高清久久久久久| 国产精品亚洲A∨天堂不卡| 亚洲VA中文字幕无码一二三区| 亚洲av丰满熟妇在线播放|