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