Domanda

Sto cercando di eseguire manualmente un particolare test JUnit su una riga di comando di Windows XP, che presenta un numero insolitamente elevato di elementi nel percorso della classe. Ho provato diverse varianti, come ad esempio:

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

(Altre varianti stanno impostando il classpath tutto su una riga, impostando il classpath tramite -classpath come argomento su java "). Dipende sempre dalla console vomitare le mani con questo errore:

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

Questo è un test di JUnit che verifica un progetto legacy esistente piuttosto ampio, quindi nessun suggerimento su come riorganizzare la mia struttura di directory su qualcosa di più ragionevole, per ora questi tipi di soluzioni sono disponibili. Stavo solo cercando di eseguire un rapido test su questo progetto ed eseguirlo dalla riga di comando, e la console mi sta facendo un muro di pietra. Aiuto!

È stato utile?

Soluzione

La riga di comando di Windows è molto limitante in questo senso. Una soluzione alternativa è quella di creare un "vaso di tracciamento". Questo è un barattolo che contiene solo un file Manifest.mf , il cui Class-Path specifica i percorsi del disco del lungo elenco di barattoli, ecc. Ora basta aggiungere questo pathing jar al percorso di classe della riga di comando. Questo di solito è più conveniente che unire insieme le risorse effettive.

Come ricordo, i percorsi del disco possono essere relativi al pathing jar stesso. Quindi il Manifest.mf potrebbe assomigliare a questo:

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

Se il tuo pathing jar contiene principalmente risorse di base, allora non cambierà troppo frequentemente, ma probabilmente vorrai comunque generarlo da qualche parte nella tua build. Ad esempio:

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

Altri suggerimenti

Da Java 6 è possibile utilizzare classpath jolly .

Esempio: foo / * , si riferisce a tutti i file .jar nella directory foo

  • questo non corrisponderà ai file di classe (solo file jar). Per abbinare entrambi utilizzare: foo; foo / * o foo / *; foo . L'ordine determina cosa viene caricato per primo.
  • La ricerca NON è ricorsiva

Utilizza un file argomento " " su Java 9+

In Java 9+, l'eseguibile java supporta la fornitura di argomenti tramite un file. Vedere https: // docs .oracle.com / JavaSE / 9 / tools / java.htm # JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111 .

Questo meccanismo ha esplicitamente lo scopo di risolvere il problema delle limitazioni del sistema operativo sulla lunghezza dei comandi:

  

È possibile abbreviare o semplificare il comando java utilizzando i file @argument   per specificare un file di testo che contiene argomenti, come opzioni e   nomi di classe, passati al comando java. Ti consente di creare java   comandi di qualsiasi lunghezza su qualsiasi sistema operativo.

     

Nella riga di comando, utilizzare il prefisso at (@) per identificare un   file di argomenti che contiene opzioni java e nomi di classe. Quando il   Il comando java rileva un file che inizia con il segno at (@), esso   espande il contenuto di quel file in un elenco di argomenti proprio come loro   sarebbe specificato nella riga di comando.

Questo è il "giusto" soluzione, se si esegue la versione 9 o successiva. Questo meccanismo modifica semplicemente il modo in cui l'argomento viene fornito alla JVM e è quindi compatibile al 100% con qualsiasi framework o applicazione , indipendentemente da come eseguono il caricamento di classe, ovvero è completamente equivalente a fornire semplicemente l'argomento sull'argomento riga di comando come al solito. Questo non è vero per soluzioni alternative basate su manifest a questa limitazione del sistema operativo.

Un esempio di questo è:

Comando originale:

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

può essere riscritto come:

java @c: \ path \ to \ cparg

dove c: \ path \ to \ cparg è un file che contiene:

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

Questo " file di argomenti " supporta anche i caratteri di continuazione della riga e le virgolette per gestire correttamente gli spazi nei percorsi, ad esempio

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

Gradle

Se riscontri questo problema in Gradle, vedi questo plugin, che converte automaticamente il tuo percorso di classe in un file di argomento " " e lo fornisce a JVM quando si eseguono exec o test di attività su Windows. Su Linux o altri sistemi operativi non fa nulla per impostazione predefinita, sebbene sia possibile utilizzare un valore di configurazione opzionale per applicare la trasformazione indipendentemente dal sistema operativo.

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

(disclaimer: sono l'autore)

Vedi anche questo problema relativo a Gradle: si spera che questa funzionalità venga eventualmente integrata nel core Gradle: https :. //github.com/gradle/gradle/issues/1989

(suppongo che non intendi veramente DOS, ma fai riferimento a cmd.exe.)

Penso che sia meno un limite di CLASSPATH rispetto a un limite di dimensione variabile ambiente / ambiente. Su XP, le variabili di ambiente individuali possono avere una dimensione di 8k, l'intero ambiente è limitato a 64k. Non riesco a vedere che colpiresti quel limite.

Esiste un limite su Windows che limita la lunghezza di una riga di comando, su Windows NT + è 8k per cmd.exe. Un comando set è soggetto a tale limitazione. Può essere che tu abbia più di 8k di directory nel tuo comando set? Quindi potresti essere sfortunato, anche se li dividi come suggerito Nick Berardi .

Se fossi nei tuoi panni, scaricarei l'utilità di giunzione da MS: http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx e quindi mappa il tuo & Quot; C: \ percorso " per dire, " z: \ " e " c: \ path2 " per dire, " y: \ " ;. In questo modo, ridurrai 4 caratteri per elemento nel tuo 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;

Ora il tuo percorso di classe sarà:

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

Potrebbe fare di più a seconda del tuo attuale classpath .

Penso che tu sia nel fiume senza una pagaia qui. La riga di comando ha un limite per gli argomenti per chiamare un programma.

Ho 2 suggerimenti che potresti provare. Innanzitutto, prima di eseguire i test junit, è possibile consentire a uno script / ant_task di creare JAR delle varie classi sul percorso di classe. Quindi puoi inserire i JAR sul percorso di classe, che dovrebbe essere più corto.

Un altro modo per provare è creare un antscript per eseguire JUNIT, in ANT non ci dovrebbe essere un tale limite per le voci classpath.

Come accennato da HuibertGill, lo avvolgo in uno script di build Ant solo in modo da non dover gestire tutto da soli.

Potresti provare questo


@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%;"

vai al prompt dei comandi ed eseguilo due volte (non ho idea del perché .... devo farlo su una macchina Windows XP) anche i percorsi sono impostati solo per la sessione del prompt dei comandi corrente

Non c'era soluzione al problema se non quello di accorciare in qualche modo il classpath spostando i file jar in una cartella come " C: \ jars " ;.

Grazie a Raman per aver introdotto una nuova soluzione a un problema di tracciamento per Java 9+. Ho fatto un hack per bootRun che mi permette di usare tutto ciò che è già stato valutato da Gradle per eseguire java con file di argomenti. Non molto elegante ma funzionante.

// 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 = ''
        }
    }
}

Hai provato a impilarli?

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%
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top