`
forchenyun
  • 浏览: 312688 次
  • 性别: 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" 暗示这是一个关于...

    Lazy Nezumi Pro(高级绘画插件)18.04.08.2351

    Lazy Nezumi Pro 是一个 Windows 应用程序,可以帮助你画出流畅,优美的线条,用鼠标或手写板。 它能与许多你喜爱的程序协作。可以让你拥有独特的笔刷稳定系统。本工具支持绝大多数的 2D 和 3D 绘图软件。 在 ...

Global site tag (gtag.js) - Google Analytics