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