[RFE] Control Relative Path Resolution

Robert Scholte rfscholte at apache.org
Tue Feb 12 20:18:53 UTC 2019

On Tue, 12 Feb 2019 13:13:10 +0100, Alan Bateman <Alan.Bateman at oracle.com>  

> On 12/02/2019 07:26, Robert Scholte wrote:
>> Recently an interesting change has been applied to the codebase of the  
>> JDK: Several predefined System properties are now read-only. This makes  
>> the runtime more robust, so we consider this as a great improvement.
> Just to put a bit more context on this. Java SE defines a number of  
> system properties such as java.home and user.dir that provide  
> information about the runtime and the environment. These system  
> properties were never intended to be changed in a running VM but this  
> read-only-ness never enforced (and it still not enforced). Needless to  
> say, code that changes these properties in a running VM creates massive  
> potential for breakage. The recent change that you mention is to improve  
> the robustness of code in java.base by not reading the values of these  
> system properties after startup. If a library changes the value of  
> java.home (and we have seen cases of this) then it will not impact APIs  
> in java.base that are dependent on the location of the runtime. Ideally  
> we should go further and prevent critical system properties from being  
> changed but this is not easy to do after 20+ years of no enforcement.
>> However, this introduces a new challenge, in this case regarding the  
>> system property 'user.dir', since it has different purposes. Some Maven  
>> plugins change this value in some cases as it is the only way to  
>> control the resolution of relative paths. Being able to change the  
>> "working directory" gives several interesting benefits, which should  
>> not impact other usages of user.dir.
> Java SE and the JDK have no support for the equivalent of chdir, it's  
> not clear how such a feature could work reliably in a multi-threaded  
> environment. We have seen attempts by containers to support multiple  
> tenants with different working directories but there are issues and  
> holes in all attempts that I have seen.
>> :
>> # In practice
>> What we also see is that people are having problems understanding  
>> inputstreams. The following codefragments we see quite often:
>> File f = new File( "src/test/resources/README.md" );
>> FileReader is = new FileReader( f );
> This seems like a case where the test runner should make available the  
> src location. We use jtreg for JDK tests and it sets test.src so that  
> tests can locate files in the test source tree if they need it. I  
> understand SureFire sets basedir to the directory containing the POM but  
> maybe it needs to set additional properties for tests (if it does then  
> the IDEs would need to create the same environment). For the scenario  
> then an alternative argument is that resources needed by the tests  
> should be copied to the output directory with the test classes and other  
> resources.
>> Knowing that files under src/test/resources end up on the classpath,  
>> this is the preferred solution:
>> InputStream is = MyClass.class.getResourceAsStream("/README.md");
> This will locate the resource relative to MyClass.class, as in  
> target/classes or in root directory of the JAR file if packaged. That  
> said, I suspect many developers can't distinguish file paths from  
> resource names (SO seems to be littered with examples of this).
>> However, others feel more comfortable with URLs and Files, resulting in:
>> URL url = MyClass.class.getResource("/README.md");
>> File f = url.getFile();
> I don't expect this will compile but I think your point is that  
> developers will often make the mistake of using a URL path component as  
> a file path. This is a big hazard. An API note was added to both URI and  
> URL recently to show how to convert file URIs to file paths and it  
> remains to be seen if that helps, it might be that URL::getFile and a  
> few more should be deprecated as they are named in a way that tempts  
> developers to use them the wrong way.
>> :
>> The Java community would benefit if the JDK would specify 1 *mutable*  
>> System property to control the basedir of a File. This property would  
>> default to the value of 'user.dir' to keep the current behavior. With  
>> this there is exactly 1 way for all to adjust the resolution of  
>> relative paths.
>> This would make it possible to remain the original behavior (users  
>> don't have to change their code) and to make the JDK more robust by  
>> keeping user.dir read-only.
> This has the same issues as user.dir. Is there any way to get Surefire,  
> or whatever plugin is executing the test runner, to create system  
> properties so that tests can locate files in the test source or target  
> locations? I understand they have "basedir" today but this doesn't seem  
> to be enough.

Assuming this can be solved without forcing a new JVM to start, we need  
something like
  File f = new File( System.property( "file.basedir", ""), "a/b/c" );

Here it is explicit done by the developer, but I would like to see it  
implicit, where the System.property( "file.basedir", "") is added by the  
java.io.File implementation in case the File is relative. To me explicit  
and implicit have the same result, hence I prefer implicit.
This will remove the boiler template and it introduces a predefined name  
for the property, so that tools, IDEs and execution frameworks don't have  
to decide which property to choose.

This should keep the behavior as (un)reliable as it used to be, but with  
the extra property you can give control and responsibility to the  

Another conclusion could be that new File( System.property(  
"file.basedir", ""), "a/b/c" ) will never work due to the multithreading  

I don't know how this is implemented in Surefire, but what I do know is  
that I can't remember seeing issues about this over the last decade:  
adjusting the user.dir has worked for us for a long time (as this was the  
only way to adjust the relative path resolution)


> -Alan

More information about the jdk-dev mailing list