在运行时加载swt

时间:2014-10-31 17:24:10

标签: java swt jna

我正在使用DJ而我正在显示原生文件对话框。要显示这些,它需要一个特定于操作系统的库。该库有一些dll文件以及一些类。我想加载特定的库(Windows,Linux或Mac),具体取决于它运行的操作系统。我试过System.load()但是看起来这只加载了dll文件而不是带有它们的jar和其他类,因为我得到了这个错误。 System.load(System.getProperty("user.dir")+"/binaries/lib/swt-win64.jar");

Exception in thread "main" java.lang.UnsatisfiedLinkError: E:\Eclipse\workspace\PinewoodDerby\binaries\lib\swt-win64.jar: Can't load this .dll (machine code=0x4ba4) on a AMD 64-bit platform
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary1(Unknown Source)
    at java.lang.ClassLoader.loadLibrary0(Unknown Source)
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.load0(Unknown Source)
    at java.lang.System.load(Unknown Source)
    at derby.DerbyProgram.<init>(DerbyProgram.java:144)
    at derby.DerbyProgram.getInstance(DerbyProgram.java:119)
    at derby.DerbyProgram.main(DerbyProgram.java:110)

我从Eclipse的网站下载了jar,刚刚提取swt.jar并将其重命名为swt-win64.jar

如果我在类路径中包含swt-win64.jar,那么一切正常,但这意味着此构建仅适用于64位Windows而不是其他任何东西,我希望同一个jar可以在所有平台上运行。

更新:当我使用this帖子的代码加载swt jar时,我得到了这个例外:

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/SWT                                                       
        at chrriis.dj.nativeswing.swtimpl.core.SWTNativeInterface.initialize_(SWTNativeInterface.java:213)                           
        at chrriis.dj.nativeswing.swtimpl.NativeInterface.initialize(NativeInterface.java:71)                                        
        at chrriis.dj.nativeswing.swtimpl.core.SWTNativeInterface.open_(SWTNativeInterface.java:337)                                 
        at chrriis.dj.nativeswing.swtimpl.NativeInterface.open(NativeInterface.java:100)                                             
        at derby.DerbyProgram.<init>(DerbyProgram.java:161)                                                                          
        at derby.DerbyProgram.getInstance(DerbyProgram.java:130)                                                                     
        at derby.DerbyProgram.main(DerbyProgram.java:121)                                                                            
Caused by: java.lang.ClassNotFoundException: org.eclipse.swt.SWT                                                                     
        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)                                                                    
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)                                                                    
        at java.security.AccessController.doPrivileged(Native Method)                                                                
        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)                                                                
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)                                                                     
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)                                                             
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)                                                                     
        ... 7 more

我读了代码,addUrlMethod.invoke(classLoader, swtFileUrl)我们在这里使用的方法,addURL这似乎是我们正在添加一个URL而不是实际加载类。我使用-verbose参数启动了我的程序,它没有说明加载SWT的任何内容。这是我目前加载类的代码:

private void loadSWTJar() throws MalformedURLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        String osName = System.getProperty("os.name").toLowerCase();
        String osArch = System.getProperty("os.arch").toLowerCase();
        URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader();
        Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        addUrlMethod.setAccessible(true);
        String swtFileNameOsPart = osName.contains("win") ? "win" : osName.contains("mac") ? "maco" : osName.contains("linux") || osName.contains("nix") ? "linux" : ""; // throw new RuntimeException("Unknown OS name: "+osName)
        String swtFileNameArchPart = osArch.contains("64") ? "64" : "32";
        String swtFileName = "swt-" + swtFileNameOsPart + "-" + swtFileNameArchPart + ".jar";
        URL swtFileUrl = new URL("file:" + System.getProperty("user.dir") + "/lib/"+swtFileName);
        System.out.println(addUrlMethod.invoke(classLoader, swtFileUrl));
        System.out.println("Loaded SWT jar: " + swtFileUrl);
    }

更新2:我得到了这个代码,但它只适用于Windows机器。我在Windows上没有收到任何错误,但我收到同样的错误:

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/SWT

这是我的新代码:

private String getSwtJarName() throws OSNotDetectedException {
        String swtFileName = "swt-" + getOS() + ".jar"; //$NON-NLS-1$ //$NON-NLS-2$
        return swtFileName;
    }

    private String getOS() throws OSNotDetectedException {
        String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
        String os = osName.contains("win") ? "win" : osName.contains("mac") ? "mac" : osName.contains("linux") || osName.contains("nix") ? "linux" : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
        if ("".equals(os)) { //$NON-NLS-1$
            throw new OSNotDetectedException();
        }
        return os + "-" + getArch(); //$NON-NLS-1$
    }
class OSNotDetectedException extends Exception{
    private static final long   serialVersionUID    = 1L;
    OSNotDetectedException(){}
    OSNotDetectedException(Throwable e){
        super(e);
        }
}
    private String getArch() {
        String jvmArch = System.getProperty("os.arch").toLowerCase(); //$NON-NLS-1$
        String arch = jvmArch.contains("64") ? "64" : "32"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        return arch;
    }

    private void loadSWT() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, OSNotDetectedException {
        String prefix;
        if (debugMode) {
            prefix = "binaries/lib"; //$NON-NLS-1$
        } else {
            prefix = "lib"; //$NON-NLS-1$
        }
        String swtJarName = prefix + "/" + getSwtJarName(); //$NON-NLS-1$
        System.out.println("Loading SWT:"); //$NON-NLS-1$
        System.out.println(swtJarName);
        addFile(swtJarName);
        try {
            NativeInterface.open();
        }
        catch (NoClassDefFoundError e) {
            throw new OSNotDetectedException(e);
        }
    }

    private static void addFile(String s) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        File f = new File(s);
        addFile(f);
    }

    private static void addFile(File f) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        addURL(f.toURI().toURL());
    }

    private static void addURL(URL u) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Class<URLClassLoader> sysclass = URLClassLoader.class;
        @SuppressWarnings("rawtypes")
        Class[] parameters = new Class[] { URL.class };
        Method method = sysclass.getDeclaredMethod("addURL", parameters); //$NON-NLS-1$
        method.setAccessible(true);
        method.invoke(sysloader, new Object[] { u });
    }

0 个答案:

没有答案
相关问题