# 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. 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:

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. 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. A workaround is to create a "pathing 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. 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. So the Manifest.mf might look something like this:

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. For example:

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

• The ManifestClassPath task available in Ant since version 1.7 can be used to generate a suitable property for the Class-Path attribute from an Ant Path.
– Matt
Mar 21, 2012 at 19:53
• Do I need to do anything, eg ensure that this jar is loaded? Or will the JVM scan all jars provided on the class path for such manifests? Also, is it portable across JVMs? What's the minimum version of Java that supports this? Sep 30, 2014 at 13:26
• I tried this, but the Manifest.mf allows only relative URLs to other JARs and directories. Jan 22, 2018 at 17:58
• maximum characters in the classpath list per line IS 72. SO what is the limit of Class-Path in Manifest.MF file??? Aug 31, 2018 at 8:04
• Note that this is what Maven Surefire does by default, but a recent Java update made this harder. Nov 7, 2018 at 14:31

Since Java 6 you can use classpath wildcards.

Example: foo/*, refers to all .jar files in the directory foo

• this will not match class files (only jar files). To match both use: foo;foo/* or foo/*;foo. The order determines what is loaded first.
• The search is NOT recursive
• This appears to be new in Java 6. Oct 14, 2008 at 17:20
• Hey, that's cool--I didn't know about that. That's definitely a helpful option, especially if (as in our case), the classpath is full of jars, many of which are in the same directory. Oct 15, 2008 at 12:43
• But this doesn't provide recursive traversing. Oct 19, 2016 at 10:15
• This seems like a "Link Only Answer". You should provide more details on how to go about that. Dec 12, 2017 at 10:11

# Use An "Argument File" on Java 9+

In Java 9+, the java executable supports providing arguments via a file. See 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. This let’s you to create java commands of any length on any operating system.

In the command line, use the at sign (@) prefix to identify an argument file that contains java options and class names. 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.

This is the "right" solution, if you are running version 9 or above. 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 i.e. it is completely equivalent to simply providing the argument on the command line as usual. 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:

-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 e.g.

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


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. 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.

(disclaimer: I am the author)

(I suppose you do not really mean DOS, but refer to cmd.exe.)

I think it is less a CLASSPATH limitation than an environment size/environment variable size limit. On XP, individual environment variables can be 8k in size, the entire environment is limited to 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. A set command is subject to that restriction. Can it be you have more than 8k worth of directories in your set command? You may be out of luck, then - even if you split them up like Nick Berardi suggested.

• Woops, yeah, old-school is seeping through. Yes, cmd.exe. Oct 14, 2008 at 18:08

Thanks to Raman for introducing a new solution to a pathing problem for Java 9+. I made a hack to bootRun task that allows using everything already evaluated by gradle to run java with argument files. 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

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


• where to add these lines can you explain please Aug 1, 2020 at 15:46
• This goes to build.gradle of spring boot application. Aug 3, 2020 at 12:45

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:\". This way, you will be reducing 4 characters per item in your 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;


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.

• Junction is one front-end for this in NTFS. mklink /D is another, may already be present in later versions of Windows. Dec 16, 2011 at 11:32
• mlink doesn't seem to be included on windows 7. junction is included as part of windows 7(enterprise). Dec 19, 2011 at 7:47

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. First, prior to running the junit tests, you can let a script/ant_task create JARs of the various classes on the classpath. Then you can put the JARs on the classpath, which should be shorter.

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.

As HuibertGill mentions, I would wrap this in an Ant build script just so that you don't have to manage all of this yourself.

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

There was no solution to the issue other than somehow making the classpath shorter by moving the jar files into a folder like "C:\jars".

• Incorrect. There WAS another solution, but you either didn't know what it was, or you decided not to use it. However, what you did was definitely A solution ... that can work in some circumstances. Nov 6, 2016 at 10:53

Fix for windows gradle long classpath issue. Fixes JavaExec tasks that error out with message "CreateProcess error=206, The filename or extension is too long"

Using the plugins DSL:

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


Using legacy plugin application:

buildscript {
repositories {
maven {
}
}
dependencies {
}
}

apply plugin: "com.github.ManifestClasspath"


I had a similar issue here with a giant classpath definition inside a .bat file. 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

and I moved the whole structure to a point like this

c:\test

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%

• We tried a couple variations of this, to no avail. CMD seems to substitute all those %ALT_A%, etc on-the-fly and the final path winds up being too long for it to handle, giving me the same error. Oct 14, 2008 at 18:04
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.5253872275352478, "perplexity": 3630.8864055299787}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2022-33/segments/1659882571210.98/warc/CC-MAIN-20220810191850-20220810221850-00080.warc.gz"}