2011-04-05 68 views
2

我拥有引用第三方JAR的插件A.我试图动态地从这个JAR从加载类的插件B.Eclipse RCP:另一个插件引用的库中定义的动态加载类

我有这样的事情从一类插件B:

myClass = getClass().getClassLoader().loadClass("com.foo.Bar"); 

这工作得很好,如果我想加载在插件A中定义的类,但是当尝试加载插件A中引用的JAR中的类时,我得到ClassNotFoundException。

JAR位于类路径上,并且在我不要试图通过这个类加载器来动态加载。

任何想法?

在此先感谢。

回答

1

你的设置错了。理想情况下,应该将第三方jar创建为插件(File-> New->来自现有jar的插件),从而暴露jar中的类。然后设置A & B取决于它。

+0

您可能是对的,但这在我们的应用程序中不是可行的选项。对于我的问题,我决定不使用反射动态实例化类,而是使用代码生成代替。 – lucks 2011-04-06 21:31:44

0

在插件A中,确保已经添加了jar来捆绑清单类路径,然后确保导出包含在该jar中的包。

打开META-INF/MANIFEST -MF文件。你应该看到一个多页面编辑器。转到运行时选项卡并查看Classpath部分。然后请参阅导出的软件包部分。然后进入Build页面,并确保你的jar在Binary Build部分被选中。

+0

是的,它都在那里。该设置在正常情况下工作......我在运行时动态加载类时遇到了问题,Bundle类加载器 – lucks 2011-04-06 21:29:13

+0

@lucks:您和其他人: - /曾经尝试直接使用第三方JDBC驱动程序,而无需通过Eclipse框架?当我想到我必须采用的各种技巧来做到这一点时,我仍然不寒而栗... – thkala 2011-04-06 23:21:54

+0

如果bundle classloader不起作用,那么您没有得到正确的设置。仔细检查我引用的所有部分。 – 2011-04-07 00:53:31

1

我认为您的解决方案的关键是以下我在另一篇文章中阅读,每个Eclipse插件保持它自己的类加载器

因此,我可以告诉你我的Eclipse(3.7)插件为动态加载做什么,我不确定是否可以“适合”到您的需求。基本上,我的插件做加密/解密。作为一项新的增强功能,我允许用户通过FileDialog加载一个或多个Jar文件,其中每个jar文件都使用URLClassLoader加载。创建我的“自定义”类加载器使用以下行:

this.FQCNLoader = new URLClassLoader (getFQCNUrls(), this.getClass().getClassLoader()); 

的关键是在作为第二个参数的Eclipse插件的ClassLoader通过......这意味着你的“自定义”类加载器具有Eclipse插件的CLASSPATH加上你添加的任何URL(getter getFQCNUrls()返回一个URL [])。

另一个关键问题是,我在一个视图中维护“自定义”类加载器,我知道该视图持续了Eclipse插件的整个生命周期。该视图位于需要引用动态* .jar类的所有代码之上。

所以,你需要沿着同样的路线做点什么。你的“自定义”类加载器需要在pluginA和pluginB之上的类中生存。另外,我觉得,因为每个插件有它自己的类加载器,你实际上将需要建立一个“自定义”类加载器,做类似以下内容:

1.) Let pluginB load dynamic *.jar/classes. Convert into URL[]. 
2.) Create "custom" loader, pass in pluginB URL[] PLUS pluginA classloader. 

这里是在addURL()方法我查看构建“自定义”类加载器的类...它有点难看,因为我写它很匆忙,并且每次用户加载*时都会重新生成“自定义”类加载器。罐子,但它的工作在Eclipse和无OSGi的:

private int    URLCount = 0; 
private URL[]   FQCNUrls = new URL[10]; 
private ClassLoader  FQCNLoader = new URLClassLoader (this.FQCNUrls); 

...Lots of code... 

public void addURL (URL theURL) throws IOException { 
    //CPTest lclsTest = new CPTest(); 
    if (getURLCount() == 0) { 
     getFQCNUrls()[getURLCount()] = theURL; 
     setURLCount (1); 
    } 
    else { 
     boolean lisThere = false; 
     for (int i = 0; i < getURLCount(); i++) { 
      if (getFQCNUrls()[i].toString().equalsIgnoreCase(theURL.toString())) { 
       lisThere = true; 
      } 
     } 
     if (lisThere) { 
      System.out.println ("File URL [" + theURL.toString() + "] already on the CLASSPATH!"); 
     } 
     else { 
      getFQCNUrls()[getURLCount()] = theURL; 
      setURLCount (getURLCount()+1); 
     } 

    } 

    // CLEAR : Null out the classloader... 
    this.FQCNLoader = null; 
    // BUILD/RE-BUILD : the classloader... 
    this.FQCNLoader = new URLClassLoader (getFQCNUrls(), this.getClass().getClassLoader()); 

    //try { 
    // System.out.println ("---------------------------------------------------------------------------"); 
    // System.out.println ("Current Working Directory.............[" + System.getProperty ("user.dir") + "]"); 
    // System.out.println ("---------------------------------------------------------------------------"); 
    // System.out.println ("this.classes []! "); 
    // lclsTest.dumpClasses (this.getClass().getClassLoader()); 
    // System.out.println ("---------------------------------------------------------------------------"); 
    // 
    // System.out.println ("---------------------------------------------------------------------------"); 
    // System.out.println ("File URL [" + theURL.toString() + "] added! "); 
    // lclsTest.dumpClasses (this.FQCNLoader); 
    // System.out.println ("---------------------------------------------------------------------------"); 

    // System.out.println ("---------------------------------------------------------------------------"); 
    // System.out.println ("ClassLoader.getSystemClassLoader() "); 
    // lclsTest.dumpClasses (ClassLoader.getSystemClassLoader()); 
    // System.out.println ("---------------------------------------------------------------------------"); 

    // Class cls = this.FQCNLoader.loadClass ("com.lmig.RRFECF.pso.security.nonproduction.CM_RRFECF_development_securitykey"); 
    // Class cls = Class.forName(theFQCN, false, theClsLoader); 
    // theObjectKey = (Object) theClsLoader.loadClass(theFQCN); 


    //} 
    //catch (Exception e) { 
    //// TODO Auto-generated catch block 
    // e.printStackTrace(); 
    //} 

    Class sysclass = URLClassLoader.class; 
    try { 
     Method method = sysclass.getDeclaredMethod("addURL", parameters); 
     method.setAccessible(true); 
     method.invoke(getFQCNLoader(), new Object[] { 
      theURL 
     }); 
    } 
    catch (Throwable t) { 
     t.printStackTrace(); 
     throw new IOException(
      "Error, could not add URL to system classloader"); 
    } 
} 

BTW,我鼓励你抢CPTest类在第一行注释掉,它是无价的我如何洞察不同的类加载器和什么在他们身上。我在代码中留下了Sysout行,这样您就可以看到如何在类加载器中转储所有类...

相关问题