System.java revision 0883232ea56c06c9c530ec924fdaf21f19f3f14c
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.Libcore;
55import libcore.io.StructUtsname;
56import libcore.util.ZoneInfoDB;
57
58/**
59 * Provides access to system-related information and resources including
60 * standard input and output. Enables clients to dynamically load native
61 * libraries. All methods of this class are accessed in a static way and the
62 * class itself can not be instantiated.
63 *
64 * @see Runtime
65 */
66public final class System {
67
68    /**
69     * Default input stream.
70     */
71    public static final InputStream in;
72
73    /**
74     * Default output stream.
75     */
76    public static final PrintStream out;
77
78    /**
79     * Default error output stream.
80     */
81    public static final PrintStream err;
82
83    private static final String lineSeparator;
84    private static Properties systemProperties;
85
86    static {
87        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
88        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
89        in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
90        lineSeparator = System.getProperty("line.separator");
91    }
92
93    /**
94     * Sets the standard input stream to the given user defined input stream.
95     *
96     * @param newIn
97     *            the user defined input stream to set as the standard input
98     *            stream.
99     */
100    public static void setIn(InputStream newIn) {
101        setFieldImpl("in", "Ljava/io/InputStream;", newIn);
102    }
103
104    /**
105     * Sets the standard output stream to the given user defined output stream.
106     *
107     * @param newOut
108     *            the user defined output stream to set as the standard output
109     *            stream.
110     */
111    public static void setOut(PrintStream newOut) {
112        setFieldImpl("out", "Ljava/io/PrintStream;", newOut);
113    }
114
115    /**
116     * Sets the standard error output stream to the given user defined output
117     * stream.
118     *
119     * @param newErr
120     *            the user defined output stream to set as the standard error
121     *            output stream.
122     */
123    public static void setErr(PrintStream newErr) {
124        setFieldImpl("err", "Ljava/io/PrintStream;", newErr);
125    }
126
127    /**
128     * Prevents this class from being instantiated.
129     */
130    private System() {
131    }
132
133    /**
134     * Copies {@code length} elements from the array {@code src},
135     * starting at offset {@code srcPos}, into the array {@code dst},
136     * starting at offset {@code dstPos}.
137     *
138     * <p>The source and destination arrays can be the same array,
139     * in which case copying is performed as if the source elements
140     * are first copied into a temporary array and then into the
141     * destination array.
142     *
143     * @param src
144     *            the source array to copy the content.
145     * @param srcPos
146     *            the starting index of the content in {@code src}.
147     * @param dst
148     *            the destination array to copy the data into.
149     * @param dstPos
150     *            the starting index for the copied content in {@code dst}.
151     * @param length
152     *            the number of elements to be copied.
153     */
154    public static native void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length);
155
156    /**
157     * Returns the current system time in milliseconds since January 1, 1970
158     * 00:00:00 UTC. This method shouldn't be used for measuring timeouts or
159     * other elapsed time measurements, as changing the system time can affect
160     * the results.
161     *
162     * @return the local system time in milliseconds.
163     */
164    public static native long currentTimeMillis();
165
166    /**
167     * Returns the current timestamp of the most precise timer available on the
168     * local system. This timestamp can only be used to measure an elapsed
169     * period by comparing it against another timestamp. It cannot be used as a
170     * very exact system time expression.
171     *
172     * @return the current timestamp in nanoseconds.
173     */
174    public static native long nanoTime();
175
176    /**
177     * Causes the VM to stop running and the program to exit. If
178     * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
179     * {@code true} argument, then all objects will be properly
180     * garbage-collected and finalized first.
181     *
182     * @param code
183     *            the return code.
184     */
185    public static void exit(int code) {
186        Runtime.getRuntime().exit(code);
187    }
188
189    /**
190     * Indicates to the VM that it would be a good time to run the
191     * garbage collector. Note that this is a hint only. There is no guarantee
192     * that the garbage collector will actually be run.
193     */
194    public static void gc() {
195        Runtime.getRuntime().gc();
196    }
197
198    /**
199     * Returns the value of the environment variable with the given name {@code
200     * var}.
201     *
202     * @param name
203     *            the name of the environment variable.
204     * @return the value of the specified environment variable or {@code null}
205     *         if no variable exists with the given name.
206     */
207    public static String getenv(String name) {
208        return getenv(name, null);
209    }
210
211    private static String getenv(String name, String defaultValue) {
212        if (name == null) {
213            throw new NullPointerException("name == null");
214        }
215        String value = Libcore.os.getenv(name);
216        return (value != null) ? value : defaultValue;
217    }
218
219    /*
220     * Returns an environment variable. No security checks are performed.
221     * @param var the name of the environment variable
222     * @return the value of the specified environment variable
223     */
224    private static native String getEnvByName(String name);
225
226    /**
227     * Returns an unmodifiable map of all available environment variables.
228     *
229     * @return the map representing all environment variables.
230     */
231    public static Map<String, String> getenv() {
232        Map<String, String> map = new HashMap<String, String>();
233        for (String entry : Libcore.os.environ()) {
234            int index = entry.indexOf('=');
235            if (index != -1) {
236                map.put(entry.substring(0, index), entry.substring(index + 1));
237            }
238        }
239        return new SystemEnvironment(map);
240    }
241
242    /**
243     * Returns the inherited channel from the creator of the current virtual
244     * machine.
245     *
246     * @return the inherited {@link Channel} or {@code null} if none exists.
247     * @throws IOException
248     *             if an I/O error occurred.
249     * @see SelectorProvider
250     * @see SelectorProvider#inheritedChannel()
251     */
252    public static Channel inheritedChannel() throws IOException {
253        return SelectorProvider.provider().inheritedChannel();
254    }
255
256    /**
257     * Returns the system properties. Note that this is not a copy, so that
258     * changes made to the returned Properties object will be reflected in
259     * subsequent calls to getProperty and getProperties.
260     *
261     * @return the system properties.
262     */
263    public static Properties getProperties() {
264        if (systemProperties == null) {
265            initSystemProperties();
266        }
267        return systemProperties;
268    }
269
270    private static void initSystemProperties() {
271        VMRuntime runtime = VMRuntime.getRuntime();
272        Properties p = new Properties();
273
274        String projectUrl = "http://www.android.com/";
275        String projectName = "The Android Project";
276
277        p.put("java.boot.class.path", runtime.bootClassPath());
278        p.put("java.class.path", runtime.classPath());
279
280        // None of these four are meaningful on Android, but these keys are guaranteed
281        // to be present for System.getProperty. For java.class.version, we use the maximum
282        // class file version that dx currently supports.
283        p.put("java.class.version", "50.0");
284        p.put("java.compiler", "");
285        p.put("java.ext.dirs", "");
286        p.put("java.version", "0");
287
288        p.put("java.home", getenv("JAVA_HOME", "/system"));
289
290        p.put("java.io.tmpdir", "/tmp");
291        p.put("java.library.path", getenv("LD_LIBRARY_PATH"));
292
293        p.put("java.specification.name", "Dalvik Core Library");
294        p.put("java.specification.vendor", projectName);
295        p.put("java.specification.version", "0.9");
296
297        p.put("java.vendor", projectName);
298        p.put("java.vendor.url", projectUrl);
299        p.put("java.vm.name", "Dalvik");
300        p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification");
301        p.put("java.vm.specification.vendor", projectName);
302        p.put("java.vm.specification.version", "0.9");
303        p.put("java.vm.vendor", projectName);
304        p.put("java.vm.version", runtime.vmVersion());
305
306        p.put("file.separator", "/");
307        p.put("line.separator", "\n");
308        p.put("path.separator", ":");
309
310        p.put("java.runtime.name", "Android Runtime");
311        p.put("java.runtime.version", "0.9");
312        p.put("java.vm.vendor.url", projectUrl);
313
314        p.put("file.encoding", "UTF-8");
315        p.put("user.language", "en");
316        p.put("user.region", "US");
317
318        p.put("user.home", getenv("HOME", ""));
319        p.put("user.name", getenv("USER", ""));
320
321        StructUtsname info = Libcore.os.uname();
322        p.put("os.arch", info.machine);
323        p.put("os.name", info.sysname);
324        p.put("os.version", info.release);
325
326        // Undocumented Android-only properties.
327        p.put("android.icu.library.version", ICU.getIcuVersion());
328        p.put("android.icu.unicode.version", ICU.getUnicodeVersion());
329        // TODO: it would be nice to have this but currently it causes circularity.
330        // p.put("android.tzdata.version", ZoneInfoDB.getVersion());
331        parsePropertyAssignments(p, specialProperties());
332
333        // Override built-in properties with settings from the command line.
334        parsePropertyAssignments(p, runtime.properties());
335
336        systemProperties = p;
337    }
338
339    /**
340     * Returns an array of "key=value" strings containing information not otherwise
341     * easily available, such as #defined library versions.
342     */
343    private static native String[] specialProperties();
344
345    /**
346     * Adds each element of 'assignments' to 'p', treating each element as an
347     * assignment in the form "key=value".
348     */
349    private static void parsePropertyAssignments(Properties p, String[] assignments) {
350        for (String assignment : assignments) {
351            int split = assignment.indexOf('=');
352            String key = assignment.substring(0, split);
353            String value = assignment.substring(split + 1);
354            p.put(key, value);
355        }
356    }
357
358    /**
359     * Returns the value of a particular system property or {@code null} if no
360     * such property exists.
361     *
362     * <p>The following properties are always provided by the Dalvik VM:
363     * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
364     * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
365     *     <td><b>Name</b></td>        <td><b>Meaning</b></td>                    <td><b>Example</b></td></tr>
366     * <tr><td>file.separator</td>     <td>{@link java.io.File#separator}</td>    <td>{@code /}</td></tr>
367     *
368     * <tr><td>java.class.path</td>    <td>System class path</td>                 <td>{@code .}</td></tr>
369     * <tr><td>java.class.version</td> <td>(Not useful on Android)</td>           <td>{@code 50.0}</td></tr>
370     * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
371     * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
372     * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
373     * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
374     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /system/lib}</td></tr>
375     * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
376     * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
377     * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
378     *
379     * <tr><td>java.specification.version</td>    <td>VM libraries version</td>        <td>{@code 0.9}</td></tr>
380     * <tr><td>java.specification.vendor</td>     <td>VM libraries vendor</td>         <td>{@code The Android Project}</td></tr>
381     * <tr><td>java.specification.name</td>       <td>VM libraries name</td>           <td>{@code Dalvik Core Library}</td></tr>
382     * <tr><td>java.vm.version</td>               <td>VM implementation version</td>   <td>{@code 1.2.0}</td></tr>
383     * <tr><td>java.vm.vendor</td>                <td>VM implementation vendor</td>    <td>{@code The Android Project}</td></tr>
384     * <tr><td>java.vm.name</td>                  <td>VM implementation name</td>      <td>{@code Dalvik}</td></tr>
385     * <tr><td>java.vm.specification.version</td> <td>VM specification version</td>    <td>{@code 0.9}</td></tr>
386     * <tr><td>java.vm.specification.vendor</td>  <td>VM specification vendor</td>     <td>{@code The Android Project}</td></tr>
387     * <tr><td>java.vm.specification.name</td>    <td>VM specification name</td>       <td>{@code Dalvik Virtual Machine Specification}</td></tr>
388     *
389     * <tr><td>line.separator</td>     <td>The system line separator</td>         <td>{@code \n}</td></tr>
390     *
391     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
392     * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
393     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
394     *
395     * <tr><td>path.separator</td>     <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
396     *
397     * <tr><td>user.dir</td>           <td>Base of non-absolute paths</td>        <td>{@code /}</td></tr>
398     * <tr><td>user.home</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
399     * <tr><td>user.name</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
400     *
401     * </table>
402     *
403     * <p>It is a mistake to try to override any of these. Doing so will have unpredictable results.
404     *
405     * @param propertyName
406     *            the name of the system property to look up.
407     * @return the value of the specified system property or {@code null} if the
408     *         property doesn't exist.
409     */
410    public static String getProperty(String propertyName) {
411        return getProperty(propertyName, null);
412    }
413
414    /**
415     * Returns the value of a particular system property. The {@code
416     * defaultValue} will be returned if no such property has been found.
417     *
418     * @param prop
419     *            the name of the system property to look up.
420     * @param defaultValue
421     *            the return value if the system property with the given name
422     *            does not exist.
423     * @return the value of the specified system property or the {@code
424     *         defaultValue} if the property does not exist.
425     */
426    public static String getProperty(String prop, String defaultValue) {
427        if (prop.isEmpty()) {
428            throw new IllegalArgumentException();
429        }
430        return getProperties().getProperty(prop, defaultValue);
431    }
432
433    /**
434     * Sets the value of a particular system property.
435     *
436     * @param prop
437     *            the name of the system property to be changed.
438     * @param value
439     *            the value to associate with the given property {@code prop}.
440     * @return the old value of the property or {@code null} if the property
441     *         didn't exist.
442     */
443    public static String setProperty(String prop, String value) {
444        if (prop.isEmpty()) {
445            throw new IllegalArgumentException();
446        }
447        return (String) getProperties().setProperty(prop, value);
448    }
449
450    /**
451     * Removes a specific system property.
452     *
453     * @param key
454     *            the name of the system property to be removed.
455     * @return the property value or {@code null} if the property didn't exist.
456     * @throws NullPointerException
457     *             if the argument {@code key} is {@code null}.
458     * @throws IllegalArgumentException
459     *             if the argument {@code key} is empty.
460     */
461    public static String clearProperty(String key) {
462        if (key == null) {
463            throw new NullPointerException("key == null");
464        }
465        if (key.isEmpty()) {
466            throw new IllegalArgumentException();
467        }
468        return (String) getProperties().remove(key);
469    }
470
471    /**
472     * Returns the {@link java.io.Console} associated with this VM, or null.
473     * Not all VMs will have an associated console. A console is typically only
474     * available for programs run from the command line.
475     * @since 1.6
476     */
477    public static Console console() {
478        return Console.getConsole();
479    }
480
481    /**
482     * Returns null. Android does not use {@code SecurityManager}. This method
483     * is only provided for source compatibility.
484     *
485     * @return null
486     */
487    public static SecurityManager getSecurityManager() {
488        return null;
489    }
490
491    /**
492     * Returns an integer hash code for the parameter. The hash code returned is
493     * the same one that would be returned by the method {@code
494     * java.lang.Object.hashCode()}, whether or not the object's class has
495     * overridden hashCode(). The hash code for {@code null} is {@code 0}.
496     *
497     * @param anObject
498     *            the object to calculate the hash code.
499     * @return the hash code for the given object.
500     * @see java.lang.Object#hashCode
501     */
502    public static native int identityHashCode(Object anObject);
503
504    /**
505     * Returns the system's line separator. On Android, this is {@code "\n"}. The value
506     * comes from the value of the {@code line.separator} system property when the VM
507     * starts. Later changes to the property will not affect the value returned by this
508     * method.
509     * @since 1.7
510     * @hide 1.7 - fix documentation references to "line.separator" in Formatter.
511     */
512    public static String lineSeparator() {
513        return lineSeparator;
514    }
515
516    /**
517     * Loads and links the dynamic library that is identified through the
518     * specified path. This method is similar to {@link #loadLibrary(String)},
519     * but it accepts a full path specification whereas {@code loadLibrary} just
520     * accepts the name of the library to load.
521     *
522     * @param pathName
523     *            the path of the file to be loaded.
524     */
525    public static void load(String pathName) {
526        Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader());
527    }
528
529    /**
530     * Loads and links the library with the specified name. The mapping of the
531     * specified library name to the full path for loading the library is
532     * implementation-dependent.
533     *
534     * @param libName
535     *            the name of the library to load.
536     * @throws UnsatisfiedLinkError
537     *             if the library could not be loaded.
538     */
539    public static void loadLibrary(String libName) {
540        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
541    }
542
543    /**
544     * @hide internal use only
545     */
546    public static void logE(String message) {
547        log('E', message, null);
548    }
549
550    /**
551     * @hide internal use only
552     */
553    public static void logE(String message, Throwable th) {
554        log('E', message, th);
555    }
556
557    /**
558     * @hide internal use only
559     */
560    public static void logI(String message) {
561        log('I', message, null);
562    }
563
564    /**
565     * @hide internal use only
566     */
567    public static void logI(String message, Throwable th) {
568        log('I', message, th);
569    }
570
571    /**
572     * @hide internal use only
573     */
574    public static void logW(String message) {
575        log('W', message, null);
576    }
577
578    /**
579     * @hide internal use only
580     */
581    public static void logW(String message, Throwable th) {
582        log('W', message, th);
583    }
584
585    private static native void log(char type, String message, Throwable th);
586
587    /**
588     * Provides a hint to the VM that it would be useful to attempt
589     * to perform any outstanding object finalization.
590     */
591    public static void runFinalization() {
592        Runtime.getRuntime().runFinalization();
593    }
594
595    /**
596     * Ensures that, when the VM is about to exit, all objects are
597     * finalized. Note that all finalization which occurs when the system is
598     * exiting is performed after all running threads have been terminated.
599     *
600     * @param flag
601     *            the flag determines if finalization on exit is enabled.
602     * @deprecated this method is unsafe.
603     */
604    @SuppressWarnings("deprecation")
605    @Deprecated
606    public static void runFinalizersOnExit(boolean flag) {
607        Runtime.runFinalizersOnExit(flag);
608    }
609
610    /**
611     * Sets all system properties. This does not take a copy; the passed-in object is used
612     * directly. Passing null causes the VM to reinitialize the properties to how they were
613     * when the VM was started.
614     */
615    public static void setProperties(Properties p) {
616        systemProperties = p;
617    }
618
619    /**
620     * Throws {@code SecurityException}.
621     *
622     * <p>Security managers do <i>not</i> provide a secure environment for
623     * executing untrusted code and are unsupported on Android. Untrusted code
624     * cannot be safely isolated within a single VM on Android, so this method
625     * <i>always</i> throws a {@code SecurityException}.
626     *
627     * @param sm a security manager
628     * @throws SecurityException always
629     */
630    public static void setSecurityManager(SecurityManager sm) {
631        if (sm != null) {
632            throw new SecurityException();
633        }
634    }
635
636    /**
637     * Returns the platform specific file name format for the shared library
638     * named by the argument.
639     *
640     * @param userLibName
641     *            the name of the library to look up.
642     * @return the platform specific filename for the library.
643     */
644    public static native String mapLibraryName(String userLibName);
645
646    /**
647     * Sets the value of the named static field in the receiver to the passed in
648     * argument.
649     *
650     * @param fieldName
651     *            the name of the field to set, one of in, out, or err
652     * @param stream
653     *            the new value of the field
654     */
655    private static native void setFieldImpl(String fieldName, String signature, Object stream);
656
657
658    /**
659     * The unmodifiable environment variables map. System.getenv() specifies
660     * that this map must throw when passed non-String keys.
661     */
662    static class SystemEnvironment extends AbstractMap<String, String> {
663        private final Map<String, String> map;
664
665        public SystemEnvironment(Map<String, String> map) {
666            this.map = Collections.unmodifiableMap(map);
667        }
668
669        @Override public Set<Entry<String, String>> entrySet() {
670            return map.entrySet();
671        }
672
673        @Override public String get(Object key) {
674            return map.get(toNonNullString(key));
675        }
676
677        @Override public boolean containsKey(Object key) {
678            return map.containsKey(toNonNullString(key));
679        }
680
681        @Override public boolean containsValue(Object value) {
682            return map.containsValue(toNonNullString(value));
683        }
684
685        private String toNonNullString(Object o) {
686            if (o == null) {
687                throw new NullPointerException("o == null");
688            }
689            return (String) o;
690        }
691    }
692}
693