JDK-4045688 : Add chdir or equivalent notion of changing working directory
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.1.1,1.1.5,1.2.0,1.3.0,1.3.1,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS:
    generic,linux,solaris_2.5.1,solaris_2.6,windows_95 generic,linux,solaris_2.5.1,solaris_2.6,windows_95
  • CPU: generic,x86,sparc
  • Submitted: 1997-04-17
  • Updated: 2008-08-18
  • Resolved: 2008-08-18
Related Reports
Duplicate :  
Relates :  
RFE for Java runtime environment to support chdir() [or similar]

Part 1/2:

 >Subject: trying to change directory in java
 >From: Alec Muffett <###@###.###>
 >Date: 02 Apr 1997 20:19:59 +0100
 >The attached below is an attempt we've been doing to implement some
 >sort of chdir mechanism in Java; we're not certain if that is even
 >possible (perhaps the JVM thinks directories are too complex a notion
 >to be portable?) but some of the documentation we've been reading
 >seems to imply that setting the "user.dir" element of System
 >properties should have an effect on the current working directory of
 >the running VM...
 >However - it don't work.
 >Could someone wiser than I possibly please comment on why this is
 >failing, and whether we're barking up the wrong tree?
 >        - alec


Part 2/2:

 Alec Muffett <###@###.###> writes:
 >Roland Schemers <###@###.###> writes:
 >>>>   // set the properties for user.dir
 >>>>   newprops.put("user.dir", "/etc");
 >>>>   System.setProperties(newprops);
 >>You are barking up the wrong tree :-) All setProperties does is
 >>replace one Properties object with another.
 >We suspected as much, but some aspect of the documentation we were
 >reading seemed to imply that it might work, and there didn't seem to
 >be any alternative.
 >>It doesn't do anything
 >>special. As far as I know, there is no "chdir" in the standard java.*
 >>APIs. I don't know if this was intential or not.
 >Possibly intentional, after all the language is designed to target the
 >lowest common denominators of hardware (Game-Boys?) which probably
 >don't have directories, and it would probavly interfere with the
 >threading mechanism.
 >As it is it looks like we have to write error-prone code that has lots
 >of hardwired pathnames in it if we want to do things "The Java Way" (TM).
 >It wouldn't be so bad even, if (say) one of the systems properties was
 >a string which got prefixed onto the start of all filename fetches for
 >you automatically, as part of java.io.*.
 >Admittedly, you'll thrash the kernel inode cache a lot when you start
 >traversing the four-layer-deep, multiply-128-directory-wide tree of
 >some 35,000 subdirectories and 250,000 files; but at least the code
 >will be simpler; anyway, that's what you have to expect from
 >object-oriented programs which hide functionality from you.
 >Remind me to tell you the story sometime of the student who implemented
 >an array class using singly-linked-lists, remalloc(), and linear
 >searching, when someone used it to create a 100,000 element array and
 >qsort()ed it on the university mainframe back in '89.
 >PS: *NO*, I do not want to have to create a superclass of my own to
 >provide this functionality; as a serious applications/system programmer,
 >I want it to be there, for me, when I am coding, and I do not want to
 >have to overlay system-supplied functions in order to get them provide
 >functionality that's been in every major O/S since 1982.
 >Is anyone out there from Javasoft, listening?
 >   - alec
 >ps: this functionality [traversing enormous directory structures] 
 >is NOT an unreasonable requirement for an application
 >program, as anyone who briefly considers the operation of the Unix
 >"find" command and how it works, will realise.
 >Now, wouldn't it be nice if Java was suitable for writing generic
 >forms of some really useful tools...
###@###.### 10/15/04 20:41 GMT

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 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 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 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 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 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 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