2011-02-18 14 views
13

¿Hay alguna razón para favorecer el uso (posiblemente muy largo) de la variable CLASSPATH para establecer qué jar deben estar en la aplicación classpath durign ejecutar luego para usar la propiedad java 1.5+ -Djava.ext.dirs que especifica el directorio completo (directorios) de jarras para buscar?CLASSPATH vs java.ext.dirs

Para que sea un ejemplo de la vida real, tengo una aplicación java independiente con la carpeta lib que contiene todos los archivos jar dependientes. Sofar el script de inicio está configurando todos los (quizás 20) jar a la variable CLASSPATH uno por uno. Desde ahora, mi archivo de aplicaciones es generado por Maven. No puedo ver de antemano cuáles serán los nombres de los jar (por ejemplo, cambio la versión de un JAR). Por supuesto, puedo pasar por el directorio lib en el script de inicio y agregar todos los archivos jar encontrados a la variable CLASSPATH nuevamente. O probablemente haga que maven genere este script para mí. Pero aquí vienen las suspensiones:

1) ¿Sería correcto y apropiado reemplazar todo esto simplemente configurando la propiedad java.ext.dirs para que contenga lo que contiene + mi lib dir extra en mi script? ¿Alguna advertencia escondida allí?

Gracias por las respuestas :)

Respuesta

23

java.ext.dirs tiene un uso muy específico: se utiliza para especificar dónde las clases de cargas extension mechanism. Se usa para agregar funcionalidad al JRE o a otras bibliotecas (como JAI). No es un mecanismo de carga de clases de propósito general.

Use el wildcard character * en su lugar. Fue introducido en Java 6, por lo que muchas personas aún no saben que es posible.

+1

Gracias por eso. Otra cosa de la que estaba hablando era si usaba (probablemente erróneamente) java.ext.dirs o especificaba classpath usando comodines. ¿Es diferente de nombrarlos uno por uno? Tal vez el orden puede importar a veces? –

+0

Un punto en contra de importar 'cada Jar en un directorio' es que si el directorio contiene 1500 Jars y la aplicación. solo requiere 2 de ellos, el JRE podría tener que buscar muchos Frascos antes de descubrir una clase o recurso. No veo el gran beneficio de usar comodines en las rutas de clases (incluso si una aplicación usa 50 Jars). –

+1

Gracias por su opinión. Pero como describí anteriormente, mi directorio lib contiene solo los frascos realmente necesarios, ni más ni menos. No quiero codificarlos en el script porque las versiones del jar pueden haber cambiado. ¿Sugeriría entonces que deje que maven genere el guión para mí con los frascos codificados en el guión? –

3

Un gran problema para poner cosas en el directorio lib.ext es que las diferentes aplicaciones pueden requerir diferentes versiones de bibliotecas, y esas pueden entrar en conflicto entre sí.

Piense en el antiguo infierno DLL de Windows 3 días (si los recuerda) cuando se desarrolló una situación similar cuando muchos sino la mayoría de los desarrolladores de software colocaban bibliotecas compartidas en el directorio Windows/System porque se recogían automáticamente de allí en lugar de incluirlos con sus aplicaciones y cargarlos explícitamente.

Lo que quiere es tener un classpath separado para cada aplicación (¡no classpath de nivel de sistema!), Establecer en su script de inicio y señalar únicamente los archivos jar y directorios de clases aplicables para esa aplicación específica. De esta forma, varias aplicaciones con necesidades conflictivas de biblioteca pueden lanzarse una al lado de la otra sin interferir con la funcionalidad de cada una.

Lo mismo es aún más cierto si usted es un desarrollador, donde no quiere que ninguna biblioteca externa interfiera con su aplicación mientras la prueba. Y hay otra cosa: si está desarrollando y utilizando el truco lib/ext (o un classpath de nivel de sistema), ¿cómo puede estar seguro de que la aplicación que va a enviar se envía con las bibliotecas correctas? Si olvida incluir en su instalador o paquete de instalación, nunca lo notará porque está en su máquina en una ubicación compartida. Pero el cliente, que no tiene esa biblioteca, recibiría errores en el tiempo de ejecución y pronto estaría en el teléfono solicitando asistencia (y posiblemente un reembolso, y emitiendo malas críticas en la prensa por el envío de un producto defectuoso).

+2

De acuerdo, escribí que la aplicación se ejecuta a través de un script que establece el classpath o java.ext.dirs solo para la aplicación. La carpeta lib (como se mencionó anteriormente) es parte de la aplicación, por lo que solo están disponibles los archivos jar necesarios para la aplicación. Entonces no hay bibliotecas compartidas ni rutas de clase compartidas aquí. –

+1

@jwenting, el interlocutor no está hablando de poner cosas en el directorio jre/lib/ext. Él está hablando de usar la bandera del comando 'java'' -Djava.ext.dirs'. – Pacerier

4

Joachim hizo una buena observación sobre el atajo de caracteres comodín. Pero ya que la pregunta es preguntar acerca de las diferencias y advertencias a tener en cuenta ...

Una diferencia es que si especificamos nuestras bibliotecas bajo la bandera -Djava.ext.dirs, serán loaded using the extension classloader (por ejemplo sun.misc.Launcher.ExtClassLoader) en lugar del cargador de clases del sistema (por ejemplo, sun.misc.Launcher.AppClassLoader).

Suponiendo que en nuestra biblioteca, tenemos una clase llamada Lib. Y nuestra aplicación se ejecuta este código:

public class Main { 
    public static void main(String args[]) { 
     System.out.println(System.getProperty("java.ext.dirs")); 
     ClassLoader test_cl = Main.class.getClassLoader(); 
     ClassLoader lib_cl = Lib.class.getClassLoader(); 
     System.out.println(test_cl == lib_cl); 
     System.out.println(test_cl); 
     System.out.println(lib_cl); 
    } 
} 

La salida de la consola será:

C:\Program Files\Java\jdk1.6.0\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext 
true 
[email protected] 
[email protected] 

cuando la aplicación se ejecuta utilizando el comando java -cp "folder/*;." Main.

Sin embargo, cuando la aplicación se ejecuta utilizando el comando java -Djava.ext.dirs=folder Main, la salida tendrá lugar ser:

folder 
false 
[email protected] 
[email protected] 
+0

¿Lo entiendo bien? Si tengo una biblioteca (en java.ext.dirs) que carga cosas de mi jar principal (que está en classpath), ¿eso no funcionará porque está en un cargador de clases diferente? –