分析Eclipse源代碼,理解OSGI插件機制內幕

<script language="javascript" type="text/javascript">document.title="分析Eclipse源代碼,理解OSGI插件機制內幕 - "+document.title</script>

一、概述

        一直關注我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());             //設置啓動級別
  ......
 }

發佈了38 篇原創文章 · 獲贊 0 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章