2010-01-10 10 views
11

SWT viene con un JAR base y un JAR específico por plataforma (Windows, Linux/32 bits, Linux/64 bits, Mac, AIX, ...). ¿Cómo puedo crear un JAR ejecutable que seleccionará el JAR de la plataforma correcta en tiempo de ejecución?¿Cómo puedo crear JAR ejecutable con SWT que se ejecuta en todas las plataformas?

[EDITAR] Estaba pensando en suministrar todos los archivos JAR de la plataforma en un subdirectorio y en main() modificaría el cargador de clases. ¿Alguien ha intentado esto?

+1

¿Por qué no distribuir varios ejecutables para cada plataforma (al estilo de Eclipse)? –

+0

Porque SWT solo ocupa una pequeña parte de la aplicación: todo el conjunto actualmente es de 30 MB. Así que puedo pedirle a la gente que descargue 32MB por cada plataforma o descargar un archivo de 40MB (para seis plataformas) que se ejecuta en todas partes. –

+0

En el caso de eclipse, tenemos más de 10 descargas, cada una> 100 MB y la única diferencia entre ellas es el contenedor SWT. O deseo una sola descarga o una gran descarga principal y una pequeña descarga por plataforma que se descarga automáticamente cuando ejecuto la aplicación por primera vez. –

Respuesta

1

IIUC, usted todavía tiene el problema de especificar la biblioteca JNI específico de la plataforma. Es posible que pueda aprovechar Java Web Start para esto, pero no lo he intentado. Alternativamente, algunos proyectos crean instaladores personalizados para plataformas compatibles. Por ejemplo, Deploying SWT Applications on Mac OS X describe cómo construir un paquete de aplicaciones SWT Mac. El enfoque se usa en este example. También he visto esto JarBundler Ant Task usado.

Adición: el artículo Deploying an SWT application on Java Webstart incluye algunas referencias útiles.

+0

Ahora he intentado con un URLClassLoader pero hay dos problemas: si el JAR no está en ClassPath en el MANIFEST.MF, la carga de las DLL fallará. Esto significa que tengo que agregar * todos * JARs SWT al classpath al mismo tiempo. Esto lleva al problema de que las DLL de 32 bits y 64 bits son visibles y la carga de cualquiera fallará. * suspiro * Al final, agregaré todos los JAR a la ruta de clase pero copiaré solo un solo JAR SWT en el directorio lib. De esta forma, solo se cargará un solo JAR. –

+0

Puedo ver el atractivo técnico, pero también puedo ver las dificultades de mantenimiento. Enfrentando un problema similar, agregué un enlace a un artículo SO que menciona a JWS. – trashgod

0

Será más fácil utilizar diferentes scripts de shell para diferentes plataformas y especificar el archivo jar específico de la plataforma en el script.

+0

Podría escribir scripts de shell pero realmente esperaba evitar eso. Mi solución actual (agregar todos los JAR SWT a classpath pero copiar solo la correcta en el directorio lib) funciona. Ahora, solo necesito escribir un instalador :) –

5

Para mi trabajo actual necesitaba suministrar un archivo ejecutable que pudiera cargar frascos dentro de sí mismo y ejecutar un segundo main(). Básicamente una rutina de arranque() y una aplicación principal().

Paso 1. En la "clase principal" manifiesta que ponga su clase de arranque

Paso 2. Cuando la clase de arranque que se ejecuta unjar es su propio frasco y todos los frascos en su interior a un directorio temporal. Use algo como la línea de abajo para obtener su propio frasco.

Main.class.getProtectionDomain().getCodeSource().getLocation().toURI() 

Paso 3. Su clase de arranque detecta el sistema operativo a través de la propiedad "os.name" y carga los frascos apropiados desde el directorio temporal con esta

private static void loadJarIntoClassloader(URL u) throws Exception 
{ 
    URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 

    Class<URLClassLoader> sysclass = URLClassLoader.class; 
    Method method = sysclass.getDeclaredMethod("addURL", URL.class); 
    method.setAccessible(true); 
    method.invoke(sysLoader, new Object[]{u}); 
} 

Paso 4. Ahora usted debería ser capaz ejecutar su aplicación llamando a la aplicación main().

NOTA: Este pequeño hack depende de su JVM utilizando URLClassLoader como su SystemClassLoader, lo que es cierto para las JVM de Sun, no es seguro en otras.

De esta manera puede entregar un solo frasco solamente, y se descomprimirá y se ejecutará con los frascos correctos.

+1

Si quiere ser independiente del tipo del cargador de clases, simplemente use el método de fábrica 'newInstance (urls, parentClassLoader)' para envolverlo y luego instale el nuevo cargador de clases con 'Thread .currentThread(). setContextClassLoader() '. –

+0

+1 Interesante idea para crear el classpath en un main y luego llamar a otro. –

+0

@Aaron gracias por la sugerencia, tendré que intentarlo – karoberts

Cuestiones relacionadas