现在的位置: 首页 > 综合 > 正文

分析Eclipse源代码,理解OSGI插件机制内幕

2013年08月18日 ⁄ 综合 ⁄ 共 4172字 ⁄ 字号 评论关闭

一、概述

        一直关注我blog的朋友会看到,最近我一直在关注Eclipse源代码的编译工作,但除了简单的编译设置和烦琐而极具耐心的源代码剥离,似乎还没有什么太有趣的东西出现。现在,经过了前面一系列的热身运动,我将和大家一起走入Eclipse的内核,看看它到底是怎么工作的?

        1、Eclipse源代码        版本:3.1.1        大小:63.2MB

        eclipse-sourceBuild-srcIncluded-3.1.1.zip

        下载地址:http://download.eclipse.org/eclipse/downloads

        2、源代码阅读工具        Source Insight  V3.5

         它其实是一个代码编辑软件,因为有强大的代码分析工具,可以很方便地跟踪代码的相关性,所以常用来作为阅读代码的工具。

         下载地址:http://sourceinsight.com/down35.html

         为了方便代码的分析,我们只提取以下几个插件的代码:

org.eclipse.platform                             org.eclipse.platform_3.1.1.jar
org.eclipse.core.commands              org.eclipse.core.commands_3.1.0.jar
org.eclipse.core.expressions            org.eclipse.core.expressions_3.1.0.jar
org.eclipse.core.runtime                     org.eclipse.core.runtime_3.1.1.jar
org.eclipse.help                                    org.eclipse.help_3.1.0.jar
org.eclipse.jface                                   org.eclipse.jface_3.1.1.jar
org.eclipse.osgi                                    org.eclipse.osgi_3.1.1.jar
org.eclipse.swt.win32.win32.x86      org.eclipse.swt.win32.win32.x86_3.1.1.jar
org.eclipse.swt                                     org.eclipse.swt_3.1.0.jar
org.eclipse.ui.workbench                   org.eclipse.ui.workbench_3.1.1.jar
org.eclipse.ui                                        org.eclipse.ui_3.1.1.jar
org.eclipse.update.configurator        org.eclipse.update.configurator_3.1.0.jar

         将这些代码解压缩到一个空目录里,然后导入到Source Insight的Project里。     

二、Eclipse启动过程

        首先我们从Eclipse的启动过程开始分析。

        1、eclipse.exe

        它是Eclipse的启动文件,是与平台相关的可执行文件。它的功能比较简单,主要是加载startup.jar文件,代码在Eclipse源代码的/features/org.eclipse.platform.launchers/library目录下,对应多个平台。对于win32平台,你可以直接运行win32目录下的build.bat文件来编译得到它(需要安装C编译器)。

        2、startup.jar

        这个是Eclipse真正的启动文件,你可以在命令行下运行java -jar startup.jar命令来启动Eclipse。它的入口是org.eclipse.core.launcher.Main,它对应的源代码在org.eclipse.platform/src目录的子目录下的Main.java。我们从main函数往后跟踪,找到basicRun,这个是启动的主要部分。

protected void basicRun(String[] args) throws Exception {
        ......
        setupVMProperties();                  //设置VM属性
        processConfiguration();             //读取configuration/config.ini配置文件
        ......
        // need to ensure that getInstallLocation is called at least once to initialize the value.
        // Do this AFTER processing the configuration to allow the configuration to set
        // the install location. 
        getInstallLocation();

        // locate boot plugin (may return -dev mode variations)
        URL[] bootPath = getBootPath(bootLocation);

        setSecurityPolicy(bootPath);       //设置执行权限

        // splash handling is done here, because the default case needs to know
        // the location of the boot plugin we are going to use
        handleSplash(bootPath);

        invokeFramework(passThruArgs, bootPath);            //启动Eclipse内核
    }

这个函数前面部分是设置一些属性,最关键的是最后invokeFramework函数,它是启动Eclipse的核心。下面我们看看invokeFramework函数的具体内容。

private void invokeFramework(String[] passThruArgs, URL[] bootPath) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, Error, Exception, InvocationTargetException {
        ......
        URLClassLoader loader = new StartupClassLoader(bootPath, parent);

        Class clazz = loader.loadClass(STARTER);             //加载   String STARTER = "org.eclipse.core.runtime.adaptor.EclipseStarter";
        Method method = clazz.getDeclaredMethod("run", new Class[] {String[].class, Runnable.class});          //获得run方法
        ......
        method.invoke(clazz, new Object[] {passThruArgs, endSplashHandler});           //调用run方法
        ......
    }

首先创建加载器loader,它是一个URLClassLoader类型。接着加载类"org.eclipse.core.runtime.adaptor.EclipseStarter",获得其run方法,然后调用此方法。

        3、OSGI启动

        "org.eclipse.core.runtime.adaptor.EclipseStarter"类的源代码位于/plugins/org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor。可见它已经位于OSGI包内,它是OSGI的启动类。

 public static void startup(String[] args, Runnable endSplashHandler) throws Exception {
  ......
  adaptor = createAdaptor();              //建立适配器
  ......
  OSGi osgi = new OSGi(adaptor);                 //建立OSGI对象,这就是我们要找的东西
  ......
  osgi.launch();          //启动OSGI
  ......
  context = osgi.getBundleContext();                  //获得已加载的Bundle的执行上下文
  ......
  Bundle[] startBundles = loadBasicBundles();              //加载Bundle
  setStartLevel(getStartLevel());             //设置启动级别
  ......
 }

抱歉!评论已关闭.