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

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

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

    例子下載在此

    最近搞了個(gè)小實(shí)驗(yàn),發(fā)現(xiàn)Eclipse 插件的類(lèi)加載的一個(gè)問(wèn)題。Eclipse使用Equinox實(shí)現(xiàn)OSGi的框架,可以在插件的配置中確定哪些類(lèi)expose出去,哪些類(lèi)不能為外部所見(jiàn)。我發(fā)現(xiàn)的問(wèn)題是,可以通過(guò)ClassLoader繞過(guò)這個(gè)限制,在外部插件中加載到插件里那些不為外部所見(jiàn)的類(lèi),并且能夠創(chuàng)建類(lèi)的實(shí)例,可以通過(guò)反射調(diào)用其方法(當(dāng)然,如果被加載的類(lèi)實(shí)現(xiàn)了某些接口,也可以通過(guò)接口的引用直接調(diào)用相應(yīng)的方法)。

    為了演示這個(gè)問(wèn)題,先在eclipse中創(chuàng)建一個(gè)插件UtilityLibrary

    其中utilitylibrary.expose包中的類(lèi)會(huì)暴露給外部,而utilitylibrary.hide包中的類(lèi)不會(huì)暴露給外部。在MANIFEST.MF中增加這個(gè)設(shè)置:


    VisiableClassVisiableClass類(lèi)的內(nèi)容很簡(jiǎn)單:
    package utilitylibrary.expose;

    public class VisiableClass {
        
    public VisiableClass() {
            System.out.println(
    "This is VisiableClass");
        }

        
    public String getMessage() {
            
    return "From VisiableClass:\r\n"
                    
    + this.getClass().getClassLoader().toString() + "\t";
        }
    }

    package utilitylibrary.hide;

    public class InvisiableClass {
        
    public InvisiableClass() {
            System.out.println(
    "InvisiableClass");
        }

        
    public String getMessage() {
            
    return "From InvisiableClass:\r\n"
                    
    + this.getClass().getClassLoader().toString() + "\t";
        }
    }


    其實(shí)主要就是打印出相應(yīng)的信息。類(lèi)代碼幾乎是一樣的。

    下面創(chuàng)建另一個(gè)插件UsePlugin,依賴(lài)并使用UtilityLibrary中的類(lèi)。插件其實(shí)就是Eclipse自帶的Hello World程序,它會(huì)在eclipse 的toolbar上增加一個(gè)按鈕,點(diǎn)擊后會(huì)彈出一個(gè)MessageBox。好,MessageBox上顯示的就是從UtilityLibrary中類(lèi)的方法的返回值。首先增加插件依賴(lài)關(guān)系:


    在SampleAction中的Run方法里,如果直接使用InvisiableClass,插件完全找不到這個(gè)類(lèi),修改建議里面建議expose這個(gè)類(lèi):


    當(dāng)然,使用VisiableClass是沒(méi)問(wèn)題的。下面通過(guò)VisiableClass來(lái)將InvisiableClass拽出來(lái),SampleAction類(lèi)的源代碼如下,只要關(guān)心run方法就可以了:

    package useplugin.actions;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    import org.eclipse.jface.action.IAction;
    import org.eclipse.jface.dialogs.MessageDialog;
    import org.eclipse.jface.viewers.ISelection;
    import org.eclipse.ui.IWorkbenchWindow;
    import org.eclipse.ui.IWorkbenchWindowActionDelegate;

    import utilitylibrary.expose.VisiableClass;

    /**
     * Our sample action implements workbench action delegate. The action proxy will
     * be created by the workbench and shown in the UI. When the user tries to use
     * the action, this delegate will be created and execution will be delegated to
     * it.
     * 
     * 
    @see IWorkbenchWindowActionDelegate
     
    */
    public class SampleAction implements IWorkbenchWindowActionDelegate {
        
    private IWorkbenchWindow window;

        
    /**
         * The constructor.
         
    */
        
    public SampleAction() {
        }

        
    /**
         * The action has been activated. The argument of the method represents the
         * 'real' action sitting in the workbench UI.
         * 
         * 
    @see IWorkbenchWindowActionDelegate#run
         
    */
        
    public void run(IAction action) {
            
    try {
                Class
    <?> clazz = VisiableClass.class.getClassLoader().loadClass(
                        
    "utilitylibrary.hide.InvisiableClass");
                Object obj 
    = clazz.newInstance();
                Method method 
    = clazz.getMethod("getMessage");
                Object ret 
    = method.invoke(obj, new Object[] {});
                System.out.println(ret);
                MessageDialog.openInformation(window.getShell(), 
    "UsePlugin", ret
                        .toString());
            } 
    catch (ClassNotFoundException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (InstantiationException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (IllegalAccessException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (SecurityException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (NoSuchMethodException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (IllegalArgumentException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            } 
    catch (InvocationTargetException e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        
    /**
         * Selection in the workbench has been changed. We can change the state of
         * the 'real' action here if we want, but this can only happen after the
         * delegate has been created.
         * 
         * 
    @see IWorkbenchWindowActionDelegate#selectionChanged
         
    */
        
    public void selectionChanged(IAction action, ISelection selection) {
        }

        
    /**
         * We can use this method to dispose of any system resources we previously
         * allocated.
         * 
         * 
    @see IWorkbenchWindowActionDelegate#dispose
         
    */
        
    public void dispose() {
        }

        
    /**
         * We will cache window object in order to be able to provide parent shell
         * for the message dialog.
         * 
         * 
    @see IWorkbenchWindowActionDelegate#init
         
    */
        
    public void init(IWorkbenchWindow window) {
            
    this.window = window;
        }
    }


    在run方法里面,直接使用VisiableClass.class.getClassLoader().loadClass("utilitylibrary.hide.InvisiableClass");來(lái)加載本不應(yīng)該被外部所見(jiàn)的Invisiable類(lèi)。因?yàn)樵贓clipse中,每個(gè)插件使用一個(gè)ClassLoader,所以用來(lái)加載VisiableClass類(lèi)的ClassLoader也同樣負(fù)責(zé)加載在同一個(gè)插件中的InvisiableClass類(lèi)。這樣InvisiableClass就在插件外部被加載成功了。類(lèi)加載成功后,剩下的事情就是順?biāo)浦哿耍瑒?chuàng)建個(gè)實(shí)例然后使用反射調(diào)用相應(yīng)的方法。
    程序運(yùn)行的時(shí)候,點(diǎn)擊toolbar上那個(gè)button,會(huì)彈出如下對(duì)話(huà)框:


    程序運(yùn)行也沒(méi)啥錯(cuò)誤。


    問(wèn)題分析:
    其實(shí)我覺(jué)得這個(gè)問(wèn)題是很難繞過(guò)去的。對(duì)于同一個(gè)插件,因?yàn)閮?nèi)部的類(lèi)需要互相引用和互相使用,所以必須使用同一個(gè)類(lèi)加載器來(lái)加載。所以,這個(gè)插件只要expose出來(lái)一個(gè)包,那么外部的插件就可以通過(guò)包中的任何一個(gè)類(lèi)來(lái)得到加載這個(gè)插件中的類(lèi)的類(lèi)加載器,然后就可以通過(guò)reflect愛(ài)做啥做啥了。

    換一個(gè)角度可能更好理解這個(gè)問(wèn)題為什么難以繞過(guò)去。假設(shè)VisiableClass需要用到InvisiableClass,雖然InvisiableClass沒(méi)有暴露出來(lái),但是在正常的使用VisiableClass的時(shí)候,需要先加載VisiableClass類(lèi),而加載VisiableClass的時(shí)候JVM就會(huì)隱式的加載InvisiableClass。這個(gè)過(guò)程和例子里現(xiàn)式的加載InvisiableClass沒(méi)啥本質(zhì)不同。也就是說(shuō),從ClassLoader的角度,很難判斷一個(gè)類(lèi)的加載是正常的代碼還是為了突破bundle的訪(fǎng)問(wèn)限制——它們都是在執(zhí)行run方法時(shí)發(fā)生的類(lèi)加載行為。

    或者是我有什么地方?jīng)]設(shè)置好?求解答。例子下載在此

    Feedback

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 12:30 by Jet Geng
    你好,拜讀你的文章我發(fā)現(xiàn)classloader的另外一種用法。謝謝。只是有一點(diǎn)不太明白。你為什么要繞過(guò)osgi的這種限制。

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 12:40 by Johnny.Liang
    從設(shè)計(jì)的角度來(lái)看,通過(guò)了解一些底層機(jī)制,繞過(guò)OSGi的類(lèi)加載策略來(lái)直接訪(fǎng)問(wèn)不對(duì)外公開(kāi)的類(lèi),不見(jiàn)得是一件好的事情,作為技術(shù)研究,了解這些底層機(jī)制有助于更熟悉一個(gè)框架,以更靈活的運(yùn)用它,但作為軟件開(kāi)發(fā),這些做法可能會(huì)導(dǎo)致很多隱患和風(fēng)險(xiǎn),個(gè)人認(rèn)為不值得推崇。

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 12:46 by 三人行,必有我?guī)熝?/a>
    一般隱藏起來(lái)的,都是internal的。里面的內(nèi)容可以隨意改變,你用Class.ForName來(lái)初始化一個(gè)類(lèi),一旦class name改變,你的代碼就報(bào)廢了。

    這么做有什么意義呢?

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 12:57 by 深夜兩點(diǎn)
    @Jet Geng
    @三人行,必有我?guī)熝?br>@Johnny.Liang

    謝謝大家的關(guān)注~。 我這也只是一種嘗試,并不是在實(shí)際中要這么使用,也無(wú)意去繞過(guò)OSGi的限制,只是為了說(shuō)明“可以繞過(guò)這種限制”。這么使用定然不好。所以我才覺(jué)得Equinox應(yīng)該把這條路封掉。現(xiàn)在的疑問(wèn)是Equinox沒(méi)有封掉這條路,期待的答案是Equinox能不能封掉這條路。

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 13:20 by 臨遠(yuǎn)
    其實(shí)沒(méi)有這么麻煩,大家可以在bundle里看到有l(wèi)oadClass和getResource的方法,直接調(diào)用,就可以通過(guò)類(lèi)名和資源名獲得對(duì)應(yīng)的資源。實(shí)際上內(nèi)部也是利用了classLoader。

    就像暴力反射一樣,雖然一般不會(huì)這樣用,但是也確實(shí)提供了讓你為所欲為的可能。

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 13:41 by 深夜兩點(diǎn)
    @臨遠(yuǎn)
    其實(shí)沒(méi)有這么麻煩,大家可以在bundle里看到有l(wèi)oadClass和getResource的方法,直接調(diào)用,就可以通過(guò)類(lèi)名和資源名獲得對(duì)應(yīng)的資源。實(shí)際上內(nèi)部也是利用了classLoader。


    請(qǐng)問(wèn)boudle里指的是什么?

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 13:52 by 表現(xiàn)表達(dá)
    2010-05-17 12:40 by Johnny.Liang
    從設(shè)計(jì)的角度來(lái)看,通過(guò)了解一些底層機(jī)制,繞過(guò)OSGi的類(lèi)加載策略來(lái)直接訪(fǎng)問(wèn)不對(duì)外公開(kāi)的類(lèi),不見(jiàn)得是一件好的事情,作為技術(shù)研究,了解這些底層機(jī)制有助于更熟悉一個(gè)框架,以更靈活的運(yùn)用它,但作為軟件開(kāi)發(fā),這些做法可能會(huì)導(dǎo)致很多隱患和風(fēng)險(xiǎn),個(gè)人認(rèn)為不值得推崇。

    同意,真的不見(jiàn)得是好事情。弊大于利

    # re: OSGi(Equinox)類(lèi)加載的問(wèn)題——使用ClassLoader突破bundle的訪(fǎng)問(wèn)限制  回復(fù)  更多評(píng)論   

    2010-05-17 18:03 by 臨遠(yuǎn)
    @深夜兩點(diǎn)
    你看一下org.osgi.framework.Bundle的api javadoc。里邊有你需要的方法。

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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: xvideos亚洲永久网址| 亚洲Aⅴ在线无码播放毛片一线天| 全亚洲最新黄色特级网站| 99久久这里只精品国产免费| 久久久久国产免费| 亚洲一区二区三区免费| 国产精品无码亚洲一区二区三区| 91丁香亚洲综合社区| 亚洲视频免费在线播放| 亚洲国产精品成人精品无码区| 亚洲欧洲日本在线| 亚洲电影日韩精品 | 国产亚洲人成网站在线观看不卡 | 无码精品人妻一区二区三区免费| 亚洲免费福利在线视频| 亚洲精品美女在线观看| 蜜芽亚洲av无码精品色午夜| 亚洲A∨无码一区二区三区| 国精无码欧精品亚洲一区| 亚洲人成网站色在线入口| 国产免费AV片无码永久免费| 永久在线毛片免费观看| 毛片大全免费观看| 成人无遮挡裸免费视频在线观看| 5555在线播放免费播放| 2021在线观看视频精品免费| 久久精品免费一区二区| 18禁免费无码无遮挡不卡网站| 免费专区丝袜脚调教视频| av无码国产在线看免费网站| 99久久这里只精品国产免费| 成人毛片免费在线观看| 成人免费毛片视频| 国产精品免费_区二区三区观看| 四虎影视大全免费入口| 四虎永久免费影院在线| 亚洲人成网站色在线入口| 亚洲色偷拍另类无码专区| 亚洲精品乱码久久久久久| 亚洲国产第一页www| 亚洲第一页中文字幕|