[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