在执行过程中有加载资源问题 [英] Problems with loading resources during execution

查看:210
本文介绍了在执行过程中有加载资源问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里的根本问题的背景,我与一组上使用 SWT 库项目合作,我试图打包用于部署的软件。事实证明 SWT 很平台/体系结构相关。我希望能够打包所有六个 JAR S(在Linux,Mac,赢得和32/64位)到相同的软件包,并使用相应的库视系统。我意识到这是一个严峻的挑战但是,切换到秋千(或其他任何东西)是不是一个真正的选择权了。

Here's the background of the underlying problem, I am collaborating with a group on a project which uses Swt libraries and I am trying to package the software for deployment. As it turns out SWT is very platform/architecture dependent. I would like to be able to package all six jars (linux, mac, win and 32/64-bit) into the same package and use the appropriate library depending on the system. I realize that it is a tough challenge however, switching to Swing (or anything else) isn't really an option right now.

我已经找到了一些相关的线程(<一href=\"http://stackoverflow.com/questions/2037220/how-can-i-creating-executable-jar-with-swt-that-runs-on-all-platforms\">@Aaron Digulla的线程和<一个href=\"http://stackoverflow.com/questions/2706222/create-cross-platform-java-swt-application/3204032#3204032\">@mchr's这为我提供了关于在手边的问题有价值的见解线程)。我曾试图落实@Alexey罗曼诺夫<一个提出的解决方案href=\"http://stackoverflow.com/questions/2706222/create-cross-platform-java-swt-application/3204032#3204032\">here.但有一点不同,因为他提出了 loadSwtJar()方法也不是一成不变的,我实例化对象,而紧随其后的是,运行方法之前什么都做是为了对象。

I have found a number of relevant threads (@Aaron Digulla's thread and @mchr's thread) which provided me valuable insights regarding the problem at hand. I have tried to implement the solution proposed by @Alexey Romanov here. With one difference, as the loadSwtJar() method he proposes is not static, I instantiate the object, and immediately following that, run the method before anything else is done to the object.

它显示为装载过程不能正常工作。我对这种说法的理由是如下:

It appears as the loading procedure doesn't work properly. My reasoning for this statement is as follows:


  • 如果所有的 SWT 罐子是从可执行的JAR文件的类路径中删除,那么异常线程mainjava.lang.NoClassDefFoundError的:组织/日蚀/ SWT /事件/ MouseListener的被抛出它的原因是:抛出java.lang.ClassNotFoundException:org.eclipse.swt.events.MouseListener

  • If all Swt jars are removed from the classpath of the executable jar file, then Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/events/MouseListener is thrown which is caused by: java.lang.ClassNotFoundException: org.eclipse.swt.events.MouseListener

对我来说这意味着库没有在classpath中发现,是我错了?

to me this means that the libraries are not found on classpath, am I mistaken?


  • 如果 SWT 罐子留在类路径中,然后在执行过程中的第一个jar文件系统使用。这意味着如果GTK的Linux的x86_64的恰好是jar的列表中的第一个SWT罐子则系统会尝试使用,如果不考虑系统是Win32或Mac OSX。

  • If swt jars are left on the classpath then the first jar file is used by the system during execution. Meaning if gtk-linux-x86_64 happens to be the first swt jar on the list of jars then the system tries to use that, regardless if the system is win32 or Mac OSX.

我尝试添加一些输出,看是否 loadSwtJar()方法是选择正确的罐子,输出似乎是正确的我已经尝试了所有平台在合适的包被选中(和文件就在可运行罐子存在)。但尽管如此,发生未加载正确的库,因此执行错误:
异常线程mainjava.lang.reflect.InvocationTargetException 为前致:java.lang.UnsatisfiedLinkError中:产生的原因无法加载32位在64位JVM位SWT库
(注意,这是我得到我的Linux机器上的错误,如果我改变了的build.xml 文件的64位和32位SWT库出现的顺序)

I have tried to add some output to see if the loadSwtJar() method is choosing the right jar, and the output seems right on all platforms I have tried, as in the right package is selected (and the files do exist in the runnable jar). But nevertheless the right library is not loaded hence execution errors occur: Exception in thread "main" java.lang.reflect.InvocationTargetException caused by for ex: Caused by: java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bit JVM (Note that this is the error I get on my Linux machine if I change the order of appearance of 64-bit and 32 bit swt libraries on the build.xml file)

那么,什么似乎是这里的问题?我是否错过了一些细节,或者是它根本不可能检查系统属性,并相应地加载相应的库?

So, what seems to be the problem here? Am I missing out on some detail, or is it simply not possible to check system properties and load an appropriate library accordingly?

最后下面是我的构建文件的摘录,想通这可能有助于找到问题的根源。

Finally below is an excerpt of my build file, figured it might help finding the source of the problem.

由于提前,

编辑:与同事长时间调试会话后,正如我所提到的问题得到解决(除了一个恼人的错误就在MacOS线程管理<一href=\"http://stackoverflow.com/questions/2746539/problems-with-swt-on-mac/3049608#3049608\">here).它参与了ANT构建调整以及主类是书面的方式(主类,因为它的出现,是扩大和放大器;实现从SWT库,意味着code不会编译引用在所有的,包裹着另一个类的主类,并加载从那里SWT罐子这似乎足以解决这个问题)

After a long debug session with a colleague, the problem is resolved (except an annoying bug regarding Thread management on MacOS as I mentioned here). It involved tweaking with the ANT build as well as the way the main class was written. (The main class, as it turns out, was extending & implementing references from the SWT library which meant that the code wouldn't compile at all, wrapped the main class with another class and loaded the SWT jars from there which seemed to be enough to tackle the problem)

感谢和问候大家谁作出了贡献,特别是@Aaron。真的AP preciated!

Thanks and regards to everyone who contributed, especially @Aaron. Really appreciated!

推荐答案

下面是我的主类的最新版本的副本。让我知道这是否为你的作品。我测试了它在Linux(32位/ 64位)和Windows(32位)。

Here is a copy of the latest version of my Main class. Let me know if that works for you. I tested it on Linux (32/64bit) and Windows (32bit).

package de.pdark.epen.editor;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;
import de.pdark.epen.exceptions.WikiException;

public class Main
{
    public final static String VERSION = "V0.9 (13.05.2010)"; //$NON-NLS-1$
    private final static Logger log = LoggerFactory.getLogger (Main.class);

    private static final String ORG_ECLIPSE_SWT_WIDGETS_SHELL = "org.eclipse.swt.widgets.Shell"; //$NON-NLS-1$

    /**
    * @param args
    */
    @SuppressWarnings({"nls", "PMD.SystemPrintln"})
    public static void main (String[] args)
    {
        String msg = "Starting ePen "+VERSION;
        System.out.println (msg);
        log.info (msg);

        LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory ();
        StatusPrinter.print (lc);

        int rc = 1;
        try
        {
            Main main = new Main ();
            main.run (args);
            rc = 0;
        }
        catch (Throwable t) //NOPMD
        {
            ExceptionUtils.printRootCauseStackTrace (t);
        }
        finally
        {
            System.out.println ("Done.");
            log.info ("Exit {}", rc);
            System.exit (rc); //NOPMD
        }
    }

    @SuppressWarnings({"nls", "PMD.SystemPrintln", "PMD.SignatureDeclareThrowsException"})
    private void run (String[] args) throws Exception
    {
        if (!SystemUtils.isJavaVersionAtLeast (150))
        {
            System.out.println ("Version="+SystemUtils.JAVA_VERSION_INT);
            throw new WikiException ("Need at least Java 5 but this Java is only "+SystemUtils.JAVA_VERSION);
        }

        loadSwtJar ();

        URLClassLoader cl = (URLClassLoader) getClass().getClassLoader(); //NOPMD
        Class<?> c = cl.loadClass ("de.pdark.epen.editor.EPenEditor");
        Class<?> shellClass = cl.loadClass (ORG_ECLIPSE_SWT_WIDGETS_SHELL);

        Constructor<?> ctor = c.getConstructor (shellClass);
        Object obj = ctor.newInstance (new Object[] { null });
        Method run = c.getMethod ("run", args.getClass ()); //$NON-NLS-1$
        run.invoke (obj, new Object[] { args });
    }

    @SuppressWarnings({"nls", "PMD"})
    private void loadSwtJar ()
    {
        try {
            Class.forName (ORG_ECLIPSE_SWT_WIDGETS_SHELL);
            // Already on classpath
            return;
        } catch (ClassNotFoundException e) {
            // Add the JAR
        }

        String osName = SystemUtils.OS_NAME.toLowerCase ();
        String osArch = SystemUtils.OS_ARCH.toLowerCase ();

        String swtFileNameOsPart = 
            osName.contains("win") ? "win32" :
            osName.contains("mac") ? "macosx" :
            osName.contains("linux") || osName.contains("nix") ? "linux" :
            null;
        String swtFileNameUiPart = 
            osName.contains("win") ? "win32" :
            osName.contains("mac") ? "cocoa" :
            osName.contains("linux") || osName.contains("nix") ? "gtk" :
            null;

        if (null == swtFileNameOsPart)
        {
            throw new RuntimeException ("Can't determine name of SWT Jar from os.name=[" + osName + "] and os.arch=["
                    + osArch + "]");
        }

        String swtFileNameArchPart = osArch.contains ("64") ? ".x86_64" : ".x86";
        if(".x86".equals(swtFileNameArchPart) && "macosx".equals(swtFileNameOsPart)) {
            swtFileNameArchPart = "";
        }

        String swtFileName = "org.eclipse.swt." + swtFileNameUiPart + "." + swtFileNameOsPart + swtFileNameArchPart + "-3.6.0.jar";
        File file = new File ("swt", swtFileName);
        if (!file.exists ())
        {
            throw new RuntimeException ("Can't locate SWT Jar " + file.getAbsolutePath ());
        }
        try
        {
            URLClassLoader classLoader = (URLClassLoader) getClass ().getClassLoader ();
            Method addUrlMethod = URLClassLoader.class.getDeclaredMethod ("addURL", URL.class);
            addUrlMethod.setAccessible (true);

            URL swtFileUrl = file.toURI ().toURL ();
            log.info ("Adding {} to the classpath", swtFileUrl);
            addUrlMethod.invoke (classLoader, swtFileUrl);
        }
        catch (Exception e)
        {
            throw new RuntimeException ("Unable to add the swt jar to the class path: " + file.getAbsoluteFile (), e);
        }
    }
}

这篇关于在执行过程中有加载资源问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆