如何在Windows中设置长Java类路径?

如何在Windows中设置长Java类路径?,java,junit,classpath,Java,Junit,Classpath,我正试图在WindowsXP命令行上手动运行一个特定的JUnit测试,该命令行在类路径中包含异常多的元素。我尝试了几种变体,例如: 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

我正试图在WindowsXP命令行上手动运行一个特定的JUnit测试,该命令行在类路径中包含异常多的元素。我尝试了几种变体,例如:

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测试,测试的是一个相当大的现有遗留项目,因此没有关于将我的目录结构重新安排到更合理的位置的建议,这些类型的解决方案现在已经过时了。我只是尝试对这个项目进行一个快速测试,并在命令行上运行它,控制台正在阻止我。帮助!

Ha你试过把它们叠起来吗

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%

我认为你在这里没有划桨,处境艰难。 命令行对调用程序的参数有限制

我有两个建议你可以试试。 首先,在运行junit测试之前,可以让脚本/ant_任务在类路径上创建各种类的JAR。 然后可以将jar放在类路径上,该路径应该更短

您可以尝试的另一种方法是创建一个antscript来运行JUNIT, 在ANT中,类路径条目不应该有这样的限制。

(我想你不是指DOS,而是指cmd.exe。)

我认为这与其说是一个类路径限制,不如说是一个环境大小/环境变量大小限制。在XP上,单个环境变量的大小可以是8k,整个环境的大小限制为64k。我看不出你会达到这个限制


windows上有一个限制命令行长度的限制,在WindowsNT+上,cmd.exe的长度是8k。set命令受此限制。set命令中是否有超过8k的目录?那么,您可能运气不好,即使按照建议将它们拆分。

windows命令行非常有限解决方法是创建一个“路径jar”“。这是一个仅包含
Manifest.mf
文件的jar,其
类路径
指定了jar长列表的磁盘路径等。现在只需将此路径jar添加到命令行类路径中即可。这通常比将实际资源打包在一起更方便

我记得,磁盘路径可以是相对于路径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>

因为您可以使用Java 6

示例:
foo/*
,引用目录
foo

  • 这与类文件(仅jar文件)不匹配。要匹配两者,请使用:
    foo;foo/*
    foo/*;foo
    。顺序决定首先加载的内容
  • 搜索不是递归的

正如HuibertGill所提到的,我会将其封装在Ant构建脚本中,这样您就不必自己管理所有这些。

如果我是您的话,我会从MS:下载连接实用程序,然后映射您的 “C:\path”表示“z:\”,而“C:\path2”表示“y:\”。这样,在
类路径中,每个项目将减少4个字符

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;
根据实际的
类路径,它可能会做得更多。您可以试试这个


转到命令提示符并运行两次(不知道为什么…我必须在windows XP机器上这样做)
此外,仅为当前命令提示符会话设置的路径r也没有解决此问题的方法,只能通过将jar文件移动到“C:\jars”这样的文件夹中,以某种方式缩短类路径。

在Java 9上使用“参数文件”+ 在Java9+中,Java可执行文件支持通过文件提供参数。看见

此机制明确旨在解决操作系统对命令长度的限制问题:

您可以使用@argument文件来缩短或简化java命令 指定包含参数的文本文件,如选项和 类名称,传递给java命令这让您可以创建java 任何操作系统上任意长度的命令。

在命令行中,使用at符号(@)前缀标识 包含java选项和类名的参数文件。当 java命令遇到一个以at符号(@)开头的文件,它 将该文件的内容展开为参数列表,就像它们一样 将在命令行上指定

如果您运行的是版本9或更高版本,这是“正确”的解决方案。这种机制只是修改了参数提供给JVM的方式,因此与任何框架或应用程序都是100%兼容的,不管它们如何进行类加载,也就是说,它完全等同于像往常一样在命令行上提供参数。对于基于清单的解决方案,此操作系统限制并非如此

这方面的一个例子是:

原始命令:

java-cpc:\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中遇到此问题,请参阅此插件,它会自动将您的类路径转换为“参数文件”,并在Windows上执行exec或测试任务时提供给JVM。在Linux或其他操作系统上,默认情况下它什么也不做,尽管可以使用可选的配置值来应用转换,而不考虑操作系统

(免责声明:我是作者)

另请参见相关的Gradle问题——希望是这一上限
-cp "\
c:\foo\bar.jar;\
c:\foo\baz.jar"
// 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 = ''
        }
    }
}

plugins {
  id "com.github.ManifestClasspath" version "0.1.0-RELEASE"
}
buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.github.viswaramamoorthy:gradle-util-plugins:0.1.0-RELEASE"
  }
}

apply plugin: "com.github.ManifestClasspath"