System.java revision a6c26760ff2f6d3ae5794f5b15509f965b991f17
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 *      http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang;
34
35import dalvik.system.VMRuntime;
36import dalvik.system.VMStack;
37import java.io.BufferedInputStream;
38import java.io.Console;
39import java.io.FileDescriptor;
40import java.io.FileInputStream;
41import java.io.FileOutputStream;
42import java.io.IOException;
43import java.io.InputStream;
44import java.io.PrintStream;
45import java.nio.channels.Channel;
46import java.nio.channels.spi.SelectorProvider;
47import java.util.AbstractMap;
48import java.util.Collections;
49import java.util.HashMap;
50import java.util.Map;
51import java.util.Properties;
52import java.util.Set;
53import libcore.icu.ICU;
54import libcore.io.ErrnoException;
55import libcore.io.Libcore;
56import libcore.io.StructPasswd;
57import libcore.io.StructUtsname;
58
59/**
60 * Provides access to system-related information and resources including
61 * standard input and output. Enables clients to dynamically load native
62 * libraries. All methods of this class are accessed in a static way and the
63 * class itself can not be instantiated.
64 *
65 * @see Runtime
66 */
67public final class System {
68
69    /**
70     * Default input stream.
71     */
72    public static final InputStream in;
73
74    /**
75     * Default output stream.
76     */
77    public static final PrintStream out;
78
79    /**
80     * Default error output stream.
81     */
82    public static final PrintStream err;
83
84    private static final String lineSeparator;
85    private static final Properties unchangeableSystemProperties;
86    private static Properties systemProperties;
87
88    static {
89        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
90        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
91        in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
92        unchangeableSystemProperties = initUnchangeableSystemProperties();
93        systemProperties = createSystemProperties();
94        lineSeparator = System.getProperty("line.separator");
95    }
96
97    /**
98     * Sets the standard input stream to the given user defined input stream.
99     *
100     * @param newIn
101     *            the user defined input stream to set as the standard input
102     *            stream.
103     */
104    public static void setIn(InputStream newIn) {
105        setFieldImpl("in", "Ljava/io/InputStream;", newIn);
106    }
107
108    /**
109     * Sets the standard output stream to the given user defined output stream.
110     *
111     * @param newOut
112     *            the user defined output stream to set as the standard output
113     *            stream.
114     */
115    public static void setOut(PrintStream newOut) {
116        setFieldImpl("out", "Ljava/io/PrintStream;", newOut);
117    }
118
119    /**
120     * Sets the standard error output stream to the given user defined output
121     * stream.
122     *
123     * @param newErr
124     *            the user defined output stream to set as the standard error
125     *            output stream.
126     */
127    public static void setErr(PrintStream newErr) {
128        setFieldImpl("err", "Ljava/io/PrintStream;", newErr);
129    }
130
131    /**
132     * Prevents this class from being instantiated.
133     */
134    private System() {
135    }
136
137    /**
138     * Copies {@code length} elements from the array {@code src},
139     * starting at offset {@code srcPos}, into the array {@code dst},
140     * starting at offset {@code dstPos}.
141     *
142     * <p>The source and destination arrays can be the same array,
143     * in which case copying is performed as if the source elements
144     * are first copied into a temporary array and then into the
145     * destination array.
146     *
147     * @param src
148     *            the source array to copy the content.
149     * @param srcPos
150     *            the starting index of the content in {@code src}.
151     * @param dst
152     *            the destination array to copy the data into.
153     * @param dstPos
154     *            the starting index for the copied content in {@code dst}.
155     * @param length
156     *            the number of elements to be copied.
157     */
158    public static native void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length);
159
160    /**
161     * The char array length threshold below which to use a Java
162     * (non-native) version of arraycopy() instead of the native
163     * version. See b/7103825.
164     */
165    private static final int ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD = 64;
166
167    /**
168     * The char[] specialized version of arraycopy().
169     *
170     * @hide internal use only
171     */
172    public static void arraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
173        if (src == null) {
174            throw new NullPointerException("src == null");
175        }
176        if (dst == null) {
177            throw new NullPointerException("dst == null");
178        }
179        if (srcPos < 0 || dstPos < 0 || length < 0 ||
180            srcPos > src.length - length || dstPos > dst.length - length) {
181            throw new ArrayIndexOutOfBoundsException(
182                "src.length=" + src.length + " srcPos=" + srcPos +
183                " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length);
184        }
185        if (length <= ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD) {
186            // Copy char by char for shorter arrays.
187            if (src == dst && srcPos < dstPos && dstPos < srcPos + length) {
188                // Copy backward (to avoid overwriting elements before
189                // they are copied in case of an overlap on the same
190                // array.)
191                for (int i = length - 1; i >= 0; --i) {
192                    dst[dstPos + i] = src[srcPos + i];
193                }
194            } else {
195                // Copy forward.
196                for (int i = 0; i < length; ++i) {
197                    dst[dstPos + i] = src[srcPos + i];
198                }
199            }
200        } else {
201            // Call the native version for longer arrays.
202            arraycopyCharUnchecked(src, srcPos, dst, dstPos, length);
203        }
204    }
205
206    /**
207     * The char[] specialized, unchecked, native version of
208     * arraycopy(). This assumes error checking has been done.
209     */
210    private static native void arraycopyCharUnchecked(char[] src, int srcPos,
211        char[] dst, int dstPos, int length);
212
213    /**
214     * Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC.
215     *
216     * <p>This method always returns UTC times, regardless of the system's time zone.
217     * This is often called "Unix time" or "epoch time".
218     * Use a {@link java.text.DateFormat} instance to format this time for display to a human.
219     *
220     * <p>This method shouldn't be used for measuring timeouts or
221     * other elapsed time measurements, as changing the system time can affect
222     * the results. Use {@link #nanoTime} for that.
223     */
224    public static native long currentTimeMillis();
225
226    /**
227     * Returns the current timestamp of the most precise timer available on the
228     * local system, in nanoseconds. Equivalent to Linux's {@code CLOCK_MONOTONIC}.
229     *
230     * <p>This timestamp should only be used to measure a duration by comparing it
231     * against another timestamp on the same device.
232     * Values returned by this method do not have a defined correspondence to
233     * wall clock times; the zero value is typically whenever the device last booted.
234     * Use {@link #currentTimeMillis} if you want to know what time it is.
235     */
236    public static native long nanoTime();
237
238    /**
239     * Causes the VM to stop running and the program to exit with the given exit status.
240     * If {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
241     * {@code true} argument, then all objects will be properly
242     * garbage-collected and finalized first.
243     */
244    public static void exit(int code) {
245        Runtime.getRuntime().exit(code);
246    }
247
248    /**
249     * Indicates to the VM that it would be a good time to run the
250     * garbage collector. Note that this is a hint only. There is no guarantee
251     * that the garbage collector will actually be run.
252     */
253    public static void gc() {
254        Runtime.getRuntime().gc();
255    }
256
257    /**
258     * Returns the value of the environment variable with the given name, or null if no such
259     * variable exists.
260     */
261    public static String getenv(String name) {
262        if (name == null) {
263            throw new NullPointerException("name == null");
264        }
265        return Libcore.os.getenv(name);
266    }
267
268    /**
269     * Returns an unmodifiable map of all environment variables to their values.
270     */
271    public static Map<String, String> getenv() {
272        Map<String, String> map = new HashMap<String, String>();
273        for (String entry : Libcore.os.environ()) {
274            int index = entry.indexOf('=');
275            if (index != -1) {
276                map.put(entry.substring(0, index), entry.substring(index + 1));
277            }
278        }
279        return new SystemEnvironment(map);
280    }
281
282    /**
283     * Returns the inherited channel from the creator of the current virtual
284     * machine.
285     *
286     * @return the inherited {@link Channel} or {@code null} if none exists.
287     * @throws IOException
288     *             if an I/O error occurred.
289     * @see SelectorProvider
290     * @see SelectorProvider#inheritedChannel()
291     */
292    public static Channel inheritedChannel() throws IOException {
293        return SelectorProvider.provider().inheritedChannel();
294    }
295
296    /**
297     * Returns the system properties. Note that this is not a copy, so that
298     * changes made to the returned Properties object will be reflected in
299     * subsequent calls to getProperty and getProperties.
300     *
301     * @return the system properties.
302     */
303    public static Properties getProperties() {
304        return systemProperties;
305    }
306
307    private static Properties initUnchangeableSystemProperties() {
308        VMRuntime runtime = VMRuntime.getRuntime();
309        Properties p = new Properties();
310
311        String projectUrl = "http://www.android.com/";
312        String projectName = "The Android Project";
313
314        p.put("java.boot.class.path", runtime.bootClassPath());
315        p.put("java.class.path", runtime.classPath());
316
317        // None of these four are meaningful on Android, but these keys are guaranteed
318        // to be present for System.getProperty. For java.class.version, we use the maximum
319        // class file version that dx currently supports.
320        p.put("java.class.version", "50.0");
321        p.put("java.compiler", "");
322        p.put("java.ext.dirs", "");
323        p.put("java.version", "0");
324
325        // TODO: does this make any sense? Should we just leave java.home unset?
326        String javaHome = getenv("JAVA_HOME");
327        if (javaHome == null) {
328            javaHome = "/system";
329        }
330        p.put("java.home", javaHome);
331
332        String ldLibraryPath = getenv("LD_LIBRARY_PATH");
333        if (ldLibraryPath != null) {
334            p.put("java.library.path", ldLibraryPath);
335        }
336
337        p.put("java.specification.name", "Dalvik Core Library");
338        p.put("java.specification.vendor", projectName);
339        p.put("java.specification.version", "0.9");
340
341        p.put("java.vendor", projectName);
342        p.put("java.vendor.url", projectUrl);
343        p.put("java.vm.name", "Dalvik");
344        p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification");
345        p.put("java.vm.specification.vendor", projectName);
346        p.put("java.vm.specification.version", "0.9");
347        p.put("java.vm.vendor", projectName);
348        p.put("java.vm.version", runtime.vmVersion());
349
350        p.put("file.separator", "/");
351        p.put("line.separator", "\n");
352        p.put("path.separator", ":");
353
354        p.put("java.runtime.name", "Android Runtime");
355        p.put("java.runtime.version", "0.9");
356        p.put("java.vm.vendor.url", projectUrl);
357
358        p.put("file.encoding", "UTF-8");
359        p.put("user.language", "en");
360        p.put("user.region", "US");
361
362        try {
363            StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid());
364            p.put("user.home", passwd.pw_dir);
365            p.put("user.name", passwd.pw_name);
366        } catch (ErrnoException exception) {
367            throw new AssertionError(exception);
368        }
369
370        StructUtsname info = Libcore.os.uname();
371        p.put("os.arch", info.machine);
372        p.put("os.name", info.sysname);
373        p.put("os.version", info.release);
374
375        // Undocumented Android-only properties.
376        p.put("android.icu.library.version", ICU.getIcuVersion());
377        p.put("android.icu.unicode.version", ICU.getUnicodeVersion());
378        p.put("android.icu.cldr.version", ICU.getCldrVersion());
379
380        parsePropertyAssignments(p, specialProperties());
381
382        // Override built-in properties with settings from the command line.
383        parsePropertyAssignments(p, runtime.properties());
384        return p;
385    }
386
387    private static Properties createSystemProperties() {
388        Properties p = new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties);
389        // On Android, each app gets its own temporary directory.
390        // (See android.app.ActivityThread.) This is just a fallback default,
391        // useful only on the host.
392        p.put("java.io.tmpdir", "/tmp");
393        return p;
394    }
395
396    /**
397     * Returns an array of "key=value" strings containing information not otherwise
398     * easily available, such as #defined library versions.
399     */
400    private static native String[] specialProperties();
401
402    /**
403     * Adds each element of 'assignments' to 'p', treating each element as an
404     * assignment in the form "key=value".
405     */
406    private static void parsePropertyAssignments(Properties p, String[] assignments) {
407        for (String assignment : assignments) {
408            int split = assignment.indexOf('=');
409            String key = assignment.substring(0, split);
410            String value = assignment.substring(split + 1);
411            p.put(key, value);
412        }
413    }
414
415    /**
416     * Returns the value of a particular system property or {@code null} if no
417     * such property exists.
418     *
419     * <p>The following properties are always provided by the Dalvik VM <b>and
420     * cannot be modified</b>:
421     * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
422     * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
423     *     <td><b>Name</b></td>        <td><b>Meaning</b></td>                    <td><b>Example</b></td></tr>
424     * <tr><td>file.separator</td>     <td>{@link java.io.File#separator}</td>    <td>{@code /}</td></tr>
425     *
426     * <tr><td>java.class.path</td>    <td>System class path</td>                 <td>{@code .}</td></tr>
427     * <tr><td>java.class.version</td> <td>(Not useful on Android)</td>           <td>{@code 50.0}</td></tr>
428     * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
429     * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
430     * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
431     * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
432     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /vendor/lib:/system/lib}</td></tr>
433     * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
434     * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
435     * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
436     *
437     * <tr><td>java.specification.version</td>    <td>VM libraries version</td>        <td>{@code 0.9}</td></tr>
438     * <tr><td>java.specification.vendor</td>     <td>VM libraries vendor</td>         <td>{@code The Android Project}</td></tr>
439     * <tr><td>java.specification.name</td>       <td>VM libraries name</td>           <td>{@code Dalvik Core Library}</td></tr>
440     * <tr><td>java.vm.version</td>               <td>VM implementation version</td>   <td>{@code 1.2.0}</td></tr>
441     * <tr><td>java.vm.vendor</td>                <td>VM implementation vendor</td>    <td>{@code The Android Project}</td></tr>
442     * <tr><td>java.vm.name</td>                  <td>VM implementation name</td>      <td>{@code Dalvik}</td></tr>
443     * <tr><td>java.vm.specification.version</td> <td>VM specification version</td>    <td>{@code 0.9}</td></tr>
444     * <tr><td>java.vm.specification.vendor</td>  <td>VM specification vendor</td>     <td>{@code The Android Project}</td></tr>
445     * <tr><td>java.vm.specification.name</td>    <td>VM specification name</td>       <td>{@code Dalvik Virtual Machine Specification}</td></tr>
446     *
447     * <tr><td>line.separator</td>     <td>The system line separator</td>         <td>{@code \n}</td></tr>
448     *
449     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
450     * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
451     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
452     *
453     * <tr><td>path.separator</td>     <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
454     *
455     * <tr><td>user.dir</td>           <td>Base of non-absolute paths</td>        <td>{@code /}</td></tr>
456     * <tr><td>user.home</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
457     * <tr><td>user.name</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
458     *
459     * </table>
460     *
461     * <p>It is an error to override anyone of these properties. Any attempt to
462     * do so will leave their values unchanged.
463     *
464     * @param propertyName
465     *            the name of the system property to look up.
466     * @return the value of the specified system property or {@code null} if the
467     *         property doesn't exist.
468     */
469    public static String getProperty(String propertyName) {
470        return getProperty(propertyName, null);
471    }
472
473    /**
474     * Returns the value of a particular system property. The {@code
475     * defaultValue} will be returned if no such property has been found.
476     */
477    public static String getProperty(String name, String defaultValue) {
478        checkPropertyName(name);
479        return systemProperties.getProperty(name, defaultValue);
480    }
481
482    /**
483     * Sets the value of a particular system property. Most system properties
484     * are read only and cannot be cleared or modified. See {@link #setProperty} for a
485     * list of such properties.
486     *
487     * @return the old value of the property or {@code null} if the property
488     *         didn't exist.
489     */
490    public static String setProperty(String name, String value) {
491        checkPropertyName(name);
492        return (String) systemProperties.setProperty(name, value);
493    }
494
495    /**
496     * Removes a specific system property. Most system properties
497     * are read only and cannot be cleared or modified. See {@link #setProperty} for a
498     * list of such properties.
499     *
500     * @return the property value or {@code null} if the property didn't exist.
501     * @throws NullPointerException
502     *             if the argument is {@code null}.
503     * @throws IllegalArgumentException
504     *             if the argument is empty.
505     */
506    public static String clearProperty(String name) {
507        checkPropertyName(name);
508        return (String) systemProperties.remove(name);
509    }
510
511    private static void checkPropertyName(String name) {
512        if (name == null) {
513            throw new NullPointerException("name == null");
514        }
515        if (name.isEmpty()) {
516            throw new IllegalArgumentException("name is empty");
517        }
518    }
519
520    /**
521     * Returns the {@link java.io.Console} associated with this VM, or null.
522     * Not all VMs will have an associated console. A console is typically only
523     * available for programs run from the command line.
524     * @since 1.6
525     */
526    public static Console console() {
527        return Console.getConsole();
528    }
529
530    /**
531     * Returns null. Android does not use {@code SecurityManager}. This method
532     * is only provided for source compatibility.
533     *
534     * @return null
535     */
536    public static SecurityManager getSecurityManager() {
537        return null;
538    }
539
540    /**
541     * Returns an integer hash code for the parameter. The hash code returned is
542     * the same one that would be returned by the method {@code
543     * java.lang.Object.hashCode()}, whether or not the object's class has
544     * overridden hashCode(). The hash code for {@code null} is {@code 0}.
545     *
546     * @param anObject
547     *            the object to calculate the hash code.
548     * @return the hash code for the given object.
549     * @see java.lang.Object#hashCode
550     */
551    public static native int identityHashCode(Object anObject);
552
553    /**
554     * Returns the system's line separator. On Android, this is {@code "\n"}. The value
555     * comes from the value of the {@code line.separator} system property when the VM
556     * starts. Later changes to the property will not affect the value returned by this
557     * method.
558     * @since 1.7
559     */
560    public static String lineSeparator() {
561        return lineSeparator;
562    }
563
564    /**
565     * Loads and links the dynamic library that is identified through the
566     * specified path. This method is similar to {@link #loadLibrary(String)},
567     * but it accepts a full path specification whereas {@code loadLibrary} just
568     * accepts the name of the library to load.
569     *
570     * @param pathName
571     *            the path of the file to be loaded.
572     */
573    public static void load(String pathName) {
574        Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader());
575    }
576
577    /**
578     * Loads and links the library with the specified name. The mapping of the
579     * specified library name to the full path for loading the library is
580     * implementation-dependent.
581     *
582     * @param libName
583     *            the name of the library to load.
584     * @throws UnsatisfiedLinkError
585     *             if the library could not be loaded.
586     */
587    public static void loadLibrary(String libName) {
588        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
589    }
590
591    /**
592     * @hide internal use only
593     */
594    public static void logE(String message) {
595        log('E', message, null);
596    }
597
598    /**
599     * @hide internal use only
600     */
601    public static void logE(String message, Throwable th) {
602        log('E', message, th);
603    }
604
605    /**
606     * @hide internal use only
607     */
608    public static void logI(String message) {
609        log('I', message, null);
610    }
611
612    /**
613     * @hide internal use only
614     */
615    public static void logI(String message, Throwable th) {
616        log('I', message, th);
617    }
618
619    /**
620     * @hide internal use only
621     */
622    public static void logW(String message) {
623        log('W', message, null);
624    }
625
626    /**
627     * @hide internal use only
628     */
629    public static void logW(String message, Throwable th) {
630        log('W', message, th);
631    }
632
633    private static native void log(char type, String message, Throwable th);
634
635    /**
636     * Provides a hint to the VM that it would be useful to attempt
637     * to perform any outstanding object finalization.
638     */
639    public static void runFinalization() {
640        Runtime.getRuntime().runFinalization();
641    }
642
643    /**
644     * Ensures that, when the VM is about to exit, all objects are
645     * finalized. Note that all finalization which occurs when the system is
646     * exiting is performed after all running threads have been terminated.
647     *
648     * @param flag
649     *            the flag determines if finalization on exit is enabled.
650     * @deprecated This method is unsafe.
651     */
652    @SuppressWarnings("deprecation")
653    @Deprecated
654    public static void runFinalizersOnExit(boolean flag) {
655        Runtime.runFinalizersOnExit(flag);
656    }
657
658    /**
659     * Attempts to set all system properties. Copies all properties from
660     * {@code p} and discards system properties that are read only and cannot
661     * be modified. See {@link #setProperty} for a list of such properties.
662     */
663    public static void setProperties(Properties p) {
664        PropertiesWithNonOverrideableDefaults userProperties =
665                new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties);
666        if (p != null) {
667            userProperties.putAll(p);
668        }
669
670        systemProperties = userProperties;
671    }
672
673    /**
674     * Throws {@code SecurityException}.
675     *
676     * <p>Security managers do <i>not</i> provide a secure environment for
677     * executing untrusted code and are unsupported on Android. Untrusted code
678     * cannot be safely isolated within a single VM on Android, so this method
679     * <i>always</i> throws a {@code SecurityException}.
680     *
681     * @param sm a security manager
682     * @throws SecurityException always
683     */
684    public static void setSecurityManager(SecurityManager sm) {
685        if (sm != null) {
686            throw new SecurityException();
687        }
688    }
689
690    /**
691     * Returns the platform specific file name format for the shared library
692     * named by the argument.
693     *
694     * @param userLibName
695     *            the name of the library to look up.
696     * @return the platform specific filename for the library.
697     */
698    public static native String mapLibraryName(String userLibName);
699
700    /**
701     * Sets the value of the named static field in the receiver to the passed in
702     * argument.
703     *
704     * @param fieldName
705     *            the name of the field to set, one of in, out, or err
706     * @param stream
707     *            the new value of the field
708     */
709    private static native void setFieldImpl(String fieldName, String signature, Object stream);
710
711    /**
712     * A properties class that prohibits changes to any of the properties
713     * contained in its defaults.
714     */
715    static final class PropertiesWithNonOverrideableDefaults extends Properties {
716        PropertiesWithNonOverrideableDefaults(Properties defaults) {
717            super(defaults);
718        }
719
720        @Override
721        public Object put(Object key, Object value) {
722            if (defaults.containsKey(key)) {
723                logE("Ignoring attempt to set property \"" + key +
724                        "\" to value \"" + value + "\".");
725                return defaults.get(key);
726            }
727
728            return super.put(key, value);
729        }
730
731        @Override
732        public Object remove(Object key) {
733            if (defaults.containsKey(key)) {
734                logE("Ignoring attempt to remove property \"" + key + "\".");
735                return null;
736            }
737
738            return super.remove(key);
739        }
740    }
741
742    /**
743     * The unmodifiable environment variables map. System.getenv() specifies
744     * that this map must throw when passed non-String keys.
745     */
746    static class SystemEnvironment extends AbstractMap<String, String> {
747        private final Map<String, String> map;
748
749        public SystemEnvironment(Map<String, String> map) {
750            this.map = Collections.unmodifiableMap(map);
751        }
752
753        @Override public Set<Entry<String, String>> entrySet() {
754            return map.entrySet();
755        }
756
757        @Override public String get(Object key) {
758            return map.get(toNonNullString(key));
759        }
760
761        @Override public boolean containsKey(Object key) {
762            return map.containsKey(toNonNullString(key));
763        }
764
765        @Override public boolean containsValue(Object value) {
766            return map.containsValue(toNonNullString(value));
767        }
768
769        private String toNonNullString(Object o) {
770            if (o == null) {
771                throw new NullPointerException("o == null");
772            }
773            return (String) o;
774        }
775    }
776}
777