Pregunta

Estoy tratando de ejecutar una prueba JUnit particular a mano en una línea de comandos de Windows XP, que tiene un número inusualmente alto de elementos en la ruta de clase. He intentado varias variaciones, como:

set CLASS_PATH=C:\path\a\b\c;C:\path\e\f\g;....
set CLASS_PATH=%CLASS_PATH%;C:\path2\a\b\c;C:\path2\e\f\g;....
...
C:\apps\jdk1.6.0_07\bin\java.exe -client oracle.jdevimpl.junit.runner.TestRunner com.myco.myClass.MyTest testMethod

(Otras variaciones están configurando el classpath en una sola línea, configurando el classpath a través de -classpath como argumento para java "). Siempre se trata de que la consola arroje sus manos con este error:

The input line is too long.
The syntax of the command is incorrect.

Esta es una prueba JUnit que prueba un proyecto heredado existente bastante grande, por lo que no hay sugerencias sobre reorganizar mi estructura de directorios a algo más razonable, ese tipo de soluciones están disponibles por ahora. Solo estaba tratando de generar una prueba rápida contra este proyecto y ejecutarlo en la línea de comando, y la consola me está bloqueando. Ayuda!

¿Fue útil?

Solución

La línea de comando de Windows es muy limitante a este respecto. Una solución alternativa es crear un "tarro de ruta". Este es un frasco que contiene solo un archivo Manifest.mf , cuyo Class-Path especifica las rutas de disco de su larga lista de frascos, etc. Ahora solo agregue este pathing jar a su classpath de línea de comando. Esto suele ser más conveniente que agrupar los recursos reales.

Como recuerdo, las rutas del disco pueden ser relativas al jar de ruta mismo. Entonces el Manifest.mf podría verse más o menos así:

Class-Path: this.jar that.jar ../lib/other.jar

Si su pathing jar contiene principalmente recursos fundamentales, entonces no cambiará con demasiada frecuencia, pero probablemente aún quiera generarlo en algún lugar de su compilación. Por ejemplo:

<jar destfile="pathing.jar">
  <manifest>
    <attribute name="Class-Path" value="this.jar that.jar ../lib/other.jar"/>
  </manifest>
</jar>

Otros consejos

Desde Java 6 puede usar classpath comodines .

Ejemplo: foo / * , se refiere a todos los archivos .jar en el directorio foo

  • esto no coincidirá con los archivos de clase (solo archivos jar). Para hacer coincidir ambos, use: foo; foo / * o foo / *; foo . El orden determina qué se carga primero.
  • La búsqueda NO es recursiva

Use un " Archivo de argumentos " en Java 9+

En Java 9+, el ejecutable de Java admite el suministro de argumentos a través de un archivo. Ver https: // docs .oracle.com / javase / 9 / tools / java.htm # JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111 .

Este mecanismo tiene la intención explícita de resolver el problema de las limitaciones del sistema operativo en las longitudes de los comandos:

  

Puede acortar o simplificar el comando java utilizando archivos @argument   para especificar un archivo de texto que contenga argumentos, como opciones y   nombres de clase, pasados ??al comando java. Esto le permite crear Java   comandos de cualquier longitud en cualquier sistema operativo.

     

En la línea de comando, use el prefijo at (@) para identificar un   archivo de argumento que contiene opciones de Java y nombres de clase. Cuando el   el comando java encuentra un archivo que comienza con el signo at (@),   expande el contenido de ese archivo en una lista de argumentos tal como   se especificaría en la línea de comando.

Este es el " derecho " solución, si está ejecutando la versión 9 o superior. Este mecanismo simplemente modifica cómo se proporciona el argumento a la JVM y, por lo tanto, es 100% compatible con cualquier marco o aplicación , independientemente de cómo se carga la clase, es decir, es completamente equivalente a simplemente proporcionar el argumento en el línea de comando como de costumbre. Esto no es cierto para las soluciones basadas en manifiesto a esta limitación del sistema operativo.

Un ejemplo de esto es:

Comando original:

java -cp c: \ foo \ bar.jar; c: \ foo \ baz.jar

se puede reescribir como:

java @c: \ path \ to \ cparg

donde c: \ path \ to \ cparg es un archivo que contiene:

-cp c:\foo\bar.jar;c:\foo\baz.jar

Este " archivo de argumentos " también admite caracteres de continuación de línea y comillas para manejar adecuadamente los espacios en las rutas, por ejemplo,

-cp "\
c:\foo\bar.jar;\
c:\foo\baz.jar"

Gradle

Si se encuentra con este problema en Gradle, consulte este complemento, que convierte su classpath automáticamente en un archivo de argumento " y proporciona eso a la JVM cuando realiza tareas ejecutivas o de prueba en Windows. En Linux u otros sistemas operativos, no hace nada de manera predeterminada, aunque se puede usar un valor de configuración opcional para aplicar la transformación independientemente del sistema operativo.

https://github.com/redocksoft/classpath-to-file- gradle-plugin

(descargo de responsabilidad: yo soy el autor)

Vea también este problema relacionado con Gradle: con suerte, esta capacidad se integrará eventualmente en el núcleo de Gradle: https : //github.com/gradle/gradle/issues/1989 .

(supongo que en realidad no se refiere a DOS, sino que se refiere a cmd.exe).

Creo que es menos una limitación de CLASSPATH que un límite de tamaño de entorno / tamaño de variable de entorno. En XP, las variables de entorno individuales pueden tener un tamaño de 8k, todo el entorno está limitado a 64k. No veo que alcanzarías ese límite.

Hay un límite en Windows que restringe la longitud de una línea de comando, en WindowsNT + es 8k para cmd.exe. Un comando set está sujeto a esa restricción. ¿Puede ser que tenga más de 8k de directorios en su comando set? Puede que no tenga suerte, entonces, incluso si los divide como Nick Berardi sugerido.

Si estuviera en su lugar, descargaría la utilidad de unión de MS: http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx y luego mapee su " C: \ ruta & " decir, "z: \" y "c: \ path2" decir, "y: \". De esta manera, reducirá 4 caracteres por elemento en su classpath .

set CLASS_PATH=C:\path\a\b\c;C:\path\e\f\g;
set CLASS_PATH=%CLASS_PATH%;C:\path2\a\b\c;C:\path2\e\f\g;

Ahora, tu classpath será:

set CLASS_PATH=z\a\b\c;z\e\f\g;
set CLASS_PATH=%CLASS_PATH%;y:\a\b\c;y:\e\f\g;

Podría hacer más dependiendo de su classpath real.

Creo que estás arriba del arroyo sin una paleta aquí. La línea de comando tiene un límite de argumentos para llamar a un programa.

Tengo 2 sugestiones que podrías probar. Primero, antes de ejecutar las pruebas junit, puede dejar que un script / ant_task cree JAR de las diversas clases en el classpath. Luego puede colocar los JAR en el classpath, que debería ser más corto.

Otra forma de intentarlo es crear un antscript para ejecutar JUNIT, en ANT no debería haber tal límite para las entradas de classpath.

Como menciona HuibertGill, envolvería esto en un script de compilación Ant para que no tenga que administrar todo esto usted mismo.

Podrías probar esto


@echo off
set A=D:\jdk1.6.0_23\bin
set B=C:\Documents and Settings\674205\Desktop\JavaProj
set PATH="%PATH%;%A%;"
set CLASSPATH="%CLASSPATH%;%B%;"

vaya a un símbolo del sistema y ejecútelo dos veces (no tengo idea de por qué ... tengo que hacerlo en una máquina con Windows XP) también las rutas r establecidas solo para la sesión actual del símbolo del sistema

No había otra solución al problema que hacer que el classpath sea más corto moviendo los archivos jar a una carpeta como " C: \ jars " ;.

Gracias a Raman por presentar una nueva solución a un problema de ruta para Java 9+. Realicé una tarea de pirateo de bootRun que permite usar todo lo que ya evaluó gradle para ejecutar java con archivos de argumentos. No es muy elegante pero funciona.

// Fix long path problem on Windows by utilizing java Command-Line Argument Files 
// https://docs.oracle.com/javase/9/tools/java.htm#JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111 
// The task creates the command-line argument file with classpath
// Then we specify the args parameter with path to command-line argument file and main class
// Then we clear classpath and main parameters
// As arguments are applied after applying classpath and main class last step 
// is done to cheat gradle plugin: we will skip classpath and main and manually
// apply them through args
// Hopefully at some point gradle will do this automatically 
// https://github.com/gradle/gradle/issues/1989 

if (Os.isFamily(Os.FAMILY_WINDOWS)) {
    bootRun {
        doFirst {
            def argumentFilePath = "build/javaArguments.txt"
            def argumentFile = project.file(argumentFilePath)
            def writer = argumentFile.newPrintWriter()
            writer.print('-cp ')
            writer.println(classpath.join(';'))
            writer.close()

            args = ["@${argumentFile.absolutePath}", main]
            classpath = project.files()
            main = ''
        }
    }
}

¿Has intentado apilarlos?

set CLASS_PATH = c:\path
set ALT_A = %CLASS_PATH%\a\b\c;
set ALT_B = %CLASS_PATH%\e\f\g;
...

set ALL_PATHS = %CLASS_PATH%;%ALT_A%;%ALT_B%
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top