jar-in-jar类加载问题

时间:2011-08-04 19:13:38

标签: java swt

我按照Create cross platform Java SWT Application中描述的步骤进行操作。我使用swt库创建了一个包含swt_browser.jar的jar,其中只包含我的类。然后我添加了其他特定于platrom的swt罐子。 我使用下面的代码加载swt_browser.jar和特定于平台的swt库jar。但不知何故,加载类SWTBrowser的调用抱怨:

java.lang.ClassNotFoundException: org.eclipse.swt.widgets.Layout
你知道我做错了吗?

-----加载swt jars的代码-------

   ClassLoader parent = Main.class.getClassLoader();
            URL.setURLStreamHandlerFactory(new RsrcURLStreamHandlerFactory(parent));
            URL swtBrowserFileUrl = new URL("rsrc:swt_browser.jar");
            URL swtFileUrl = new URL("rsrc:" + swtFileName);

            ClassLoader cl = new URLClassLoader(new URL[]{swtBrowserFileUrl, swtFileUrl}, parent);
            Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            addUrlMethod.setAccessible(true);
            addUrlMethod.invoke(cl, swtBrowserFileUrl);
            addUrlMethod.invoke(cl, swtFileUrl);
            Thread.currentThread().setContextClassLoader(cl);
            try {
                // Check we can now load the SWT class -this check passes!
                Class.forName("org.eclipse.swt.widgets.Layout", true, cl);
            } catch (ClassNotFoundException exx) {
                System.err.println("Launch failed: Failed to load SWT class from jar: " + swtFileName);
                throw new RuntimeException(exx);
            }

           //this line below throws exception : java.lang.ClassNotFoundException:     org.eclipse.swt.widgets.Layout 

            Class<?> c = Class.forName("com.sun.star.google.gui.SWTBrowser", true, cl);

            Object obj = c.newInstance();
            Method run = c.getMethod("run", url.getClass()); //$NON-NLS-1$
            run.invoke(obj, new Object[]{url});

1 个答案:

答案 0 :(得分:2)

您的jar具有以下文件结构:

file structure

您正在设置以下ClassLoaders:

  • 主要的类加载器
    • SWT classloader

Main类加载器在其类路径中具有以下所有内容:

  • 您的应用类
  • jar-in-jar类加载器

SWT类加载器是在运行时构造的,其类路径上有以下内容:

  • 适合您平台的SWT课程

您的加载代码要求SWT类加载器加载SWT类并且可以正常工作。但是,您要求它加载应用程序类。它不知道您的应用程序类,因此它委托给它的父类Main类加载器。这设法加载您的应用程序类,然后尝试引用SWT类。此引用由加载应用程序类的类加载器(Main类加载器)处理。这不知道SWT类并引发异常。

您需要以不同方式打包您的应用程序。您需要具有以下类加载器。

  • 主要类加载器
    • SWT classloader

Main类加载器在其类路径中具有以下所有内容:

  • 处理构建SWT类加载器的单个app类
  • jar-in-jar类加载器

SWT类加载器是在运行时构造的,其类路径上有以下内容:

  • 适合您平台的SWT课程
  • 您的应用类

这意味着当您加载应用类时,它将由SWT类加载器加载。这意味着当您的应用引用SWT类时,会使用正确的类加载器。

有关此工作示例,您可以下载并检查以下jar:https://github.com/downloads/mchr3k/org.intrace/intrace-ui.jar

编辑:生成intrace-ui.jar的ant构建文件可以在这里看到:https://github.com/mchr3k/org.intrace/blob/master/org.intrace/build.xml

特别是,“jar”目标处理包装。