【问题标题】:Load a class to Java classpath dynamically using Eclipse and OSGi使用 Eclipse 和 OSGi 将类动态加载到 Java 类路径
【发布时间】:2012-10-03 18:13:16
【问题描述】:

结合来自该站点上的许多帖子和许多其他帖子的信息,我得到了以下代码来动态添加(在运行时)一个包含类的目录到类路径并在该目录中加载一个类。

我正在使用 OSGi 包并从 Eclipse 运行“Eclipse 应用程序”(一种运行配置)。

这是我正在使用的代码:

CASE 1:(这两种情况是不同的事情,我试图做同样的事情。)

File file = new File("/Users/alek/fastFIX/myJPass/"); 
URL url = file.toURI().toURL(); 
URL[] urls = new URL[]{url}; 
ClassLoader cl = new URLClassLoader(urls); 
Class  cls = cl.loadClass("GuiLauncher");    //the file GuiLauncher.class is in the /Users/alek/fastFIX/myJPass/ directory
Class[] argTypes = new Class[] { String[].class };
Method main = cls.getDeclaredMethod("main", argTypes); //trying to run the main class
main.invoke(null, (Object) args);

我没有收到任何错误,也没有任何反应。 我还尝试了以下方法,因为我实际上需要加载的类与其他(已经加载的)类进行交互。

案例 2:

ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {  new File("/Users/alek/fastFIX/myJPass/").toURL() }, currentThreadClassLoader);
Thread.currentThread().setContextClassLoader(urlClassLoader);

然后我像这样加载:

 Class<?> c = Class.forName("GuiLauncher");

或者像这样:

Class<?> c = Thread.currentThread().getContextClassLoader().loadClass("GuiLauncher");

并尝试像这样调用主函数:

Class[] argTypes = new Class[] { String[].class };
Method main = cls.getDeclaredMethod("main", argTypes); //trying to run the main class
main.invoke(null, (Object) args);

这里也没有任何反应。

对可能发生的事情有任何线索吗?我已经阅读了这里的所有相关帖子以及其他许多地方都没有运气。

【问题讨论】:

  • 为了记录,在动态加载的对象上调用方法更简单的方法是让它们实现已知的接口。 MyPlugin m = cls.newInstance(); m.runPlugin(magic, hax); 其中 MyPlugin 是您的运行时类实现的接口。
  • 你写了“Class.forName("GuiLauncher");”。您的课程在默认包中吗?可能你类的文件夹和包声明不匹配?
  • 如果您在执行类加载器之前引用了GuiLauncher 类,它会被默认类加载器从类路径加载。因此,在这种情况下,您的 loadClass 不会产生任何影响,因为它会检查父类加载器以查看它是否已加载并发现它已加载。
  • @Wug:我无法访问我正在加载的类的代码。
  • @basiljames,我以前没有这样做过。在任何情况下,如果类已经加载,则应该运行 main 方法。如果我错了,请纠正我。

标签: java eclipse dynamic osgi classpath


【解决方案1】:

在 OSGI 框架中,需要添加 OSGI 类加载器作为父类,如下所示: ... ClassLoader cl = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader()); ...

【讨论】:

    【解决方案2】:

    在情况 1 中,我怀疑 GuiLauncher 类已经在类路径中,因此可能会被默认类加载器加载。尝试在设置动态类加载器之前执行Class.forName(),以确认没有可用的类。如果您在 Eclipse 中,则需要注意该类不包含在 Eclipse 类路径中,这通常会发生。您可能需要编译一次,然后将 .java.class 文件移动到其他位置以将它们隐藏在 Eclipse 中!

    情况2:

    Class.forName("GuiLauncher");
    

    不会像你期望的那样工作,因为这将使用系统类加载器。这应该失败,因此我在上面怀疑。您需要使用指定动态类加载器的other version of this method

    Class.forName("GuiLauncher", true, urlClassLoader)
    

    以下代码对我有用。

    import java.net.*;
    import java.lang.reflect.*;
    import java.io.File;
    
    public class Main{
    
    public static void main(String[] args)
    {
        try{
          Class  cls = Class.forName("Plugin");
        }
        catch(Exception e){
          System.out.println("Nothing there!");
        }
    
        try{
          File file = new File("plugin"); 
          ClassLoader cl = new URLClassLoader(new URL[]{file.toURI().toURL()}); 
          Class  cls = Class.forName("Plugin", true, cl);
          Method main = cls.getDeclaredMethod("main", new Class[] { String[].class });
          main.invoke(null, (Object) args);
        }
        catch(Exception e){
          e.printStackTrace();
        }
      }
    }
    

    Plugin 类编译在plugin 子文件夹中,因此它不在用于运行Main 的类路径中,如第一个Class.forName() 所示。

    public class Plugin{
      public static void main(String[] args)
      {
        System.out.println("Plugin was invoked!");
      }
    }
    

    并打印出来:

    Nothing there! 
    Plugin was invoked!
    

    【讨论】:

    • 感谢您的回复。它是一样的,没有任何反应。你说的这个和案例1有什么区别?
    • 主要方法应该打开一个awt窗口。我已经尝试将类放在类路径中(手动)并且工作正常,但在我的真实场景中我无法做到这一点。当我做 class.forname(class) 时,我得到 classnotfoundException。我试过你说的 class.forname 的版本也没有运气
    • 如果我打印 Class.forName("GuiLauncher", true, urlClassLoader) 我得到“class GuiLauncher”的结果。我认为这意味着该类已成功加载。加载主要方法时可能会出现问题? args 数组是一个向主函数发送参数的数组,在本例中为空。
    • 嗨@DNA,再次感谢您。这让我遇到了同样的问题,没有错误消息,但什么也没发生。可能很重要的一点是,我正在运行 OSGi 包。我仍然不知道这会如何影响或是否会影响,但会继续阅读。再次感谢。
    • 好的,听起来 OSGi 就是问题所在——我相信 OSGi 会为每个包分配一个类加载器。如果您使用 OSGI,我什至不确定为什么要自己创建类加载器 - 请参阅 blog post。您可以尝试在调试器中运行代码,看看会出现什么...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2015-03-06
    • 2011-11-05
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多