Как установить длинный путь к классам Java в Windows? - PullRequest
40 голосов
/ 14 октября 2008

Я пытаюсь запустить определенный тест JUnit вручную в командной строке Windows XP, в которой необычно большое количество элементов в пути к классам. Я пробовал несколько вариантов, таких как:

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

(Другие варианты - установка classpath всего на одну строку, установка classpath через -classpath в качестве аргумента для java "). Это всегда сводится к тому, что консоль поднимает руки с этой ошибкой:

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

Это тест JUnit, тестирующий довольно большой существующий унаследованный проект, поэтому никаких предложений по перестройке моей структуры каталогов на что-то более разумное, эти типы решений пока отсутствуют. Я просто пытался выполнить быстрый тест для этого проекта и запустить его в командной строке, и консоль обескураживает меня. Помогите!

Ответы [ 11 ]

52 голосов
/ 14 октября 2008

Командная строка Windows очень ограничена в этом отношении. Обходной путь должен создать "дорожную флягу". Это jar-файл, содержащий только файл Manifest.mf, чей Class-Path указывает пути к дискам вашего длинного списка файлов jar и т. Д. Теперь просто добавьте этот pathing jar в путь к классам командной строки. Обычно это удобнее, чем объединять фактические ресурсы.

Насколько я помню, пути к дискам могут быть относительно самого pathing jar . Так что Manifest.mf может выглядеть примерно так:

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

Если ваш pathing jar содержит в основном основные ресурсы, то он не будет меняться слишком часто, но вы, вероятно, все равно захотите сгенерировать его где-нибудь в вашей сборке. Например:

<jar destfile="pathing.jar">
  <manifest>
    <attribute name="Class-Path" value="this.jar that.jar ../lib/other.jar"/>
  </manifest>
</jar>
20 голосов
/ 14 октября 2008

Начиная с Java 6, вы можете использовать подстановочные знаки classpath .

Пример: foo/*, относится ко всем файлам .jar в каталоге foo

  • это не будет соответствовать файлам классов (только файлы jar). Для совпадения используйте: foo;foo/* или foo/*;foo. Порядок определяет, что загружается первым.
  • Поиск НЕ рекурсивен
6 голосов
/ 19 января 2019

Используйте «Файл аргумента» на Java 9 +

В Java 9+ исполняемый файл Java поддерживает предоставление аргументов через файл. Увидеть https://docs.oracle.com/javase/9/tools/java.htm#JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111.

Этот механизм явно предназначен для решения проблемы ограничений ОС на длину команд:

Вы можете сократить или упростить команду java с помощью файлов @argument. указать текстовый файл, содержащий аргументы, такие как параметры и Имена классов, переданные в команду Java. Это позволит вам создать Java Команды любой длины в любой операционной системе.

В командной строке используйте префикс at (@) для определения файл аргументов, содержащий параметры Java и имена классов. Когда Команда Java встречает файл, начинающийся со знака (@), это расширяет содержимое этого файла в список аргументов так же, как они будет указан в командной строке.

Это «правильное» решение, если вы используете версию 9 или выше. Этот механизм просто изменяет способ предоставления аргумента JVM, и поэтому на 100% совместим с любой платформой или приложением , независимо от того, как они выполняют загрузку классов, т.е. это полностью эквивалентно простому предоставлению аргумента в команде линия как обычно. Это не относится к обходным решениям на основе манифеста для этого ограничения ОС.

Примером этого является:

Исходная команда:

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

можно переписать как:

java @c:\path\to\cparg

где c:\path\to\cparg - файл, содержащий:

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

Этот "файл аргументов" также поддерживает символы продолжения строки и кавычки для правильной обработки пробелов в путях, например

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

Gradle

Если вы столкнулись с этой проблемой в Gradle, посмотрите этот плагин, который автоматически преобразует ваш путь к классам в «файл аргументов» и предоставляет его JVM при выполнении exec или тестовых задач в Windows. В Linux или других операционных системах по умолчанию он ничего не делает, хотя для применения преобразования независимо от ОС можно использовать дополнительное значение конфигурации.

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

(отказ от ответственности: я автор)

См. Также эту связанную проблему Gradle - надеюсь, эта возможность в конечном итоге будет интегрирована в ядро ​​Gradle: https://github.com/gradle/gradle/issues/1989.

4 голосов
/ 14 октября 2008

(Полагаю, вы на самом деле не имеете в виду DOS, но обратитесь к cmd.exe.)

Я думаю, что это меньше ограничение CLASSPATH, чем ограничение размера среды / размера переменной среды. В XP отдельные переменные среды могут иметь размер 8 КБ, вся среда ограничена 64 КБ. Я не вижу, чтобы вы достигли этого предела.

Существует ограничение для окон, которое ограничивает длину командной строки, для WindowsNT + это 8 КБ для cmd.exe. Команда set подпадает под это ограничение. Может быть, в вашей команде set есть каталоги более 8 тысяч? Тогда вам может не повезти - даже если вы разделите их, как предложил Ник Берарди .

1 голос
/ 14 октября 2008

Если бы я был на вашем месте, я бы скачал утилиту соединения от MS: http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx и затем сопоставил бы вашу «C: \ path», чтобы сказать, «z: \» и «c: \ path2», чтобы сказать, «y: \». Таким образом, вы будете уменьшать 4 символа за элемент в вашем 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;

Теперь ваш classpath будет:

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

Это может сделать больше в зависимости от вашего фактического classpath.

0 голосов
/ 22 марта 2019

Спасибо Раману за представление нового решения проблемы маршрутизации для Java 9+. Я взломал задачу bootRun, которая позволяет использовать все, что уже было оценено gradle, для запуска java с файлами аргументов. Не очень элегантно, но работает.

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

0 голосов
/ 19 октября 2016

У этой проблемы не было иного решения, кроме как как-то сократить путь к классам, переместив файлы jar в папку типа "C: \ jars".

0 голосов
/ 10 июля 2012

Вы можете попробовать это


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

перейдите в командную строку и запустите ее дважды (не знаю почему .... я должен сделать это на компьютере с Windows XP) также пути r, установленные только для текущего сеанса командной строки

0 голосов
/ 14 октября 2008

Как упоминает HuibertGill, я бы обернул это в скрипт сборки Ant, чтобы вам не приходилось управлять всем этим самостоятельно.

0 голосов
/ 14 октября 2008

Я думаю, что вы здесь без ручья. У командной строки есть предел для аргументов для вызова программы.

У меня есть 2 предложения, которые вы можете попробовать. Во-первых, перед запуском тестов junit вы можете позволить скрипту / ant_task создать JAR-файлы различных классов на пути к классам. Затем вы можете поместить файлы JAR в путь к классам, который должен быть короче.

Еще один способ, которым вы можете попробовать, - создать antscript для запуска JUNIT, в ANT не должно быть такого ограничения для записей classpath.

...