`
forchenyun
  • 浏览: 312257 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Eclipse插件Lazy Start实现原理分析

阅读更多

 

转载自:http://www.pin5i.com/showtopic-19933.html

每次提到有关Eclipse插件启动的问题的时候,脑子中自然的反应就是:可以设定为预先启动(org.eclipse.ui.startup),否则默认的情况下是懒启动(Lazy Start),只有当插件中的功能被真正调用的时候,插件才会被启动。可能是人也跟着变懒了,也一直没有去留心Eclipse底层是怎么实现这种懒加载的,只是有个大致的猜测,估计又是用hook机制了。昨天闲着具体看了一下实现,果然是类似的实现。下面就大致和大家分享一下,说的不一定准确,仅供参考 ~_~。

      直接进入主题,我们的Eclipse实例启动肯定要构造工作区,那么ResourcesPlugin肯定会被启动,我们就在ResourcesPlugin.startup方法设置一个断点,调试栈如下:
    
附件: lazy_01.jpg 

附件: lazy_02.jpg     

          
    假设我们对插件类型加载细节不知道,猜测大致过程如下:

        1、 DefaultClassLoader加载类型(org.eclipse.core.resources.IContainer)

        2、EclipseLazyStarter.preFindLocalClass

        3、 启动资源插件:ResourcesPlugin.startup

          
    补充说明:

        1、 org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader是Eclipse针对OSGI类加载实现的核心角色,也是eclipse插件默认的类加载器类型,当然,每个插件有自己独立的类加载器实例来负责类型加载。

        2、 DefaultClassLoader、BundleLoader、ClasspathManager三者协作,处理类型加载请求(为什么一个类加载过程要搞的这么复杂呢?Eclipse的考虑是什么呢? 大家思考吧~_~)

    
        【EclipseLazyStarter调用分析】
        我们先大致看一下EclipseLazyStarter.preFindLocalClass方法的代码实现:

1 public class EclipseLazyStarter implements ClassLoadingStatsHook, HookConfigurator {
2    public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException {
3        //首先判断,如果不需要启动则返回
4          
5          //如果插件正在启动,则设定5000ms超时等待;如果超时,直接报错返回

7          //启动插件
8    }
9 }        
    加载类型之前为什么要给回调一下EclipseLazyStarter. preFindLocalClass,又hook了?我们看了一下EclipseLazyStarter继承了ClassLoadingStatsHook接口,ClassLoadingStatsHook接口的类型API文档说明了它的作用:

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


        追踪前面的调用栈,ClassLoadingStatsHook是在ClasspathManager.findLocalClass中被调用的:
          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.preFindLocalClass(classname, this);
7            result = findLocalClassImpl(classname, hooks);
8            return result;
9        } finally {
10            for (int i = 0; i < hooks.length; i++)
11                hooks.postFindLocalClass(classname, result, this);
12        }
13    }
        再接着往下看之前,我们大致已经知道来的Eclipse的插件lazy start是怎么回事了:
        EclipseLazyStarter hook到了插件类加载器的类型加载过程中了,在类型被加载之前会回调EclipseLazyStarter. preFindLocalClass方法:如果类型所在插件还没启动,启动它;如果正在启动,则设置5000ms的超时,限时不能完成启动,则报错返回!

  (附加说明:头一段时间在另外一篇随笔中,写了一些编写插件启动类应该注意的点,其中有一条就是避免在插件启动方法中干耗时的事情。这里真正告诉我们了原因:如果超过5000ms不能完成启动--注意这其中还不包含所依赖插件的启动时间,那么肯定会出现类加载超时的错误了:
    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是如何完成注册过程的?】
附件: lazy_03.jpg     
    过程简要解释如下:
    1、启动osgi framework,两种启动方式:如果想利用Eclipse的一些特性,则就以EclipseStarter为入口点启动;否则,可以用命令行的方式,以Laucher.main为入口点启动
    2、初始化FrameworkAdaptor(对应eclipse实现是BaseAdaptor)看一下接口说明:
        /**
* 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
*/      显而易见,FrameworkAdaptor其实是osgi framework的后门,提供平台附加支持。
      
      看一下BaseAdaptor的构造函数:
        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);
13        // get the storage after the registry has been initialized
14        storage = getStorage();
15        // TODO consider passing args to BaseAdaptorHooks
16    }      我们看到,调用了HookRegistry.initialize进行初始化
        
    3、初始化HookRegistry,我们直接看一下HookRegistry.initialize方法实现
          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 ("osgi.hook.configurators.include") 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 ("osgi.hook.configurators.exclude") 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方法调用,读取了一个名为hookconfigurators.properties的属性配置文件,在org.eclipse.osgi插件中。看一下里面的内容:
      1 ###############################################################################
2 # Copyright (c) 2005, 2006 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赫然在列!!!

    
    回过头来看一下EclipseLazyStarter(继承ClassLoadingStatsHook)的使用方式:
    BaseAdaptor.getHookRegistry().getClassLoadingStatsHooks()

    前面已经看了ClasspathManager中findLocalClass方法的代码,就是这么调用ClassLoadingStatsHook policy的(我们的EclipseLazyStarter...)

  【总结】
    hook了,osgi framework留了个后门,Eclipse好好的利用了这个后门~_~

  【附加说明】
    1、EclipseLazyStarter只是ClassLoadingStatsHook policy的实现,其实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、大家可以顺带详细的看一下HookRegistry、HookConfigurator、BaseAdaptor等

    3、hook这种手法在Eclipse的资源管理中也有比较成功的应用,可以看一下
    org.eclipse.core.resources.team.IMoveDeleteHook
    例如cvs、ClearCase等团队开发管理工具中,都实现了这种hook,通过扩展点org.eclipse.core.resources.moveDeleteHook动态挂入。大家有兴趣可以深入看看,看过之后应该就明白了为什么cvs、ClearCase等一些团队开发管理工具功能有一些不同了~_~
    
    4、对osgi感兴趣的同学,可以看一下org.eclipse.osgi插件中的代码,质量很高~_~

分享到:
评论

相关推荐

    Eclipse插件开发方法与实战

    - 插件的核心是实现`org.eclipse.ui.plugin.AbstractUIPlugin`类,该类继承自`org.eclipse.core.runtime.Plugin`,并实现了生命周期方法。 - 创建视图(View)、透视图(Perspective)、编辑器(Editor)、命令...

    Eclipse插件学习笔记

    10. **插件性能优化**:掌握提高Eclipse插件性能的方法,如延迟加载(Lazy Loading)、插件激活策略等。 书中包含的章节如"chapter12"至"chapter24",很可能分别对应上述知识点的不同部分,深入讲解了每个主题。...

    ps ai光滑线条辅助插件Lazy Nezumi

    "Lazy Nezumi"是一款专为图形设计师和插画师设计的专业级插件,它主要应用于Adobe Photoshop(PS)和Adobe Illustrator(AI)这两款强大的图像处理和矢量图形编辑软件。这款插件的主要功能是提供光滑、精确的线条...

    深入探索 React 懒加载:React.lazy 的实现原理与应用实践

    本文将深入探讨 React 中懒加载的实现原理和应用实践。 React 是一个用于构建用户界面的 JavaScript 库,以其组件化和声明式编程模型而广受欢迎。随着现代 Web 应用的不断增长,页面的加载时间和性能成为了开发者...

    js css eclipse压缩插件

    而 "plugins" 文件夹则包含实际的插件实现,它可能包括了插件的Java代码、资源文件和配置信息。安装插件时,Eclipse 会读取这两个文件夹中的内容,并将其整合到开发环境中。 使用这样的压缩插件对于前端开发者来说...

    jquery城市选择插件lazyload-min.js.rar

    在本文中,我们将深入探讨一款名为"lazyload-min.js"的jQuery城市选择插件,了解其工作原理和应用方法。 首先,"lazyload-min.js"是一个优化过的轻量级JavaScript文件,它基于流行的jQuery库,实现了城市选择的功能...

    magento lazyload插件

    它的主要功能是实现图片的延迟加载(Lazy Load),以此提升网站的加载速度和用户体验。在网页浏览时,传统方式下所有图片会一次性全部加载,这可能导致页面加载时间过长,特别是对于拥有大量图片的电商网站来说,这...

    jQuery图片延迟加载插件Lazy Load.zip

    jQuery Lazy Load插件实现了这一功能,它是基于流行的JavaScript库jQuery构建的。使用该插件,开发者可以轻松地将延迟加载集成到他们的网站中,无论是在图片相册、博客文章还是产品展示页面中。以下是一些关键知识点...

    jquery.lazyload 实现图片延迟加载

    **jQuery LazyLoad 插件详解:实现图片延迟加载** 在网页设计中,为了提升用户体验,减少页面初次加载的时间,一种常见的优化策略是采用图片延迟加载(Image Lazy Load)技术。`jQuery LazyLoad` 是一个非常实用的 ...

    js lazyload实现网页图片延迟加载特效

    在网页设计中,为了提高页面加载速度和优化用户体验,一种常见的技术是图片延迟加载,也称为懒加载(Lazy Load)。JavaScript 是实现这一功能的主要工具,它允许我们在用户滚动到图片时才加载图片,而不是一次性加载...

    对插件清单的一些分析

    Eclipse 3.4之后,`MANIFEST.MF`文件中的`Eclipse-LazyStart: true`已被`Bundle-ActivationPolicy: lazy`替代,表示插件的懒加载策略,即插件只有在实际需要时才会被激活,从而提高Eclipse的启动性能。 在Eclipse中...

    Jquery.LazyLoad.js实现图片延迟加载插件

    没解决方案,就得发挥咱DIY的精神,自己想法解决,分析了BUG,理了理思路,结合前段时间我做弹出窗口特效的方法,解决了Jquery.LazyLoad.js的兼容问题,现将思路和方法与大家分享一下。 解决思路大致是两点,一是...

    lazyload.js图片延迟加载(懒加载)插件

    - **jquery.lazyload.js**:这是懒加载插件的核心文件,包含了实现图片延迟加载功能的JavaScript代码,需要在网页中引入并进行适当配置。 - **图片延迟加载(懒加载)jQuery插件**:可能是一个包含使用该插件的HTML、...

    城市选择插件lazyload-min.js

    该插件的实现原理是利用jQuery的事件监听和Ajax异步请求,根据用户的操作动态获取并展示所需数据。 在使用`lazyload-min.js`之前,我们需要确保页面已经引入了jQuery库。之后,我们可以将插件文件`lazyload-min.js`...

    jquery lazyload延迟加载技术的实现原理分析

    《jQuery LazyLoad延迟加载技术的实现原理》 延迟加载(LazyLoad)技术是现代网页优化的重要策略之一,尤其对于图片、Flash资源、iframe以及类似FCK的网页编辑器等大容量资源,它能够显著提升页面加载速度,提高...

    lazyviewport插件

    Blender 的一个简单插件,用于将标准 G、R、S 热键映射到视图工具,因此您不必使用捕捉热键 X、Y、Z 在Blender软件中 Preferecens&gt;Addons&gt;Install 并导航到解压后的 lazyviewport.py 点击安装

    lazyload.js实现图片异步延迟加载

    在本文中,我们将深入探讨如何使用`lazyload.js`这个JavaScript库来实现这一功能。 ### 1. 懒加载原理 懒加载的基本原理是,当用户滚动页面时,只加载视口内的图片,而那些位于视口之外的图片则暂时不加载。当用户...

    Lazy Linked-List(论文实现方法)

    《Lazy Linked-List:一种高效的内存管理策略》 在计算机科学中,数据结构是构建算法的基础,而链表作为其中的一员...理解并掌握Lazy Linked-List的原理和实现,对于开发高并发、低延迟的应用程序具有重要的指导意义。

    Lazy Load Plugin for jQuery demo

    jQuery Lazy Load Plugin 是一个专门为 jQuery 设计的实现这一功能的插件,它能有效地提升页面加载速度,降低用户等待时间,从而提供更好的用户体验。 标题 "Lazy Load Plugin for jQuery demo" 暗示这是一个关于...

    jQuery_lazyload

    jQuery_lazyload通过监听滚动事件来实现延迟加载。当用户滚动页面,使得原先不在视口内的图片或者其他元素进入视口时,插件会动态地替换这些元素的`src`属性,使其加载真实的内容。这样,只有当用户实际需要看到某...

Global site tag (gtag.js) - Google Analytics