简体   繁体   English

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

[英]How to set a long Java classpath in Windows?

I'm trying to run a particular JUnit test by hand on a Windows XP command line, which has an unusually high number of elements in the class path.我正在尝试在 Windows XP 命令行上手动运行特定的 JUnit 测试,该命令行在类路径中具有异常多的元素。 I've tried several variations, such as:我尝试了几种变体,例如:

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

(Other variations are setting the classpath all on one line, setting the classpath via -classpath as an argument to java"). It always comes down to the console throwing up it's hands with this error: (其他变体是在一行上设置类路径,通过 -classpath 将类路径设置为 java 的参数”)。它总是归结为控制台抛出这个错误:

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

This is a JUnit test testing a rather large existing legacy project, so no suggestions about rearranging my directory structure to something more reasonable, those types of solutions are out for now.这是一个 JUnit 测试,测试一个相当大的现有遗留项目,所以没有关于将我的目录结构重新安排为更合理的建议,这些类型的解决方案现在已经出来了。 I was just trying to gen up a quick test against this project and run it on the command line, and the console is stonewalling me.我只是想针对这个项目生成一个快速测试并在命令行上运行它,而控制台正在阻碍我。 Help!帮助!

The Windows command line is very limiting in this regard. Windows 命令行在这方面非常有限。 A workaround is to create a "pathing jar".一种解决方法是创建一个“路径 jar”。 This is a jar containing only a Manifest.mf file, whose Class-Path specifies the disk paths of your long list of jars, etc. Now just add this pathing jar to your command line classpath.这是一个仅包含Manifest.mf文件的 jar,其Class-Path指定了长长的 jar 列表的磁盘路径等。现在只需将此路径 jar添加到您的命令行类路径中。 This is usually more convenient than packaging the actual resources together.这通常比将实际资源打包在一起更方便。

As I recall, the disk paths can be relative to the pathing jar itself.我记得,磁盘路径可以相对于路径 jar本身。 So the Manifest.mf might look something like this:所以Manifest.mf可能看起来像这样:

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

If your pathing jar contains mainly foundational resources, then it won't change too frequently, but you will probably still want to generate it somewhere in your build.如果您的路径 jar主要包含基础资源,则它不会更改太频繁,但您可能仍希望在构建中的某个地方生成它。 For example:例如:

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

Since Java 6 you can use classpath wildcards .从 Java 6 开始,您可以使用类路径通配符

Example: foo/* , refers to all .jar files in the directory foo示例: foo/* ,指的是目录foo中的所有 .jar 文件

  • this will not match class files (only jar files).这将不匹配类文件(仅 jar 文件)。 To match both use: foo;foo/* or foo/*;foo .要匹配两者,请使用: foo;foo/*foo/*;foo The order determines what is loaded first.顺序决定了先加载什么。
  • The search is NOT recursive搜索不是递归的

Use An "Argument File" on Java 9+在 Java 9+ 上使用“参数文件”

In Java 9+, the java executable supports providing arguments via a file.在 Java 9+ 中,java 可执行文件支持通过文件提供参数。 See https://docs.oracle.com/javase/9/tools/java.htm#JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111 .请参阅https://docs.oracle.com/javase/9​​/tools/java.htm#JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111

This mechanism is explicitly intended to solve the problem of OS limitations on command lengths:该机制明确旨在解决操作系统对命令长度的限制问题:

You can shorten or simplify the java command by using @argument files to specify a text file that contains arguments, such as options and class names, passed to the java command.您可以通过使用@argument 文件指定包含传递给 java 命令的参数(例如选项和类名)的文本文件来缩短或简化 java 命令。 This let's you to create java commands of any length on any operating system.这让您可以在任何操作系统上创建任何长度的 java 命令。

In the command line, use the at sign (@) prefix to identify an argument file that contains java options and class names.在命令行中,使用 at 符号 (@) 前缀来标识包含 java 选项和类名的参数文件。 When the java command encounters a file beginning with the at sign (@) , it expands the contents of that file into an argument list just as they would be specified on the command line.当 java 命令遇到以 at 符号 (@) 开头的文件时,它会将该文件的内容扩展为参数列表,就像在命令行中指定的那样。

This is the "right" solution, if you are running version 9 or above.如果您运行的是版本 9 或更高版本,这是“正确”的解决方案。 This mechanism simply modifies how the argument is provided to the JVM, and is therefore 100% compatible with any framework or application , regardless of how they do classloading ie it is completely equivalent to simply providing the argument on the command line as usual.这种机制简单地修改了参数提供给 JVM 的方式,因此与任何框架或应用程序 100% 兼容,无论它们如何进行类加载,即它完全等同于像往常一样在命令行上简单地提供参数。 This is not true for manifest-based workarounds to this OS limitation.对于此操作系统限制的基于清单的解决方法,情况并非如此。

An example of this is:这方面的一个例子是:

Original command:原始命令:

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

can be rewritten as:可以改写为:

java @c:\\path\\to\\cparg

where c:\\path\\to\\cparg is a file which contains:其中c:\\path\\to\\cparg是一个文件,其中包含:

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

This "argument file" also supports line continuation characters and quoting for properly handling spaces in paths eg这个“参数文件”还支持行继续符和引号以正确处理路径中的空格,例如

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

Gradle摇篮

If you are encountering this issue in Gradle, see this plugin, which converts your classpath automatically into an "argument file" and provides that to the JVM when doing exec or test tasks on Windows.如果您在 Gradle 中遇到此问题,请参阅此插件,它会自动将您的类路径转换为“参数文件”,并在 Windows 上执行 exec 或 test 任务时将其提供给 JVM。 On Linux or other operating systems it does nothing by default, though an optional configuration value can be used to apply the transformation regardless of OS.在 Linux 或其他操作系统上,默认情况下它什么都不做,尽管可以使用可选的配置值来应用转换,而不管操作系统如何。

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

(disclaimer: I am the author) (免责声明:我是作者)

See also this related Gradle issue -- hopefully this capability will eventually be integrated into Gradle core: https://github.com/gradle/gradle/issues/1989 .另请参阅此相关的 Gradle 问题——希望此功能最终会集成到 Gradle 核心中: https : //github.com/gradle/gradle/issues/1989

(I suppose you do not really mean DOS, but refer to cmd.exe.) (我想你的意思并不是真正的 DOS,而是指 cmd.exe。)

I think it is less a CLASSPATH limitation than an environment size/environment variable size limit.我认为它不是环境大小/环境变量大小限制的 CLASSPATH 限制。 On XP, individual environment variables can be 8k in size, the entire environment is limited to 64k.在 XP 上,单个环境变量的大小可以为 8k,整个环境限制为 64k。 I can't see you would hit that limit.我看不出你会达到那个极限。

There is a limit on windows that restricts the length of a command line, on WindowsNT+ it is 8k for cmd.exe. Windows 上有一个限制命令行长度的限制,在 WindowsNT+ 上,cmd.exe 是 8k。 A set command is subject to that restriction. set 命令受该限制的约束。 Can it be you have more than 8k worth of directories in your set command?你的 set 命令中是否有超过 8k 的目录? You may be out of luck, then - even if you split them up like Nick Berardi suggested.那么你可能不走运——即使你像尼克贝拉迪建议的那样把它们分开。

Thanks to Raman for introducing a new solution to a pathing problem for Java 9+.感谢Raman为 Java 9+ 的路径问题引入了新的解决方案。 I made a hack to bootRun task that allows using everything already evaluated by gradle to run java with argument files.我对bootRun任务进行了 hack, bootRun任务允许使用 gradle 已经评估过的所有内容来运行带有参数文件的 java。 Not very elegant but working.不是很优雅,但工作。

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

If I were in your shoes, I would download the junction utility from MS : http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx and then map your "C:\\path" to say, "z:\\" and "c:\\path2" to say, "y:\\".如果我是你的话,我会从 MS 下载连接实用程序: http : //technet.microsoft.com/en-us/sysinternals/bb896768.aspx然后映射你的“C:\\path”说,“z :\\" 和 "c:\\path2" 表示 "y:\\"。 This way, you will be reducing 4 characters per item in your classpath .这样,您将减少classpath每个项目的 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;

Now, your classpath will be :现在,您的类路径将是:

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

It might do more depending on your actual classpath .根据您的实际classpath它可能会做得更多。

You could try this你可以试试这个


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

go to a command prompt and run it twice(no idea why....i have to do so on a windows XP machine) also the paths r set only for the current command prompt session转到命令提示符并运行两次(不知道为什么....我必须在 Windows XP 机器上这样做)以及仅为当前命令提示符会话设置的路径

I think you are up the creek without a paddle here.我想你在这里没有桨就在小溪上。 The commandline has a limit for arguments to call a programm.命令行对调用程序的参数有限制。

I have 2 sugestion you could try.我有 2 sugestion 你可以尝试。 First, prior to running the junit tests, you can let a script/ant_task create JARs of the various classes on the classpath.首先,在运行 junit 测试之前,您可以让 script/ant_task 在类路径上创建各种类的 JAR。 Then you can put the JARs on the classpath, which should be shorter.然后你可以将 JAR 放在类路径上,它应该更短。

Another way you could try is to create an antscript to run JUNIT, in ANT there should not be such a limit for classpath entries.您可以尝试的另一种方法是创建一个 antscript 来运行 JUNIT,在 ANT 中,类路径条目不应该有这样的限制。

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

除了通过将 jar 文件移动到“C:\\jars”之类的文件夹中以某种方式缩短类路径之外,没有解决此问题的方法。

Fix for windows gradle long classpath issue.修复 windows gradle 长类路径问题。 Fixes JavaExec tasks that error out with message "CreateProcess error=206, The filename or extension is too long"修复了错误消息“CreateProcess error=206, The filename or extension is too long”的 JavaExec 任务

Using the plugins DSL:使用插件 DSL:

plugins {
  id "com.github.ManifestClasspath" version "0.1.0-RELEASE"
}

Using legacy plugin application:使用旧插件应用程序:

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"

I had a similar issue here with a giant classpath definition inside a .bat file.我在这里遇到了类似的问题,在 .bat 文件中有一个巨大的类路径定义。 The problem was that this class path was also including the execution path into the giant path, its ok, its make sense.问题是这个类路径也包含了进入巨型路径的执行路径,这很好,很有意义。 In this context, the software was not able to run and the message "The input line is too long" appeared everytime.在这种情况下,软件无法运行,每次都出现“输入行太长”的消息。

Solution: I just moved the all files to a shorter position.解决方案:我只是将所有文件移动到较短的位置。 For instance, I was trying to execute the software in a directory tree like: c:\\softwares\\testing\\testing_solution\\one例如,我试图在目录树中执行软件,如:c:\\softwares\\testing\\testing_solution\\one

and I moved the whole structure to a point like this我将整个结构移动到这样的点

c:\\test c:\\测试

The software worked very well.该软件运行良好。 It is not the best option, I know, but might help some one who is looking to a fast solution.我知道,这不是最好的选择,但可能会对寻求快速解决方案的人有所帮助。

Tks塔克斯

Have you tried stacking them?你试过堆叠它们吗?

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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM