Как установить длинный путь к классам Java в Windows?

StackOverflow https://stackoverflow.com/questions/201816

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь вручную запустить конкретный тест 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 в качестве аргумента Java).Всегда всё сводится к тому, что консоль вскидывает руки с такой ошибкой:

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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

Используйте «Файл аргументов» на 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 Sign (@), чтобы определить файл аргумента, который содержит параметры Java и имена классов.Когда команда Java встречается с файлом, начиная с AT Sign (@), она расширяет содержимое этого файла в список аргументов так же, как они будут указаны в командной строке.

Это «правильное» решение, если вы используете версию 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, см. этот плагин, который автоматически преобразует ваш путь к классам в «файл аргументов» и предоставляет его JVM при выполнении задач выполнения или тестирования в Windows.В Linux или других операционных системах по умолчанию он ничего не делает, хотя для применения преобразования можно использовать дополнительное значение конфигурации независимо от ОС.

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

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

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

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

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

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

Если бы я был на вашем месте, я бы скачал с MS утилиту Junction: 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;

Теперь ваш путь к классам будет:

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.

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

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

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

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

Вы могли бы попробовать это


@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 установлены только для текущего сеанса командной строки

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

Благодаря Рамановский за представление нового решения проблемы пути для 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 = ''
        }
    }
}

Вы пробовали их складывать?

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%
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top