1 /* Runtime.java -- access to the VM process
2 Copyright (C) 1998, 2002, 2003 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.io
.InputStream
;
42 import java
.io
.IOException
;
43 import java
.io
.OutputStream
;
44 import java
.util
.HashSet
;
45 import java
.util
.Iterator
;
46 import java
.util
.Properties
;
48 import java
.util
.StringTokenizer
;
51 * Runtime represents the Virtual Machine.
54 * @author Eric Blake <ebb9@email.byu.edu>
55 * @status still missing 1.4 functionality
57 // No idea why this class isn't final, since you can't build a subclass!
61 * The library path, to search when loading libraries. We can also safely use
62 * this as a lock for synchronization.
64 private final String
[] libpath
;
67 * The current security manager. This is located here instead of in
68 * System, to avoid security problems, as well as bootstrap issues.
69 * Make sure to access it in a thread-safe manner; it is package visible
70 * to avoid overhead in java.lang.
72 static SecurityManager securityManager
;
75 * The default properties defined by the system. This is likewise located
76 * here instead of in Runtime, to avoid bootstrap issues; it is package
77 * visible to avoid overhead in java.lang. Note that System will add a
78 * few more properties to this collection, but that after that, it is
79 * treated as read-only.
81 * No matter what class you start initialization with, it defers to the
82 * superclass, therefore Object.<clinit> will be the first Java code
83 * executed. From there, the bootstrap sequence, up to the point that
84 * native libraries are loaded (as of March 24, when I traced this
85 * manually) is as follows:
87 * Object.<clinit> uses a String literal, possibly triggering initialization
88 * String.<clinit> calls WeakHashMap.<init>, triggering initialization
89 * AbstractMap, WeakHashMap, WeakHashMap$1 have no dependencies
90 * String.<clinit> calls CaseInsensitiveComparator.<init>, triggering
92 * CaseInsensitiveComparator has no dependencies
93 * Object.<clinit> calls System.loadLibrary, triggering initialization
94 * System.<clinit> calls System.loadLibrary
95 * System.loadLibrary calls Runtime.getRuntime, triggering initialization
96 * Runtime.<clinit> calls Properties.<init>, triggering initialization
97 * Dictionary, Hashtable, and Properties have no dependencies
98 * Runtime.<clinit> calls insertSystemProperties; the VM must make sure
99 * that there are not any harmful dependencies
100 * Runtime.<clinit> calls Runtime.<init>
101 * Runtime.<init> calls StringTokenizer.<init>, triggering initialization
102 * StringTokenizer has no dependencies
103 * System.loadLibrary calls Runtime.loadLibrary
104 * Runtime.loadLibrary should be able to load the library, although it
105 * will probably set off another string of initializations from
108 static Properties defaultProperties
= new Properties();
111 insertSystemProperties(defaultProperties
);
115 * The thread that started the exit sequence. Access to this field must
116 * be thread-safe; lock on libpath to avoid deadlock with user code.
117 * <code>runFinalization()</code> may want to look at this to see if ALL
118 * finalizers should be run, because the virtual machine is about to halt.
120 private Thread exitSequence
;
123 * All shutdown hooks. This is initialized lazily, and set to null once all
124 * shutdown hooks have run. Access to this field must be thread-safe; lock
125 * on libpath to avoid deadlock with user code.
127 private Set shutdownHooks
;
129 /** True if we should finalize on exit. */
130 private boolean finalizeOnExit
;
133 * The one and only runtime instance. This must appear after the default
134 * properties have been initialized by the VM.
136 private static final Runtime current
= new Runtime();
139 * Not instantiable by a user, this should only create one instance.
144 throw new InternalError("Attempt to recreate Runtime");
146 // We don't use libpath in the libgcj implementation. We still
147 // set it to something to allow the various synchronizations to
149 libpath
= new String
[0];
155 * Get the current Runtime object for this JVM. This is necessary to access
156 * the many instance methods of this class.
158 * @return the current Runtime object
160 public static Runtime
getRuntime()
166 * Exit the Java runtime. This method will either throw a SecurityException
167 * or it will never return. The status code is returned to the system; often
168 * a non-zero status code indicates an abnormal exit. Of course, there is a
169 * security check, <code>checkExit(status)</code>.
171 * <p>First, all shutdown hooks are run, in unspecified order, and
172 * concurrently. Next, if finalization on exit has been enabled, all pending
173 * finalizers are run. Finally, the system calls <code>halt</code>.
175 * <p>If this is run a second time after shutdown has already started, there
176 * are two actions. If shutdown hooks are still executing, it blocks
177 * indefinitely. Otherwise, if the status is nonzero it halts immediately;
178 * if it is zero, it blocks indefinitely. This is typically called by
179 * <code>System.exit</code>.
181 * @param status the status to exit with
182 * @throws SecurityException if permission is denied
183 * @see #addShutdownHook(Thread)
184 * @see #runFinalizersOnExit(boolean)
185 * @see #runFinalization()
188 public void exit(int status
)
190 SecurityManager sm
= securityManager
; // Be thread-safe!
192 sm
.checkExit(status
);
193 boolean first
= false;
194 synchronized (libpath
) // Synch on libpath, not this, to avoid deadlock.
196 if (exitSequence
== null)
199 exitSequence
= Thread
.currentThread();
200 if (shutdownHooks
!= null)
202 Iterator i
= shutdownHooks
.iterator();
203 while (i
.hasNext()) // Start all shutdown hooks.
206 ((Thread
) i
.next()).start();
208 catch (IllegalThreadStateException e
)
217 if (shutdownHooks
!= null)
219 // Check progress of all shutdown hooks. As a hook completes,
220 // remove it from the set. If a hook calls exit, it removes
221 // itself from the set, then waits indefinitely on the
222 // exitSequence thread. Once the set is empty, set it to null to
223 // signal all finalizer threads that halt may be called.
224 while (! shutdownHooks
.isEmpty())
227 synchronized (libpath
)
229 hooks
= new Thread
[shutdownHooks
.size()];
230 shutdownHooks
.toArray(hooks
);
232 for (int i
= hooks
.length
; --i
>= 0; )
233 if (! hooks
[i
].isAlive())
234 synchronized (libpath
)
236 shutdownHooks
.remove(hooks
[i
]);
240 exitSequence
.sleep(1); // Give other threads a chance.
242 catch (InterruptedException e
)
244 // Ignore, the next loop just starts sooner.
247 synchronized (libpath
)
249 shutdownHooks
= null;
252 // XXX Right now, it is the VM that knows whether runFinalizersOnExit
253 // is true; so the VM must look at exitSequence to decide whether
254 // this should be run on every object.
258 synchronized (libpath
)
260 if (shutdownHooks
!= null)
262 shutdownHooks
.remove(Thread
.currentThread());
263 status
= 0; // Change status to enter indefinite wait.
267 if (first
|| status
> 0)
274 catch (InterruptedException e
)
276 // Ignore, we've suspended indefinitely to let all shutdown
277 // hooks complete, and to let any non-zero exits through, because
278 // this is a duplicate call to exit(0).
283 * Register a new shutdown hook. This is invoked when the program exits
284 * normally (because all non-daemon threads ended, or because
285 * <code>System.exit</code> was invoked), or when the user terminates
286 * the virtual machine (such as by typing ^C, or logging off). There is
287 * a security check to add hooks,
288 * <code>RuntimePermission("shutdownHooks")<code>.
290 * <p>The hook must be an initialized, but unstarted Thread. The threads
291 * are run concurrently, and started in an arbitrary order; and user
292 * threads or daemons may still be running. Once shutdown hooks have
293 * started, they must all complete, or else you must use <code>halt</code>,
294 * to actually finish the shutdown sequence. Attempts to modify hooks
295 * after shutdown has started result in IllegalStateExceptions.
297 * <p>It is imperative that you code shutdown hooks defensively, as you
298 * do not want to deadlock, and have no idea what other hooks will be
299 * running concurrently. It is also a good idea to finish quickly, as the
300 * virtual machine really wants to shut down!
302 * <p>There are no guarantees that such hooks will run, as there are ways
303 * to forcibly kill a process. But in such a drastic case, shutdown hooks
304 * would do little for you in the first place.
306 * @param hook an initialized, unstarted Thread
307 * @throws IllegalArgumentException if the hook is already registered or run
308 * @throws IllegalStateException if the virtual machine is already in
309 * the shutdown sequence
310 * @throws SecurityException if permission is denied
312 * @see #removeShutdownHook(Thread)
316 public void addShutdownHook(Thread hook
)
318 SecurityManager sm
= securityManager
; // Be thread-safe!
320 sm
.checkPermission(new RuntimePermission("shutdownHooks"));
321 if (hook
.isAlive() || hook
.getThreadGroup() == null)
322 throw new IllegalArgumentException();
323 synchronized (libpath
)
325 if (exitSequence
!= null)
326 throw new IllegalStateException();
327 if (shutdownHooks
== null)
328 shutdownHooks
= new HashSet(); // Lazy initialization.
329 if (! shutdownHooks
.add(hook
))
330 throw new IllegalArgumentException();
335 * De-register a shutdown hook. As when you registered it, there is a
336 * security check to remove hooks,
337 * <code>RuntimePermission("shutdownHooks")<code>.
339 * @param hook the hook to remove
340 * @return true if the hook was successfully removed, false if it was not
341 * registered in the first place
342 * @throws IllegalStateException if the virtual machine is already in
343 * the shutdown sequence
344 * @throws SecurityException if permission is denied
346 * @see #addShutdownHook(Thread)
350 public boolean removeShutdownHook(Thread hook
)
352 SecurityManager sm
= securityManager
; // Be thread-safe!
354 sm
.checkPermission(new RuntimePermission("shutdownHooks"));
355 synchronized (libpath
)
357 if (exitSequence
!= null)
358 throw new IllegalStateException();
359 if (shutdownHooks
!= null)
360 return shutdownHooks
.remove(hook
);
366 * Forcibly terminate the virtual machine. This call never returns. It is
367 * much more severe than <code>exit</code>, as it bypasses all shutdown
368 * hooks and initializers. Use caution in calling this! Of course, there is
369 * a security check, <code>checkExit(status)</code>.
371 * @param status the status to exit with
372 * @throws SecurityException if permission is denied
375 * @see #addShutdownHook(Thread)
377 public void halt(int status
)
379 SecurityManager sm
= securityManager
; // Be thread-safe!
381 sm
.checkExit(status
);
382 exitInternal(status
);
386 * Tell the VM to run the finalize() method on every single Object before
387 * it exits. Note that the JVM may still exit abnormally and not perform
388 * this, so you still don't have a guarantee. And besides that, this is
389 * inherently unsafe in multi-threaded code, as it may result in deadlock
390 * as multiple threads compete to manipulate objects. This value defaults to
391 * <code>false</code>. There is a security check, <code>checkExit(0)</code>.
393 * @param finalizeOnExit whether to finalize all Objects on exit
394 * @throws SecurityException if permission is denied
398 * @deprecated never rely on finalizers to do a clean, thread-safe,
399 * mop-up from your code
401 public static void runFinalizersOnExit(boolean finalizeOnExit
)
403 SecurityManager sm
= securityManager
; // Be thread-safe!
406 current
.finalizeOnExit
= finalizeOnExit
;
410 * Create a new subprocess with the specified command line. Calls
411 * <code>exec(cmdline, null, null)<code>. A security check is performed,
412 * <code>checkExec</code>.
414 * @param cmdline the command to call
415 * @return the Process object
416 * @throws SecurityException if permission is denied
417 * @throws IOException if an I/O error occurs
418 * @throws NullPointerException if cmdline is null
419 * @throws IndexOutOfBoundsException if cmdline is ""
421 public Process
exec(String cmdline
) throws IOException
423 return exec(cmdline
, null, null);
427 * Create a new subprocess with the specified command line and environment.
428 * If the environment is null, the process inherits the environment of
429 * this process. Calls <code>exec(cmdline, env, null)</code>. A security
430 * check is performed, <code>checkExec</code>.
432 * @param cmdline the command to call
433 * @param env the environment to use, in the format name=value
434 * @return the Process object
435 * @throws SecurityException if permission is denied
436 * @throws IOException if an I/O error occurs
437 * @throws NullPointerException if cmdline is null, or env has null entries
438 * @throws IndexOutOfBoundsException if cmdline is ""
440 public Process
exec(String cmdline
, String
[] env
) throws IOException
442 return exec(cmdline
, env
, null);
446 * Create a new subprocess with the specified command line, environment, and
447 * working directory. If the environment is null, the process inherits the
448 * environment of this process. If the directory is null, the process uses
449 * the current working directory. This splits cmdline into an array, using
450 * the default StringTokenizer, then calls
451 * <code>exec(cmdArray, env, dir)</code>. A security check is performed,
452 * <code>checkExec</code>.
454 * @param cmdline the command to call
455 * @param env the environment to use, in the format name=value
456 * @param dir the working directory to use
457 * @return the Process object
458 * @throws SecurityException if permission is denied
459 * @throws IOException if an I/O error occurs
460 * @throws NullPointerException if cmdline is null, or env has null entries
461 * @throws IndexOutOfBoundsException if cmdline is ""
464 public Process
exec(String cmdline
, String
[] env
, File dir
)
467 StringTokenizer t
= new StringTokenizer(cmdline
);
468 String
[] cmd
= new String
[t
.countTokens()];
469 for (int i
= 0; i
< cmd
.length
; i
++)
470 cmd
[i
] = t
.nextToken();
471 return exec(cmd
, env
, dir
);
475 * Create a new subprocess with the specified command line, already
476 * tokenized. Calls <code>exec(cmd, null, null)</code>. A security check
477 * is performed, <code>checkExec</code>.
479 * @param cmd the command to call
480 * @return the Process object
481 * @throws SecurityException if permission is denied
482 * @throws IOException if an I/O error occurs
483 * @throws NullPointerException if cmd is null, or has null entries
484 * @throws IndexOutOfBoundsException if cmd is length 0
486 public Process
exec(String
[] cmd
) throws IOException
488 return exec(cmd
, null, null);
492 * Create a new subprocess with the specified command line, already
493 * tokenized, and specified environment. If the environment is null, the
494 * process inherits the environment of this process. Calls
495 * <code>exec(cmd, env, null)</code>. A security check is performed,
496 * <code>checkExec</code>.
498 * @param cmd the command to call
499 * @param env the environment to use, in the format name=value
500 * @return the Process object
501 * @throws SecurityException if permission is denied
502 * @throws IOException if an I/O error occurs
503 * @throws NullPointerException if cmd is null, or cmd or env has null
505 * @throws IndexOutOfBoundsException if cmd is length 0
507 public Process
exec(String
[] cmd
, String
[] env
) throws IOException
509 return exec(cmd
, env
, null);
513 * Create a new subprocess with the specified command line, already
514 * tokenized, and the specified environment and working directory. If the
515 * environment is null, the process inherits the environment of this
516 * process. If the directory is null, the process uses the current working
517 * directory. A security check is performed, <code>checkExec</code>.
519 * @param cmd the command to call
520 * @param env the environment to use, in the format name=value
521 * @param dir the working directory to use
522 * @return the Process object
523 * @throws SecurityException if permission is denied
524 * @throws IOException if an I/O error occurs
525 * @throws NullPointerException if cmd is null, or cmd or env has null
527 * @throws IndexOutOfBoundsException if cmd is length 0
530 public Process
exec(String
[] cmd
, String
[] env
, File dir
)
533 SecurityManager sm
= securityManager
; // Be thread-safe!
535 sm
.checkExec(cmd
[0]);
536 return execInternal(cmd
, env
, dir
);
540 * Returns the number of available processors currently available to the
541 * virtual machine. This number may change over time; so a multi-processor
542 * program want to poll this to determine maximal resource usage.
544 * @return the number of processors available, at least 1
546 public native int availableProcessors();
549 * Find out how much memory is still free for allocating Objects on the heap.
551 * @return the number of bytes of free memory for more Objects
553 public native long freeMemory();
556 * Find out how much memory total is available on the heap for allocating
559 * @return the total number of bytes of memory for Objects
561 public native long totalMemory();
564 * Returns the maximum amount of memory the virtual machine can attempt to
565 * use. This may be <code>Long.MAX_VALUE</code> if there is no inherent
566 * limit (or if you really do have a 8 exabyte memory!).
568 * @return the maximum number of bytes the virtual machine will attempt
571 public native long maxMemory();
574 * Run the garbage collector. This method is more of a suggestion than
575 * anything. All this method guarantees is that the garbage collector will
576 * have "done its best" by the time it returns. Notice that garbage
577 * collection takes place even without calling this method.
579 public native void gc();
582 * Run finalization on all Objects that are waiting to be finalized. Again,
583 * a suggestion, though a stronger one than {@link #gc()}. This calls the
584 * <code>finalize</code> method of all objects waiting to be collected.
588 public native void runFinalization();
591 * Tell the VM to trace every bytecode instruction that executes (print out
592 * a trace of it). No guarantees are made as to where it will be printed,
593 * and the VM is allowed to ignore this request.
595 * @param on whether to turn instruction tracing on
597 public native void traceInstructions(boolean on
);
600 * Tell the VM to trace every method call that executes (print out a trace
601 * of it). No guarantees are made as to where it will be printed, and the
602 * VM is allowed to ignore this request.
604 * @param on whether to turn method tracing on
606 public native void traceMethodCalls(boolean on
);
609 * Load a native library using the system-dependent filename. This is similar
610 * to loadLibrary, except the only name mangling done is inserting "_g"
611 * before the final ".so" if the VM was invoked by the name "java_g". There
612 * may be a security check, of <code>checkLink</code>.
614 * @param filename the file to load
615 * @throws SecurityException if permission is denied
616 * @throws UnsatisfiedLinkError if the library is not found
618 public void load(String filename
)
620 SecurityManager sm
= securityManager
; // Be thread-safe!
622 sm
.checkLink(filename
);
623 _load(filename
, false);
627 * Load a native library using a system-independent "short name" for the
628 * library. It will be transformed to a correct filename in a
629 * system-dependent manner (for example, in Windows, "mylib" will be turned
630 * into "mylib.dll"). This is done as follows: if the context that called
631 * load has a ClassLoader cl, then <code>cl.findLibrary(libpath)</code> is
632 * used to convert the name. If that result was null, or there was no class
633 * loader, this searches each directory of the system property
634 * <code>java.library.path</code> for a file named
635 * <code>System.mapLibraryName(libname)</code>. There may be a security
636 * check, of <code>checkLink</code>.
638 * @param filename the file to load
639 * @throws SecurityException if permission is denied
640 * @throws UnsatisfiedLinkError if the library is not found
641 * @see System#mapLibraryName(String)
642 * @see ClassLoader#findLibrary(String)
644 public void loadLibrary(String libname
)
646 // This is different from the Classpath implementation, but I
647 // believe it is more correct.
648 SecurityManager sm
= securityManager
; // Be thread-safe!
650 sm
.checkLink(libname
);
651 _load(libname
, true);
655 * Return a localized version of this InputStream, meaning all characters
656 * are localized before they come out the other end.
658 * @param in the stream to localize
659 * @return the localized stream
660 * @deprecated <code>InputStreamReader</code> is the preferred way to read
663 public InputStream
getLocalizedInputStream(InputStream in
)
669 * Return a localized version of this OutputStream, meaning all characters
670 * are localized before they are sent to the other end.
672 * @param out the stream to localize
673 * @return the localized stream
674 * @deprecated <code>OutputStreamWriter</code> is the preferred way to write
677 public OutputStream
getLocalizedOutputStream(OutputStream out
)
683 * Native method that actually shuts down the virtual machine.
685 * @param status the status to end the process with
687 native void exitInternal(int status
);
690 * Load a file. If it has already been loaded, do nothing. The name has
691 * already been mapped to a true filename.
693 * @param filename the file to load
694 * @param do_search True if we should search the load path for the file
696 native void _load(String filename
, boolean do_search
);
699 *This is a helper function for the ClassLoader which can load
700 * compiled libraries. Returns true if library (which is just the
701 * base name -- path searching is done by this function) was loaded,
704 native boolean loadLibraryInternal(String libname
);
707 * A helper for the constructor which does some internal native
710 private native void init ();
713 * Map a system-independent "short name" to the full file name, and append
715 * XXX This method is being replaced by System.mapLibraryName.
717 * @param pathname the path
718 * @param libname the short version of the library name
719 * @return the full filename
721 static native String
nativeGetLibname(String pathname
, String libname
);
724 * Execute a process. The command line has already been tokenized, and
725 * the environment should contain name=value mappings. If directory is null,
726 * use the current working directory; otherwise start the process in that
729 * @param cmd the non-null command tokens
730 * @param env the non-null environment setup
731 * @param dir the directory to use, may be null
732 * @return the newly created process
733 * @throws NullPointerException if cmd or env have null elements
735 native Process
execInternal(String
[] cmd
, String
[] env
, File dir
);
738 * Get the system properties. This is done here, instead of in System,
739 * because of the bootstrap sequence. Note that the native code should
740 * not try to use the Java I/O classes yet, as they rely on the properties
741 * already existing. The only safe method to use to insert these default
742 * system properties is {@link Properties#setProperty(String, String)}.
744 * <p>These properties MUST include:
746 * <dt>java.version <dd>Java version number
747 * <dt>java.vendor <dd>Java vendor specific string
748 * <dt>java.vendor.url <dd>Java vendor URL
749 * <dt>java.home <dd>Java installation directory
750 * <dt>java.vm.specification.version <dd>VM Spec version
751 * <dt>java.vm.specification.vendor <dd>VM Spec vendor
752 * <dt>java.vm.specification.name <dd>VM Spec name
753 * <dt>java.vm.version <dd>VM implementation version
754 * <dt>java.vm.vendor <dd>VM implementation vendor
755 * <dt>java.vm.name <dd>VM implementation name
756 * <dt>java.specification.version <dd>Java Runtime Environment version
757 * <dt>java.specification.vendor <dd>Java Runtime Environment vendor
758 * <dt>java.specification.name <dd>Java Runtime Environment name
759 * <dt>java.class.version <dd>Java class version number
760 * <dt>java.class.path <dd>Java classpath
761 * <dt>java.library.path <dd>Path for finding Java libraries
762 * <dt>java.io.tmpdir <dd>Default temp file path
763 * <dt>java.compiler <dd>Name of JIT to use
764 * <dt>java.ext.dirs <dd>Java extension path
765 * <dt>os.name <dd>Operating System Name
766 * <dt>os.arch <dd>Operating System Architecture
767 * <dt>os.version <dd>Operating System Version
768 * <dt>file.separator <dd>File separator ("/" on Unix)
769 * <dt>path.separator <dd>Path separator (":" on Unix)
770 * <dt>line.separator <dd>Line separator ("\n" on Unix)
771 * <dt>user.name <dd>User account name
772 * <dt>user.home <dd>User home directory
773 * <dt>user.dir <dd>User's current working directory
776 * @param p the Properties object to insert the system properties into
778 static native void insertSystemProperties(Properties p
);