EVALUATION
In January 2006 we were able to identify only one potential customer who could did not find any of our existing solutions satisfactory. After getting a complete description of their constraints, we determined that one of the design solutions outlined above would solve most of their problem. This feature was eventually shelved because that customer had a workaround and when they learned that implemention on the jdk side would still not solve their windows problem (due to constraints imposed by that OS), they lost interest.
Since that time, no further customers have come forward or were otherwise identified. Given the huge amount of work required to implement this feature, our limited resources, the apparent little customer demand, and the compatibility and safety concerns of existing proposals, we have decided to close this RFE as "will not fix".
|
|
|
EVALUATION
First of all, there seems to be some confusion about the purpose of "user.dir". "user.dir" should be viewed as a read-only property; portions of our implementation of the jdk assume that "user.dir" will not change. It is possible that other implemenations may not make this assumption so it would be difficult to restrict the expected use of this system property in the spec. Secondly, although it is possible to write JNI code which makes a native call to change the working directory for the entire process, this is not something that we can prevent. However, we consider this an unsafe operation and do not recommend its use.
Many SDN comments request the ability to launch a new process in a different directory. It seems that a number of scenarios are addressed by some recent additions. In jdk1.3 (Kestrel) we introduced the following method:
public Process exec(String[] cmdarray, String[] envp, File dir);
where "dir" is the working directory of the process to be launched. In jdk5.0 (Tiger) we added ProcessBuilder which allows the user to manage a collection of process attributes including the working directory for new processes.
It would be very difficult for us to modify the existing behaviour of java.io.File without introducing compatibility problems. For this class, we can probably examine the current specification and modify it to more clearly describe the current behaviour with respect to "user.dir".
With respect to the request for chdir-like functionality within the current VM, we are considering a few possible solutions.
- A thread-local variable representing the current working directory.
- A true process-wide "chdir" which would probably required careful
specification and recommendations for its use, especially for
multi-threaded apps. We would also have to scrub the existing jdk code
for any sections that would be sensitive to such a change, even when
properly used by the application.
It is possible that we may decide on another solution or even conclude that there is no solution which will achieve adequate safety and compatibility. Our team is resolved to investigate these possibilities for the next feature release, jdk7 (Dolphin).
|
|
|
EVALUATION
Much of the cause for the original requests for chdir were made moot
by the addition of Runtime.exec methods taking a current directory argument
in JDK 1.3. If you really need some Java code running in another directory,
simply start up another JDK process using ProcessBuilder or Runtime.exec().
|
|
|
EVALUATION
From
http://lwn.net/Articles/164887/
(note especially the word "race-free")
Ulrich Drepper, the maintainer of glibc, isn't just trying to add a system call; his proposal creates eleven of them. They are all variants on current file operations:
int mknodat(int dfd, const char *pathname, mode_t mode, dev_t dev);
int mkdirat(int dfd, const char *pathname, mode_t mode);
int unlinkat(int dfd, const char *pathname);
int symlinkat(const char *oldname, int newdfd, const char *newname);
int linkat(int olddfd, const char *oldname,
int newdfd, const char *newname);
int renameat(int olddfd, const char *oldname,
int newdfd, const char *newname);
int utimesat(int dfd, const char *filename, struct timeval *tvp);
int chownat(int dfd, const char *path, uid_t owner, gid_t group);
int openat(int dfd, const char *filename, int flags, int mode);
int newfstatat(int dfd, char *filename, struct stat *buf, int flag);
int readlinkat(int dfd, const char *pathname, char *buf, int size);
The pattern should be clear by now: each new system call extends an existing one by adding one or more "dfd" (default file descriptor) arguments. In each case, the new argument indicates a directory which is used instead of the current working directory when relative path names are provided. These calls can help applications work their way through directory trees in a race-free manner, and are also useful for implementing a virtual per-thread working directory.
|
|
|
EVALUATION
Ruby is another application platform that embraces threading and has a
process-wide chdir. In the latest ruby release, a warning is issued if
chdir is used in a program with more than one active thread.
|
|
|
EVALUATION
Paul Eggert wrote:
Jim Meyering wrote:
> It's really too bad that there is no system interface that allows a
> program to save and restore the current working directory reliably
Actually, there is such an interface: it's the AT_FDCWD interface
of Solaris 9 and later. (Great minds think alike, huh?) It comes
with new system calls like openat and fstatat.
|
|
|
EVALUATION
Here are my personal recommendations:
- It is contrary to the safety-first principle of Java to have a chdir that
affects all threads in the JVM.
- We should not try to solve the "current directory locked on Windows" problem.
- A chdir that has inheritable thread local semantics is much safer and
clearly useful, but it is quite an implementation challenge. A high-quality
implementation might look completely different on Solaris, Linux, and Windows.
- If we implement chdir, consistency would seem to demand we implement
mutable versions of other per-process state such as environment variables.
- We should accept that Java is now a very stable platform and that it may
be too late to add global mutable process state. Immutability is in itself a feature.
|
|
|
EVALUATION
This feature can be interpreted in two ways: chdir could change the current
working directory of the process containing the JVM, causing all threads to
change simultaneously, or to provide a more "virtual" per-thread concept of
current directory, which could conceptually be a ThreadLocal. This would
be merely a convenience for building up complete path names to pass to the
underlying operating system API. This is how the current directory works
in Emacs - it's just a variable, but a magic one that can have buffer-local
values. Emacs buffers are kinda sorta like Java threads in this sense.
Such an implementation would offer convenience and safety.
Having each thread with a ThreadLocal current directory gives a programmer
experience familiar to old Unix greybeards, except that Threads replace Processes.
|
|
|
EVALUATION
This needs co-operation from the runtime (if we chdir() the VM, then the
IO libariries would get transparently updated). At this point it is not
clear what this means for the VM (which opens its libraries and classes
with relative path names). Assigning to runtime so the VM can be made
chdir() safe first before we add a trivial API to do this.
anand.palaniswamy@Eng 1997-11-07
This is primarily an I/O architecture issue, not a runtime issue.
Introducing a straight chdir-like call will add one more piece of mutable
global state, i.e., one more way for a multithreaded program to go awry, as
well as introduce incompatibilities. At present, for example, an instance of
java.io.File that contains a relative pathname always has the same meaning.
With a chdir call, this invariant would no longer be true.
Having said that, the efficiency problem for a certain small class of systems
programs is quite real. This could be addressed in a future release by
introducing the notion of a "hot" working directory as a perforamnce hint to
the internal filesystem interface. This would require tweaking the
java.io.File API so that relative pathnames are always resolved against the
value of the "user.dir" property.
-- mr@eng 11/10/1997
|
|
|
|