Java jar中的jar类加载问题

Java jar中的jar类加载问题,java,swt,Java,Swt,我遵循了在中描述的步骤。我创建了一个jar,它有一个swt_browser.jar,只包含使用swt库的类。然后我添加了其他特定于平台的swt罐。 我使用下面的代码加载swt_browser.jar和特定于平台的swt库jar。但不知何故,调用加载类SWTBrowser会抱怨: java.lang.ClassNotFoundException: org.eclipse.swt.widgets.Layout 你能看出我做错了什么吗 -----加载swt震击器的代码------- ClassLoa

我遵循了在中描述的步骤。我创建了一个jar,它有一个swt_browser.jar,只包含使用swt库的类。然后我添加了其他特定于平台的swt罐。 我使用下面的代码加载swt_browser.jar和特定于平台的swt库jar。但不知何故,调用加载类SWTBrowser会抱怨:

java.lang.ClassNotFoundException: org.eclipse.swt.widgets.Layout
你能看出我做错了什么吗

-----加载swt震击器的代码-------

ClassLoader父级=Main.class.getClassLoader();
setURLStreamHandlerFactory(新的RsrcURLStreamHandlerFactory(父级));
URL swtBrowserFileUrl=新URL(“rsrc:swt_browser.jar”);
URL swtFileUrl=新URL(“rsrc:+swtFileName”);
ClassLoader cl=新的URLClassLoader(新的URL[]{swtBrowserFileUrl,swtFileUrl},父级);
方法addUrlMethod=URLClassLoader.class.getDeclaredMethod(“addURL”,URL.class);
addUrlMethod.setAccessible(true);
调用(cl,swtBrowserFileUrl);
调用(cl,swtFileUrl);
Thread.currentThread().setContextClassLoader(cl);
试一试{
//检查我们现在可以加载SWT类了-检查通过了!
Class.forName(“org.eclipse.swt.widgets.Layout”,true,cl);
}捕获(ClassNotFoundException exx){
System.err.println(“启动失败:无法从jar加载SWT类:“+swtFileName”);
抛出新的运行时异常(exx);
}
//下面这行抛出异常:java.lang.ClassNotFoundException:org.eclipse.swt.widgets.Layout
Class c=Class.forName(“com.sun.star.google.gui.SWTBrowser”,true,cl);
Object obj=c.newInstance();
方法run=c.getMethod(“run”,url.getClass())//$非NLS-1$
调用(obj,新对象[]{url});

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

您正在设置以下类装入器:

  • 主类加载器
    • SWT类加载器
主类加载器的类路径上有以下所有内容:

  • 你的应用程序类
  • jar类加载器中的jar
SWT类加载器是在运行时构造的,在其类路径上具有以下内容:

  • 您的平台的SWT类
加载代码要求SWT类加载器加载一个SWT类,这是可行的。但是,您随后要求它加载一个应用程序类。它不知道你的应用程序类,所以它委托给它的父类,主类加载器。这将设法加载您的应用程序类,然后尝试引用SWT类。此引用由加载应用程序类的类加载器(主类加载器)处理。这不了解SWT类,并引发异常

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

  • 主类加载器
    • SWT类加载器
主类加载器的类路径上有以下所有内容:

  • 处理构建SWT类加载器的单个应用程序类
  • jar类加载器中的jar
SWT类加载器是在运行时构造的,在其类路径上具有以下内容:

  • 您的平台的SWT类
  • 你的应用程序类
这意味着当您加载应用程序类时,它将由SWT类加载器加载。这意味着,当您的应用程序引用SWT类时,将使用正确的类加载器

对于这个工作示例,您可以下载并检查以下jar:

编辑:生成intrace-ui.jar的ant构建文件可以在这里看到:


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

谢谢-我很快会尝试这样做-我感觉有点累,这就是为什么我对这个类加载复杂过程感到有点困惑…我感到困惑!我不知道该放什么进去-你能给出一些代码和更多的解释如何用一些代码片段来打包吗?我已经为intrace-ui.jar添加了一个ant构建脚本的链接。你能澄清你到底对什么感到困惑吗?你可能对我写的一个ANT任务感兴趣,我写这个任务是为了让它更简单:谢谢,我会尝试一下。这似乎是一个很好的工具,我也会检查源代码,谢谢
   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});