1 /* System.java -- useful methods to interface with the system
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2012
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU Classpath.
6 
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26 
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38 
39 
40 package java.lang;
41 
42 import gnu.classpath.SystemProperties;
43 import gnu.classpath.VMStackWalker;
44 
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.PrintStream;
48 import java.io.Console;
49 import java.nio.channels.Channel;
50 import java.nio.channels.spi.SelectorProvider;
51 import java.util.AbstractCollection;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.HashMap;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.Map;
58 import java.util.Set;
59 import java.util.Properties;
60 import java.util.PropertyPermission;
61 
62 /**
63  * System represents system-wide resources; things that represent the
64  * general environment.  As such, all methods are static.
65  *
66  * @author John Keiser
67  * @author Eric Blake (ebb9@email.byu.edu)
68  * @since 1.0
69  * @status still missing 1.4 functionality
70  */
71 public final class System
72 {
73   // WARNING: System is a CORE class in the bootstrap cycle. See the comments
74   // in vm/reference/java/lang/Runtime for implications of this fact.
75 
76   /**
77    * The standard InputStream. This is assigned at startup and starts its
78    * life perfectly valid. Although it is marked final, you can change it
79    * using {@link #setIn(InputStream)} through some hefty VM magic.
80    *
81    * <p>This corresponds to the C stdin and C++ cin variables, which
82    * typically input from the keyboard, but may be used to pipe input from
83    * other processes or files.  That should all be transparent to you,
84    * however.
85    */
86   public static final InputStream in = VMSystem.makeStandardInputStream();
87 
88   /**
89    * The standard output PrintStream.  This is assigned at startup and
90    * starts its life perfectly valid. Although it is marked final, you can
91    * change it using {@link #setOut(PrintStream)} through some hefty VM magic.
92    *
93    * <p>This corresponds to the C stdout and C++ cout variables, which
94    * typically output normal messages to the screen, but may be used to pipe
95    * output to other processes or files.  That should all be transparent to
96    * you, however.
97    */
98   public static final PrintStream out = VMSystem.makeStandardOutputStream();
99 
100   private static final String LINE_SEPARATOR = SystemProperties.getProperty("line.separator");
101 
102   /**
103    * The standard output PrintStream.  This is assigned at startup and
104    * starts its life perfectly valid. Although it is marked final, you can
105    * change it using {@link #setErr(PrintStream)} through some hefty VM magic.
106    *
107    * <p>This corresponds to the C stderr and C++ cerr variables, which
108    * typically output error messages to the screen, but may be used to pipe
109    * output to other processes or files.  That should all be transparent to
110    * you, however.
111    */
112   public static final PrintStream err = VMSystem.makeStandardErrorStream();
113 
114   /**
115    * A cached copy of the environment variable map.
116    */
117   private static Map<String,String> environmentMap;
118 
119   /**
120    * This class is uninstantiable.
121    */
System()122   private System()
123   {
124   }
125 
126   /**
127    * Set {@link #in} to a new InputStream. This uses some VM magic to change
128    * a "final" variable, so naturally there is a security check,
129    * <code>RuntimePermission("setIO")</code>.
130    *
131    * @param in the new InputStream
132    * @throws SecurityException if permission is denied
133    * @since 1.1
134    */
setIn(InputStream in)135   public static void setIn(InputStream in)
136   {
137     SecurityManager sm = SecurityManager.current; // Be thread-safe.
138     if (sm != null)
139       sm.checkPermission(new RuntimePermission("setIO"));
140 
141     VMSystem.setIn(in);
142   }
143 
144   /**
145    * Set {@link #out} to a new PrintStream. This uses some VM magic to change
146    * a "final" variable, so naturally there is a security check,
147    * <code>RuntimePermission("setIO")</code>.
148    *
149    * @param out the new PrintStream
150    * @throws SecurityException if permission is denied
151    * @since 1.1
152    */
setOut(PrintStream out)153   public static void setOut(PrintStream out)
154   {
155     SecurityManager sm = SecurityManager.current; // Be thread-safe.
156     if (sm != null)
157       sm.checkPermission(new RuntimePermission("setIO"));
158     VMSystem.setOut(out);
159   }
160 
161   /**
162    * Set {@link #err} to a new PrintStream. This uses some VM magic to change
163    * a "final" variable, so naturally there is a security check,
164    * <code>RuntimePermission("setIO")</code>.
165    *
166    * @param err the new PrintStream
167    * @throws SecurityException if permission is denied
168    * @since 1.1
169    */
setErr(PrintStream err)170   public static void setErr(PrintStream err)
171   {
172     SecurityManager sm = SecurityManager.current; // Be thread-safe.
173     if (sm != null)
174       sm.checkPermission(new RuntimePermission("setIO"));
175     VMSystem.setErr(err);
176   }
177 
178   /**
179    * Set the current SecurityManager. If a security manager already exists,
180    * then <code>RuntimePermission("setSecurityManager")</code> is checked
181    * first. Since this permission is denied by the default security manager,
182    * setting the security manager is often an irreversible action.
183    *
184    * <STRONG>Spec Note:</STRONG> Don't ask me, I didn't write it.  It looks
185    * pretty vulnerable; whoever gets to the gate first gets to set the policy.
186    * There is probably some way to set the original security manager as a
187    * command line argument to the VM, but I don't know it.
188    *
189    * @param sm the new SecurityManager
190    * @throws SecurityException if permission is denied
191    */
setSecurityManager(SecurityManager sm)192   public static synchronized void setSecurityManager(SecurityManager sm)
193   {
194     // Implementation note: the field lives in SecurityManager because of
195     // bootstrap initialization issues. This method is synchronized so that
196     // no other thread changes it to null before this thread makes the change.
197     if (SecurityManager.current != null)
198       SecurityManager.current.checkPermission
199         (new RuntimePermission("setSecurityManager"));
200 
201     // java.security.Security's class initialiser loads and parses the
202     // policy files.  If it hasn't been run already it will be run
203     // during the first permission check.  That initialisation will
204     // fail if a very restrictive security manager is in force, so we
205     // preload it here.
206     if (SecurityManager.current == null)
207       {
208         try
209           {
210             Class.forName("java.security.Security");
211           }
212         catch (ClassNotFoundException e)
213           {
214           }
215       }
216 
217     SecurityManager.current = sm;
218   }
219 
220   /**
221    * Get the current SecurityManager. If the SecurityManager has not been
222    * set yet, then this method returns null.
223    *
224    * @return the current SecurityManager, or null
225    */
getSecurityManager()226   public static SecurityManager getSecurityManager()
227   {
228     return SecurityManager.current;
229   }
230 
231   /**
232    * Get the current time, measured in the number of milliseconds from the
233    * beginning of Jan. 1, 1970. This is gathered from the system clock, with
234    * any attendant incorrectness (it may be timezone dependent).
235    *
236    * @return the current time
237    * @see java.util.Date
238    */
currentTimeMillis()239   public static long currentTimeMillis()
240   {
241     return VMSystem.currentTimeMillis();
242   }
243 
244   /**
245    * <p>
246    * Returns the current value of a nanosecond-precise system timer.
247    * The value of the timer is an offset relative to some arbitrary fixed
248    * time, which may be in the future (making the value negative).  This
249    * method is useful for timing events where nanosecond precision is
250    * required.  This is achieved by calling this method before and after the
251    * event, and taking the difference betweent the two times:
252    * </p>
253    * <p>
254    * <code>long startTime = System.nanoTime();</code><br />
255    * <code>... <emph>event code</emph> ...</code><br />
256    * <code>long endTime = System.nanoTime();</code><br />
257    * <code>long duration = endTime - startTime;</code><br />
258    * </p>
259    * <p>
260    * Note that the value is only nanosecond-precise, and not accurate; there
261    * is no guarantee that the difference between two values is really a
262    * nanosecond.  Also, the value is prone to overflow if the offset
263    * exceeds 2^63.
264    * </p>
265    *
266    * @return the time of a system timer in nanoseconds.
267    * @since 1.5
268    */
nanoTime()269   public static long nanoTime()
270   {
271     return VMSystem.nanoTime();
272   }
273 
274   /**
275    * Copy one array onto another from <code>src[srcStart]</code> ...
276    * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ...
277    * <code>dest[destStart+len-1]</code>. First, the arguments are validated:
278    * neither array may be null, they must be of compatible types, and the
279    * start and length must fit within both arrays. Then the copying starts,
280    * and proceeds through increasing slots.  If src and dest are the same
281    * array, this will appear to copy the data to a temporary location first.
282    * An ArrayStoreException in the middle of copying will leave earlier
283    * elements copied, but later elements unchanged.
284    *
285    * @param src the array to copy elements from
286    * @param srcStart the starting position in src
287    * @param dest the array to copy elements to
288    * @param destStart the starting position in dest
289    * @param len the number of elements to copy
290    * @throws NullPointerException if src or dest is null
291    * @throws ArrayStoreException if src or dest is not an array, if they are
292    *         not compatible array types, or if an incompatible runtime type
293    *         is stored in dest
294    * @throws IndexOutOfBoundsException if len is negative, or if the start or
295    *         end copy position in either array is out of bounds
296    */
arraycopy(Object src, int srcStart, Object dest, int destStart, int len)297   public static void arraycopy(Object src, int srcStart,
298                                Object dest, int destStart, int len)
299   {
300     VMSystem.arraycopy(src, srcStart, dest, destStart, len);
301   }
302 
303   /**
304    * Get a hash code computed by the VM for the Object. This hash code will
305    * be the same as Object's hashCode() method.  It is usually some
306    * convolution of the pointer to the Object internal to the VM.  It
307    * follows standard hash code rules, in that it will remain the same for a
308    * given Object for the lifetime of that Object.
309    *
310    * @param o the Object to get the hash code for
311    * @return the VM-dependent hash code for this Object
312    * @since 1.1
313    */
identityHashCode(Object o)314   public static int identityHashCode(Object o)
315   {
316     return VMSystem.identityHashCode(o);
317   }
318 
319   /**
320    * Get all the system properties at once. A security check may be performed,
321    * <code>checkPropertiesAccess</code>. Note that a security manager may
322    * allow getting a single property, but not the entire group.
323    *
324    * <p>The required properties include:
325    * <dl>
326    * <dt>java.version</dt>         <dd>Java version number</dd>
327    * <dt>java.vendor</dt>          <dd>Java vendor specific string</dd>
328    * <dt>java.vendor.url</dt>      <dd>Java vendor URL</dd>
329    * <dt>java.home</dt>            <dd>Java installation directory</dd>
330    * <dt>java.vm.specification.version</dt> <dd>VM Spec version</dd>
331    * <dt>java.vm.specification.vendor</dt>  <dd>VM Spec vendor</dd>
332    * <dt>java.vm.specification.name</dt>    <dd>VM Spec name</dd>
333    * <dt>java.vm.version</dt>      <dd>VM implementation version</dd>
334    * <dt>java.vm.vendor</dt>       <dd>VM implementation vendor</dd>
335    * <dt>java.vm.name</dt>         <dd>VM implementation name</dd>
336    * <dt>java.specification.version</dt>    <dd>Java Runtime Environment version</dd>
337    * <dt>java.specification.vendor</dt>     <dd>Java Runtime Environment vendor</dd>
338    * <dt>java.specification.name</dt>       <dd>Java Runtime Environment name</dd>
339    * <dt>java.class.version</dt>   <dd>Java class version number</dd>
340    * <dt>java.class.path</dt>      <dd>Java classpath</dd>
341    * <dt>java.library.path</dt>    <dd>Path for finding Java libraries</dd>
342    * <dt>java.io.tmpdir</dt>       <dd>Default temp file path</dd>
343    * <dt>java.compiler</dt>        <dd>Name of JIT to use</dd>
344    * <dt>java.ext.dirs</dt>        <dd>Java extension path</dd>
345    * <dt>os.name</dt>              <dd>Operating System Name</dd>
346    * <dt>os.arch</dt>              <dd>Operating System Architecture</dd>
347    * <dt>os.version</dt>           <dd>Operating System Version</dd>
348    * <dt>file.separator</dt>       <dd>File separator ("/" on Unix)</dd>
349    * <dt>path.separator</dt>       <dd>Path separator (":" on Unix)</dd>
350    * <dt>line.separator</dt>       <dd>Line separator ("\n" on Unix)</dd>
351    * <dt>user.name</dt>            <dd>User account name</dd>
352    * <dt>user.home</dt>            <dd>User home directory</dd>
353    * <dt>user.dir</dt>             <dd>User's current working directory</dd>
354    * </dl>
355    *
356    * In addition, gnu defines several other properties, where ? stands for
357    * each character in '0' through '9':
358    * <dl>
359    * <dt>gnu.classpath.home</dt>         <dd>Path to the classpath libraries.</dd>
360    * <dt>gnu.classpath.version</dt>      <dd>Version of the classpath libraries.</dd>
361    * <dt>gnu.classpath.vm.shortname</dt> <dd>Succinct version of the VM name;
362    *     used for finding property files in file system</dd>
363    * <dt>gnu.classpath.home.url</dt>     <dd> Base URL; used for finding
364    *     property files in file system</dd>
365    * <dt>gnu.cpu.endian</dt>             <dd>big or little</dd>
366    * <dt>gnu.java.io.encoding_scheme_alias.iso-8859-?</dt>   <dd>8859_?</dd>
367    * <dt>gnu.java.io.encoding_scheme_alias.iso8859_?</dt>    <dd>8859_?</dd>
368    * <dt>gnu.java.io.encoding_scheme_alias.iso-latin-_?</dt> <dd>8859_?</dd>
369    * <dt>gnu.java.io.encoding_scheme_alias.latin?</dt>       <dd>8859_?</dd>
370    * <dt>gnu.java.io.encoding_scheme_alias.utf-8</dt>        <dd>UTF8</dd>
371    * <dt>gnu.java.util.zoneinfo.dir</dt>        <dd>Root of zoneinfo tree</dd>
372    * <dt>gnu.javax.print.server</dt>     <dd>Hostname of external CUPS server.</dd>
373    * </dl>
374    *
375    * @return the system properties, will never be null
376    * @throws SecurityException if permission is denied
377    */
getProperties()378   public static Properties getProperties()
379   {
380     SecurityManager sm = SecurityManager.current; // Be thread-safe.
381     if (sm != null)
382       sm.checkPropertiesAccess();
383     return SystemProperties.getProperties();
384   }
385 
386   /**
387    * Set all the system properties at once. A security check may be performed,
388    * <code>checkPropertiesAccess</code>. Note that a security manager may
389    * allow setting a single property, but not the entire group. An argument
390    * of null resets the properties to the startup default.
391    *
392    * @param properties the new set of system properties
393    * @throws SecurityException if permission is denied
394    */
setProperties(Properties properties)395   public static void setProperties(Properties properties)
396   {
397     SecurityManager sm = SecurityManager.current; // Be thread-safe.
398     if (sm != null)
399       sm.checkPropertiesAccess();
400     SystemProperties.setProperties(properties);
401   }
402 
403   /**
404    * Get a single system property by name. A security check may be performed,
405    * <code>checkPropertyAccess(key)</code>.
406    *
407    * @param key the name of the system property to get
408    * @return the property, or null if not found
409    * @throws SecurityException if permission is denied
410    * @throws NullPointerException if key is null
411    * @throws IllegalArgumentException if key is ""
412    */
getProperty(String key)413   public static String getProperty(String key)
414   {
415     SecurityManager sm = SecurityManager.current; // Be thread-safe.
416     if (sm != null)
417       sm.checkPropertyAccess(key);
418     if (key.length() == 0)
419       throw new IllegalArgumentException("key can't be empty");
420     return SystemProperties.getProperty(key);
421   }
422 
423   /**
424    * Get a single system property by name. A security check may be performed,
425    * <code>checkPropertyAccess(key)</code>.
426    *
427    * @param key the name of the system property to get
428    * @param def the default
429    * @return the property, or def if not found
430    * @throws SecurityException if permission is denied
431    * @throws NullPointerException if key is null
432    * @throws IllegalArgumentException if key is ""
433    */
getProperty(String key, String def)434   public static String getProperty(String key, String def)
435   {
436     SecurityManager sm = SecurityManager.current; // Be thread-safe.
437     if (sm != null)
438       sm.checkPropertyAccess(key);
439     // This handles both the null pointer exception and the illegal
440     // argument exception.
441     if (key.length() == 0)
442       throw new IllegalArgumentException("key can't be empty");
443     return SystemProperties.getProperty(key, def);
444   }
445 
446   /**
447    * Set a single system property by name. A security check may be performed,
448    * <code>checkPropertyAccess(key, "write")</code>.
449    *
450    * @param key the name of the system property to set
451    * @param value the new value
452    * @return the previous value, or null
453    * @throws SecurityException if permission is denied
454    * @throws NullPointerException if key is null
455    * @throws IllegalArgumentException if key is ""
456    * @since 1.2
457    */
setProperty(String key, String value)458   public static String setProperty(String key, String value)
459   {
460     SecurityManager sm = SecurityManager.current; // Be thread-safe.
461     if (sm != null)
462       sm.checkPermission(new PropertyPermission(key, "write"));
463     // This handles both the null pointer exception and the illegal
464     // argument exception.
465     if (key.length() == 0)
466       throw new IllegalArgumentException("key can't be empty");
467     return SystemProperties.setProperty(key, value);
468   }
469 
470   /**
471    * Remove a single system property by name. A security check may be
472    * performed, <code>checkPropertyAccess(key, "write")</code>.
473    *
474    * @param key the name of the system property to remove
475    * @return the previous value, or null
476    * @throws SecurityException if permission is denied
477    * @throws NullPointerException if key is null
478    * @throws IllegalArgumentException if key is ""
479    * @since 1.5
480    */
clearProperty(String key)481   public static String clearProperty(String key)
482   {
483     SecurityManager sm = SecurityManager.current; // Be thread-safe.
484     if (sm != null)
485       sm.checkPermission(new PropertyPermission(key, "write"));
486     // This handles both the null pointer exception and the illegal
487     // argument exception.
488     if (key.length() == 0)
489       throw new IllegalArgumentException("key can't be empty");
490     return SystemProperties.remove(key);
491   }
492 
493   /**
494    * Gets the value of an environment variable.
495    *
496    * @param name the name of the environment variable
497    * @return the string value of the variable or null when the
498    *         environment variable is not defined.
499    * @throws NullPointerException
500    * @throws SecurityException if permission is denied
501    * @since 1.5
502    * @specnote This method was deprecated in some JDK releases, but
503    *           was restored in 1.5.
504    */
getenv(String name)505   public static String getenv(String name)
506   {
507     if (name == null)
508       throw new NullPointerException();
509     SecurityManager sm = SecurityManager.current; // Be thread-safe.
510     if (sm != null)
511       sm.checkPermission(new RuntimePermission("getenv." + name));
512     return VMSystem.getenv(name);
513   }
514 
515   /**
516    * <p>
517    * Returns an unmodifiable view of the system environment variables.
518    * If the underlying system does not support environment variables,
519    * an empty map is returned.
520    * </p>
521    * <p>
522    * The returned map is read-only and does not accept queries using
523    * null keys or values, or those of a type other than <code>String</code>.
524    * Attempts to modify the map will throw an
525    * <code>UnsupportedOperationException</code>, while attempts
526    * to pass in a null value will throw a
527    * <code>NullPointerException</code>.  Types other than <code>String</code>
528    * throw a <code>ClassCastException</code>.
529    * </p>
530    * <p>
531    * As the returned map is generated using data from the underlying
532    * platform, it may not comply with the <code>equals()</code>
533    * and <code>hashCode()</code> contracts.  It is also likely that
534    * the keys of this map will be case-sensitive.
535    * </p>
536    * <p>
537    * Use of this method may require a security check for the
538    * RuntimePermission "getenv.*".
539    * </p>
540    *
541    * @return a map of the system environment variables.
542    * @throws SecurityException if the checkPermission method of
543    *         an installed security manager prevents access to
544    *         the system environment variables.
545    * @since 1.5
546    */
getenv()547   public static Map<String, String> getenv()
548   {
549     SecurityManager sm = SecurityManager.current; // Be thread-safe.
550     if (sm != null)
551       sm.checkPermission(new RuntimePermission("getenv.*"));
552 
553     if (environmentMap == null)
554       {
555         Map<String,String> variables = new EnvironmentMap();
556         List<String> environ = (List<String>)VMSystem.environ();
557         for (String envEntry : environ)
558           {
559             // avoid broken and null entries
560             if (envEntry != null && !envEntry.endsWith("="))
561               {
562                 // it's perfectly legal that some entries may be in the form
563                 // key=value=value=value
564                 int equalSignIndex = envEntry.indexOf('=');
565                 String key = envEntry.substring(0, equalSignIndex);
566                 String value = envEntry.substring(equalSignIndex + 1);
567                 variables.put(key, value);
568               }
569           }
570 
571         environmentMap = Collections.unmodifiableMap(variables);
572       }
573 
574     return environmentMap;
575   }
576 
577   /**
578    * Terminate the Virtual Machine. This just calls
579    * <code>Runtime.getRuntime().exit(status)</code>, and never returns.
580    * Obviously, a security check is in order, <code>checkExit</code>.
581    *
582    * @param status the exit status; by convention non-zero is abnormal
583    * @throws SecurityException if permission is denied
584    * @see Runtime#exit(int)
585    */
exit(int status)586   public static void exit(int status)
587   {
588     Runtime.getRuntime().exit(status);
589   }
590 
591   /**
592    * Calls the garbage collector. This is only a hint, and it is up to the
593    * implementation what this hint suggests, but it usually causes a
594    * best-effort attempt to reclaim unused memory from discarded objects.
595    * This calls <code>Runtime.getRuntime().gc()</code>.
596    *
597    * @see Runtime#gc()
598    */
gc()599   public static void gc()
600   {
601     Runtime.getRuntime().gc();
602   }
603 
604   /**
605    * Runs object finalization on pending objects. This is only a hint, and
606    * it is up to the implementation what this hint suggests, but it usually
607    * causes a best-effort attempt to run finalizers on all objects ready
608    * to be reclaimed. This calls
609    * <code>Runtime.getRuntime().runFinalization()</code>.
610    *
611    * @see Runtime#runFinalization()
612    */
runFinalization()613   public static void runFinalization()
614   {
615     Runtime.getRuntime().runFinalization();
616   }
617 
618   /**
619    * Tell the Runtime whether to run finalization before exiting the
620    * JVM.  This is inherently unsafe in multi-threaded applications,
621    * since it can force initialization on objects which are still in use
622    * by live threads, leading to deadlock; therefore this is disabled by
623    * default. There may be a security check, <code>checkExit(0)</code>. This
624    * calls <code>Runtime.runFinalizersOnExit()</code>.
625    *
626    * @param finalizeOnExit whether to run finalizers on exit
627    * @throws SecurityException if permission is denied
628    * @see Runtime#runFinalizersOnExit(boolean)
629    * @since 1.1
630    * @deprecated never rely on finalizers to do a clean, thread-safe,
631    *             mop-up from your code
632    */
runFinalizersOnExit(boolean finalizeOnExit)633   public static void runFinalizersOnExit(boolean finalizeOnExit)
634   {
635     Runtime.runFinalizersOnExit(finalizeOnExit);
636   }
637 
638   /**
639    * Load a code file using its explicit system-dependent filename. A security
640    * check may be performed, <code>checkLink</code>. This just calls
641    * <code>Runtime.getRuntime().load(filename)</code>.
642    *
643    * <p>
644    * The library is loaded using the class loader associated with the
645    * class associated with the invoking method.
646    *
647    * @param filename the code file to load
648    * @throws SecurityException if permission is denied
649    * @throws UnsatisfiedLinkError if the file cannot be loaded
650    * @see Runtime#load(String)
651    */
load(String filename)652   public static void load(String filename)
653   {
654     Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader());
655   }
656 
657   /**
658    * Load a library using its explicit system-dependent filename. A security
659    * check may be performed, <code>checkLink</code>. This just calls
660    * <code>Runtime.getRuntime().load(filename)</code>.
661    *
662    * <p>
663    * The library is loaded using the class loader associated with the
664    * class associated with the invoking method.
665    *
666    * @param libname the library file to load
667    * @throws SecurityException if permission is denied
668    * @throws UnsatisfiedLinkError if the file cannot be loaded
669    * @see Runtime#load(String)
670    */
loadLibrary(String libname)671   public static void loadLibrary(String libname)
672   {
673     Runtime.getRuntime().loadLibrary(libname,
674       VMStackWalker.getCallingClassLoader());
675   }
676 
677   /**
678    * Convert a library name to its platform-specific variant.
679    *
680    * @param libname the library name, as used in <code>loadLibrary</code>
681    * @return the platform-specific mangling of the name
682    * @since 1.2
683    */
mapLibraryName(String libname)684   public static String mapLibraryName(String libname)
685   {
686     return VMRuntime.mapLibraryName(libname);
687   }
688 
689   /**
690    * Returns the inherited channel of the VM.
691    *
692    * This wraps the inheritedChannel() call of the system's default
693    * {@link SelectorProvider}.
694    *
695    * @return the inherited channel of the VM
696    *
697    * @throws IOException If an I/O error occurs
698    * @throws SecurityException If an installed security manager denies access
699    *         to RuntimePermission("inheritedChannel")
700    *
701    * @since 1.5
702    */
inheritedChannel()703   public static Channel inheritedChannel()
704     throws IOException
705   {
706     return SelectorProvider.provider().inheritedChannel();
707   }
708 
709   /*
710    * @since 1.6
711    */
console()712   public static Console console()
713   {
714     return Console.console();
715   }
716 
717   /**
718    * Returns the system-dependent line separator.
719    *
720    * @return the system-dependent line separator.
721    */
lineSeparator()722   public static String lineSeparator()
723   {
724     return LINE_SEPARATOR;
725   }
726 
727   /**
728    * This is a specialised <code>Collection</code>, providing
729    * the necessary provisions for the collections used by the
730    * environment variable map.  Namely, it prevents
731    * querying anything but <code>String</code>s.
732    *
733    * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
734    */
735   private static class EnvironmentCollection
736     extends AbstractCollection<String>
737   {
738 
739     /**
740      * The wrapped collection.
741      */
742     protected Collection<String> c;
743 
744     /**
745      * Constructs a new environment collection, which
746      * wraps the elements of the supplied collection.
747      *
748      * @param coll the collection to use as a base for
749      *             this collection.
750      */
EnvironmentCollection(Collection<String> coll)751     public EnvironmentCollection(Collection<String> coll)
752     {
753       c = coll;
754     }
755 
756     /**
757      * Blocks queries containing a null object or an object which
758      * isn't of type <code>String</code>.  All other queries
759      * are forwarded to the underlying collection.
760      *
761      * @param obj the object to look for.
762      * @return true if the object exists in the collection.
763      * @throws NullPointerException if the specified object is null.
764      * @throws ClassCastException if the specified object is not a String.
765      */
contains(Object obj)766     public boolean contains(Object obj)
767     {
768       if (obj == null)
769           throw new
770             NullPointerException("This collection does not support " +
771                                  "null values.");
772       if (!(obj instanceof String))
773           throw new
774             ClassCastException("This collection only supports Strings.");
775       return c.contains(obj);
776     }
777 
778     /**
779      * Blocks queries where the collection contains a null object or
780      * an object which isn't of type <code>String</code>.  All other
781      * queries are forwarded to the underlying collection.
782      *
783      * @param coll the collection of objects to look for.
784      * @return true if the collection contains all elements in the collection.
785      * @throws NullPointerException if the collection is null.
786      * @throws NullPointerException if any collection entry is null.
787      * @throws ClassCastException if any collection entry is not a String.
788      */
containsAll(Collection<?> coll)789     public boolean containsAll(Collection<?> coll)
790     {
791       for (Object o: coll)
792         {
793           if (o == null)
794               throw new
795                 NullPointerException("This collection does not support " +
796                                      "null values.");
797           if (!(o instanceof String))
798               throw new
799                 ClassCastException("This collection only supports Strings.");
800         }
801       return c.containsAll(coll);
802     }
803 
804     /**
805      * This returns an iterator over the map elements, with the
806      * same provisions as for the collection and underlying map.
807      *
808      * @return an iterator over the map elements.
809      */
iterator()810     public Iterator<String> iterator()
811     {
812       return c.iterator();
813     }
814 
815     /**
816      * Blocks the removal of elements from the collection.
817      *
818      * @return true if the removal was sucessful.
819      * @throws NullPointerException if the collection is null.
820      * @throws NullPointerException if any collection entry is null.
821      * @throws ClassCastException if any collection entry is not a String.
822      */
remove(Object key)823     public boolean remove(Object key)
824     {
825       if (key == null)
826           throw new
827             NullPointerException("This collection does not support " +
828                                  "null values.");
829       if (!(key instanceof String))
830           throw new
831             ClassCastException("This collection only supports Strings.");
832       return c.contains(key);
833     }
834 
835     /**
836      * Blocks the removal of all elements in the specified
837      * collection from the collection.
838      *
839      * @param coll the collection of elements to remove.
840      * @return true if the elements were removed.
841      * @throws NullPointerException if the collection is null.
842      * @throws NullPointerException if any collection entry is null.
843      * @throws ClassCastException if any collection entry is not a String.
844      */
removeAll(Collection<?> coll)845     public boolean removeAll(Collection<?> coll)
846     {
847       for (Object o: coll)
848         {
849           if (o == null)
850               throw new
851                 NullPointerException("This collection does not support " +
852                                      "null values.");
853           if (!(o instanceof String))
854             throw new
855               ClassCastException("This collection only supports Strings.");
856         }
857       return c.removeAll(coll);
858     }
859 
860     /**
861      * Blocks the retention of all elements in the specified
862      * collection from the collection.
863      *
864      * @param coll the collection of elements to retain.
865      * @return true if the other elements were removed.
866      * @throws NullPointerException if the collection is null.
867      * @throws NullPointerException if any collection entry is null.
868      * @throws ClassCastException if any collection entry is not a String.
869      */
retainAll(Collection<?> coll)870     public boolean retainAll(Collection<?> coll)
871     {
872       for (Object o: coll)
873         {
874           if (o == null)
875               throw new
876                 NullPointerException("This collection does not support " +
877                                      "null values.");
878           if (!(o instanceof String))
879             throw new
880               ClassCastException("This collection only supports Strings.");
881         }
882       return c.containsAll(coll);
883     }
884 
885     /**
886      * This simply calls the same method on the wrapped
887      * collection.
888      *
889      * @return the size of the underlying collection.
890      */
size()891     public int size()
892     {
893       return c.size();
894     }
895 
896   } // class EnvironmentCollection<String>
897 
898   /**
899    * This is a specialised <code>HashMap</code>, which
900    * prevents the addition or querying of anything other than
901    * <code>String</code> objects.
902    *
903    * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
904    */
905   static class EnvironmentMap
906     extends HashMap<String,String>
907   {
908 
909     /**
910      * Cache the entry set.
911      */
912     private transient Set<Map.Entry<String,String>> entries;
913 
914     /**
915      * Cache the key set.
916      */
917     private transient Set<String> keys;
918 
919     /**
920      * Cache the value collection.
921      */
922     private transient Collection<String> values;
923 
924     /**
925      * Constructs a new empty <code>EnvironmentMap</code>.
926      */
EnvironmentMap()927     EnvironmentMap()
928     {
929       super();
930     }
931 
932     /**
933      * Constructs a new <code>EnvironmentMap</code> containing
934      * the contents of the specified map.
935      *
936      * @param m the map to be added to this.
937      * @throws NullPointerException if a key or value is null.
938      * @throws ClassCastException if a key or value is not a String.
939      */
EnvironmentMap(Map<String,String> m)940     EnvironmentMap(Map<String,String> m)
941     {
942       super(m);
943     }
944 
945     /**
946      * Blocks queries containing a null key or one which is not
947      * of type <code>String</code>.  All other queries
948      * are forwarded to the superclass.
949      *
950      * @param key the key to look for in the map.
951      * @return true if the key exists in the map.
952      * @throws NullPointerException if the specified key is null.
953      */
containsKey(Object key)954     public boolean containsKey(Object key)
955     {
956       if (key == null)
957         throw new
958           NullPointerException("This map does not support null keys.");
959       if (!(key instanceof String))
960         throw new
961           ClassCastException("This map only allows queries using Strings.");
962       return super.containsKey(key);
963     }
964 
965     /**
966      * Blocks queries using a null or non-<code>String</code> value.
967      * All other queries are forwarded to the superclass.
968      *
969      * @param value the value to look for in the map.
970      * @return true if the value exists in the map.
971      * @throws NullPointerException if the specified value is null.
972      */
containsValue(Object value)973     public boolean containsValue(Object value)
974     {
975       if (value == null)
976           throw new
977             NullPointerException("This map does not support null values.");
978       if (!(value instanceof String))
979         throw new
980           ClassCastException("This map only allows queries using Strings.");
981       return super.containsValue(value);
982     }
983 
984     /**
985      * Returns a set view of the map entries, with the same
986      * provisions as for the underlying map.
987      *
988      * @return a set containing the map entries.
989      */
entrySet()990     public Set<Map.Entry<String,String>> entrySet()
991     {
992       if (entries == null)
993         entries = super.entrySet();
994       return entries;
995     }
996 
997     /**
998      * Blocks queries containing a null or non-<code>String</code> key.
999      * All other queries are passed on to the superclass.
1000      *
1001      * @param key the key to retrieve the value for.
1002      * @return the value associated with the given key.
1003      * @throws NullPointerException if the specified key is null.
1004      * @throws ClassCastException if the specified key is not a String.
1005      */
get(Object key)1006     public String get(Object key)
1007     {
1008       if (key == null)
1009         throw new
1010           NullPointerException("This map does not support null keys.");
1011       if (!(key instanceof String))
1012         throw new
1013           ClassCastException("This map only allows queries using Strings.");
1014       return super.get(key);
1015     }
1016 
1017     /**
1018      * Returns a set view of the keys, with the same
1019      * provisions as for the underlying map.
1020      *
1021      * @return a set containing the keys.
1022      */
keySet()1023     public Set<String> keySet()
1024     {
1025       if (keys == null)
1026         keys = new EnvironmentSet(super.keySet());
1027       return keys;
1028     }
1029 
1030     /**
1031      * Associates the given key to the given value. If the
1032      * map already contains the key, its value is replaced.
1033      * The map does not accept null keys or values, or keys
1034      * and values not of type {@link String}.
1035      *
1036      * @param key the key to map.
1037      * @param value the value to be mapped.
1038      * @return the previous value of the key, or null if there was no mapping
1039      * @throws NullPointerException if a key or value is null.
1040      * @throws ClassCastException if a key or value is not a String.
1041      */
put(String key, String value)1042     public String put(String key, String value)
1043     {
1044       if (key == null)
1045         throw new NullPointerException("A new key is null.");
1046       if (value == null)
1047         throw new NullPointerException("A new value is null.");
1048       if (!(key instanceof String))
1049         throw new ClassCastException("A new key is not a String.");
1050       if (!(value instanceof String))
1051         throw new ClassCastException("A new value is not a String.");
1052       return super.put(key, value);
1053     }
1054 
1055     /**
1056      * Removes a key-value pair from the map.  The queried key may not
1057      * be null or of a type other than a <code>String</code>.
1058      *
1059      * @param key the key of the entry to remove.
1060      * @return the removed value.
1061      * @throws NullPointerException if the specified key is null.
1062      * @throws ClassCastException if the specified key is not a String.
1063      */
remove(Object key)1064     public String remove(Object key)
1065     {
1066       if (key == null)
1067         throw new
1068           NullPointerException("This map does not support null keys.");
1069       if (!(key instanceof String))
1070         throw new
1071           ClassCastException("This map only allows queries using Strings.");
1072       return super.remove(key);
1073     }
1074 
1075     /**
1076      * Returns a collection view of the values, with the same
1077      * provisions as for the underlying map.
1078      *
1079      * @return a collection containing the values.
1080      */
values()1081     public Collection<String> values()
1082     {
1083       if (values == null)
1084         values = new EnvironmentCollection(super.values());
1085       return values;
1086     }
1087 
1088   }
1089 
1090   /**
1091    * This is a specialised <code>Set</code>, providing
1092    * the necessary provisions for the collections used by the
1093    * environment variable map.  Namely, it prevents
1094    * modifications and the use of queries with null
1095    * or non-<code>String</code> values.
1096    *
1097    * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
1098    */
1099   private static class EnvironmentSet
1100     extends EnvironmentCollection
1101     implements Set<String>
1102   {
1103 
1104     /**
1105      * Constructs a new environment set, which
1106      * wraps the elements of the supplied set.
1107      *
1108      * @param set the set to use as a base for
1109      *             this set.
1110      */
EnvironmentSet(Set<String> set)1111     public EnvironmentSet(Set<String> set)
1112     {
1113       super(set);
1114     }
1115 
1116     /**
1117      * This simply calls the same method on the wrapped
1118      * collection.
1119      *
1120      * @param obj the object to compare with.
1121      * @return true if the two objects are equal.
1122      */
equals(Object obj)1123     public boolean equals(Object obj)
1124     {
1125       return c.equals(obj);
1126     }
1127 
1128     /**
1129      * This simply calls the same method on the wrapped
1130      * collection.
1131      *
1132      * @return the hashcode of the collection.
1133      */
hashCode()1134     public int hashCode()
1135     {
1136       return c.hashCode();
1137     }
1138 
1139   } // class EnvironmentSet<String>
1140 
1141 } // class System
1142