Gradle and changes to application class loader in Java 9.

Peter Levart peter.levart at gmail.com
Mon Apr 27 10:19:49 UTC 2015



On 04/23/2015 06:18 AM, Luke Daley wrote:
> Hi all,
>
> I’ve been asked (by Alan Bateman) to move the discussion that started @ https://discuss.gradle.org/t/classcastexception-from-org-gradle-process-internal-child-bootstrapsecuritymanager/2443 and then moved to email due to technical reasons to this list.
>
> In summary, the way that Gradle mitigates the command line length limit when forking build processes breaks with 9. Mandy Chung’s original post at the link above describes why this breaks.
>
> The suggested alternative to the current “trick” of injecting into the application class loader via the security manager is to use a jar with a classpath attribute, thereby reducing the command line length. Gradle has been down this route before, but it broke some tools. One that we have a record of is GWT-Test (https://issues.gradle.org/browse/GRADLE-2223). It will potentially break anything that inspects `java.class.path` or that does the equivalent by `getURLs()` on the application class loader.
>
> We don’t really know what the practical impact of this change would be today, but aren’t willing to risk the breaking change to our existing users on < 9. Therefore, in lieu of options file support in 9, our intention is to use the classpath manifest jar approach only on 9. If our users are using any tools that rely on `java.class.path` they may be blocked from moving to 9.
>
> We are intending to make this change “soon”.
>
>>
> Join us for Gradle Summit 2015, June 11 - 12 in Santa Clara, CA: http://www.gradlesummit.com

Hi,

I think it would be nice to be able to spawn a Java subprocess and set 
it's system properties to huge strings without creating temporary files 
to communicate that information.

From: 
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653%28v=vs.85%29.aspx 


"The maximum size of a user-defined environment variable is 32,767 
characters. There is no technical limitation on the size of the 
environment block. However, there are practical limits depending on the 
mechanism used to access the block. For example, a batch file cannot set 
a variable that is longer than the maximum command line length. Windows 
Server 2003 and Windows XP:  The maximum size of the environment block 
for the process is 32,767 characters. Starting with Windows Vista and 
Windows Server 2008, there is no technical limitation on the size of the 
environment block."

I believe UNIXes have much larger limits for environment variables. So 
why not use environment variables to overcome command-line limits?

In case of gradle, I assume it is spawning subprocesses via 
java.lang.Process API right? Therefore there is no CMD.EXE limitation 
there. But 32k per environment variable might still be to small to stuff 
the entire class path into a single variable. So what about a scheme 
where "-Dsystem.property=value" syntax was enhanced to support 
"expansion" from environment variables. For example:

-Djava.class.path=/some/dir/some.jar:${env:CP1}:${env:CP2}:${env:CP3}

with environment variables defined as:

CP1=/some/dir1/some1.jar
CP2=/some/dir2/some2.jar
CP3=/some/dir3/some3.jar

...the above JVM argument would set java.class.path to:

/some/dir/some.jar:/some/dir1/some1.jar:/some/dir2/some2.jar:/some/dir3/some3.jar

Environment variables in JVM are admittedly lazily initialized when the 
program needs them (System.getenv()) and JVM boot-up sequence does not, 
currently. But in this scheme they would only be initialized during 
boot-up if any "-Dprop=value" contained the value with expansion syntax, 
so normally they would not be. There is some danger that some 
application already uses the ${env:XXX} syntax for it's own purposes, 
but for JDK9 I think, this could be tolerated.

The patch to introduce this is quite simple:

http://cr.openjdk.java.net/~plevart/jdk9-dev/SystemProperties.EnvExpansion/webrev.01/


When there's no expansion syntax used in system properties, the boot-up 
sequence amounts to loading just the following additional class:

+ [Loaded java.util.Hashtable$KeySet from java/util/Hashtable$KeySet.class]

When there is expansion syntax used in some system property, it 
additionally loads just the following:

+ [Loaded java.lang.ProcessEnvironment$ExternalData from 
java/lang/ProcessEnvironment$ExternalData.class]
+ [Loaded java.lang.ProcessEnvironment from 
java/lang/ProcessEnvironment.class]
+ [Loaded java.lang.ProcessEnvironment$StringEnvironment from 
java/lang/ProcessEnvironment$StringEnvironment.class]
+ [Loaded java.lang.ProcessEnvironment$Value from 
java/lang/ProcessEnvironment$Value.class]
+ [Loaded java.lang.ProcessEnvironment$Variable from 
java/lang/ProcessEnvironment$Variable.class]
+ [Loaded java.util.Collections$UnmodifiableMap from 
java/util/Collections$UnmodifiableMap.class]


What do you say?

Regards, Peter



More information about the jigsaw-dev mailing list