Pergunta

Eu estou tentando executar um teste JUnit especial à mão sobre uma linha de comando do Windows XP, que tem um número anormalmente elevado de elementos no caminho de classe. Eu tentei diversas variações, 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

(Outras variações estão definindo o classpath em uma única linha, definindo o classpath via -classpath como um argumento para java ") Ele sempre se resume ao console de vomitar é mãos com este erro:.

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

Este é um teste JUnit testar uma bastante grande projeto de legado existente, então há sugestões sobre como reorganizar a minha estrutura de diretório para algo mais razoável, esses tipos de soluções estão fora por agora. Eu estava apenas tentando gen-se um teste rápido contra este projecto e executá-lo na linha de comando, e o console está me obstrução. Ajuda!

Foi útil?

Solução

A linha de comando do Windows é muito limitante a este respeito. A solução é criar um "jar pathing". Este é um frasco contendo apenas um arquivo Manifest.mf, cujo Class-Path especifica os caminhos de disco da sua longa lista de frascos, etc. Agora, basta adicionar este pathing jar para o seu classpath linha de comando. Isso geralmente é mais conveniente do que a embalagem os recursos reais juntos.

Se bem me lembro, os caminhos de disco pode ser relativo ao pathing jar em si. Assim, o Manifest.mf poderia ser algo como isto:

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

Se o seu pathing jar contém recursos principalmente fundamentais, então não vai mudar muita freqüência, mas você provavelmente ainda deseja gerar lo em algum lugar em sua construção. Por exemplo:

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

Outras dicas

Desde Java 6 você pode usar classpath wildcards .

Exemplo: foo/*, refere-se a todos os arquivos .jar no diretório foo

  • isso não irá corresponder arquivos de classe (apenas arquivos jar). Para corresponder tanto para uso: foo;foo/* ou foo/*;foo. A ordem determina o que é carregado pela primeira vez.
  • A pesquisa não é recursiva

Use um "argumento File" em Java 9 +

Em Java com mais de 9, os Java suporta executáveis ??fornecendo argumentos através de um arquivo. Vejo https: // docs .oracle.com / JavaSE / 9 / ferramentas / java.htm # JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111 .

Este mecanismo é explicitamente a intenção de resolver o problema das limitações do sistema operacional em comprimentos de comando:

Você pode encurtar ou simplificar o comando java usando arquivos @argument para especificar um arquivo de texto que contém argumentos, como opções e nomes de classe, passado para o comando java. Isto permite que você para criar java comandos de qualquer comprimento em qualquer sistema operacional.

Na linha de comando, use o sinal de arroba (@) prefixo para identificar um arquivo argumento que contém opções Java e nomes de classe. Quando o comando java encontra um arquivo começando com o sinal de arroba (@), ele expande o conteúdo desse arquivo em uma lista de argumentos, assim como eles seria especificado na linha de comando.

Esta é a solução "correta", se você estiver executando a versão 9 ou superior. Este mecanismo simplesmente modifica a forma como o argumento é fornecido para a JVM, e é, portanto, 100% compatível com qualquer framework ou aplicativo , independentemente de como eles classloading ou seja, é completamente equivalente a simplesmente fornecer o argumento sobre a linha de comando, como de costume. Isso não é verdade para soluções baseada em manifesto para esta limitação OS.

Um exemplo disto é:

comando Original:

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

pode ser reescrita como:

java @c:\path\to\cparg

onde c:\path\to\cparg é um arquivo que contém:

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

Este arquivo "argumento" também suporta caracteres de continuação de linha e citando para lidar corretamente espaços nos caminhos v.g..

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

Gradle

Se você está enfrentando esse problema no Gradle, consulte este plugin, que converte o seu classpath automaticamente em um "arquivo de argumentos" e prevê que a JVM ao fazer tarefas exec ou teste no Windows. Em outros sistemas operacionais Linux ou ele não faz nada por padrão, embora um valor de configuração opcional pode ser usado para aplicar a transformação, independentemente do sistema operacional.

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

(disclaimer: Eu sou o autor)

Veja também esta questão Gradle relacionado - espero que esta capacidade será eventualmente integrada no núcleo Gradle: https :. //github.com/gradle/gradle/issues/1989

(Eu suponho que você realmente não quer dizer DOS, mas referem-se cmd.exe).

Eu acho que é menos uma limitação CLASSPATH do que um limite de tamanho variável tamanho de ambiente / meio ambiente. No XP, variáveis ??de ambiente individuais podem ser 8k em tamanho, todo o ambiente é limitado a 64k. Eu não posso ver você teria atingido esse limite.

Há um limite no Windows que restringe o comprimento de uma linha de comando, no WindowsNT + é o 8k para cmd.exe. Um comando conjunto é sujeito a esta restrição. Pode ser que você tem mais de 8k valor de diretórios em seu comando set? Você pode estar fora de sorte, então - mesmo se você dividi-los como Nick Berardi sugeriu.

Se eu estivesse no seu lugar, gostaria de baixar o utilitário junção de MS: http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx e, em seguida, mapear seu "C: \ caminho" dizer "z: \" e "c: \ cami2" quer dizer, "Y: \". Dessa forma, você estará reduzindo 4 caracteres por item em seu 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;

Agora, o seu 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;

Pode fazer mais, dependendo da sua classpath real.

Eu acho que você é até o córrego sem uma pá aqui. O comando tem um limite para argumentos para chamar um programm.

Eu tenho 2 sugestão que você poderia tentar. Em primeiro lugar, antes de executar os testes JUnit, você pode deixar um script / ant_task criar JARs das várias classes no classpath. Então você pode colocar os JARs no classpath, que deve ser mais curto.

Outra maneira você poderia tentar é criar um antscript para executar JUnit, em ANT não deve haver tal limite para entradas de classpath.

Como HuibertGill menciona, eu iria quebrar isso em um script de construção Ant apenas para que você não tem que gerenciar tudo isso sozinho.

Você poderia tentar este


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

ir para um prompt de comando e executá-lo duas vezes (nenhuma idéia porque .... eu tenho que fazê-lo em uma máquina Windows XP) Também os caminhos r definida apenas para o comando atual sessão de prompt

Não houve solução para o problema que não seja de alguma forma, fazendo com que o classpath mais curto, movendo os arquivos jar em uma pasta como "C: \ frascos".

Graças ao Raman para a introdução de uma nova solução para um problema pathing para Java 9+. Eu fiz um hack para tarefa bootRun que permite usar tudo já avaliadas pela Gradle para executar java com arquivos de argumento. Não é muito elegante, mas funcionando.

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

Você tentou empilhá-los?

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top