我按照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});
答案 0 :(得分:2)
您的jar具有以下文件结构:
您正在设置以下ClassLoaders:
Main类加载器在其类路径中具有以下所有内容:
SWT类加载器是在运行时构造的,其类路径上有以下内容:
您的加载代码要求SWT类加载器加载SWT类并且可以正常工作。但是,您要求它加载应用程序类。它不知道您的应用程序类,因此它委托给它的父类Main类加载器。这设法加载您的应用程序类,然后尝试引用SWT类。此引用由加载应用程序类的类加载器(Main类加载器)处理。这不知道SWT类并引发异常。
您需要以不同方式打包您的应用程序。您需要具有以下类加载器。
Main类加载器在其类路径中具有以下所有内容:
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”目标处理包装。