[RFE] Control Relative Path Resolution

Alan Bateman Alan.Bateman at oracle.com
Tue Feb 12 12:13:10 UTC 2019


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.

-Alan



More information about the jdk-dev mailing list