Android-System类

System类是一些与系统相关的属性和方法的集合,而且在System类中所有的属性都是静态的,要想引用这些属性和方法,直接使用System调用即可,源码如下。

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.lang;

import android.system.ErrnoException;
import android.system.StructPasswd;
import android.system.StructUtsname;
import dalvik.system.VMRuntime;
import dalvik.system.VMStack;
import java.io.BufferedInputStream;
import java.io.Console;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import libcore.icu.ICU;
import libcore.io.Libcore;

/**
 * Provides access to system-related information and resources including
 * standard input and output. Enables clients to dynamically load native
 * libraries. All methods of this class are accessed in a static way and the
 * class itself can not be instantiated.
 *
 * @see Runtime
 */
public final class System {

    /**
     * Default input stream.
     */
    public static final InputStream in;

    /**
     * Default output stream.
     */
    public static final PrintStream out;

    /**
     * Default error output stream.
     */
    public static final PrintStream err;

    private static final String PATH_SEPARATOR = ":";
    private static final String LINE_SEPARATOR = "\n";
    private static final String FILE_SEPARATOR = "/";

    private static final Properties unchangeableSystemProperties;
    private static Properties systemProperties;

    /**
     * Dedicated lock for GC / Finalization logic.
     */
    private static final Object lock = new Object();

    /**
     * Whether or not we need to do a GC before running the finalizers.
     */
    private static boolean runGC;

    /**
     * If we just ran finalization, we might want to do a GC to free the finalized objects.
     * This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc().
     */
    private static boolean justRanFinalization;

    static {
        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
        in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
        unchangeableSystemProperties = initUnchangeableSystemProperties();
        systemProperties = createSystemProperties();

        addLegacyLocaleSystemProperties();
    }

    private static void addLegacyLocaleSystemProperties() {
        final String locale = getProperty("user.locale", "");
        if (!locale.isEmpty()) {
            Locale l = Locale.forLanguageTag(locale);
            setUnchangeableSystemProperty("user.language", l.getLanguage());
            setUnchangeableSystemProperty("user.region", l.getCountry());
            setUnchangeableSystemProperty("user.variant", l.getVariant());
        } else {
            // If "user.locale" isn't set we fall back to our old defaults of
            // language="en" and region="US" (if unset) and don't attempt to set it.
            // The Locale class will fall back to using user.language and
            // user.region if unset.
            final String language = getProperty("user.language", "");
            final String region = getProperty("user.region", "");

            if (language.isEmpty()) {
                setUnchangeableSystemProperty("user.language", "en");
            }

            if (region.isEmpty()) {
                setUnchangeableSystemProperty("user.region", "US");
            }
        }
    }

    /**
     * Sets the standard input stream to the given user defined input stream.
     *
     * @param newIn
     *            the user defined input stream to set as the standard input
     *            stream.
     */
    public static void setIn(InputStream newIn) {
        setFieldImpl("in", "Ljava/io/InputStream;", newIn);
    }

    /**
     * Sets the standard output stream to the given user defined output stream.
     *
     * @param newOut
     *            the user defined output stream to set as the standard output
     *            stream.
     */
    public static void setOut(PrintStream newOut) {
        setFieldImpl("out", "Ljava/io/PrintStream;", newOut);
    }

    /**
     * Sets the standard error output stream to the given user defined output
     * stream.
     *
     * @param newErr
     *            the user defined output stream to set as the standard error
     *            output stream.
     */
    public static void setErr(PrintStream newErr) {
        setFieldImpl("err", "Ljava/io/PrintStream;", newErr);
    }

    /**
     * Prevents this class from being instantiated.
     */
    private System() {
    }

    /**
     * Copies {@code length} elements from the array {@code src},
     * starting at offset {@code srcPos}, into the array {@code dst},
     * starting at offset {@code dstPos}.
     *
     * 

The source and destination arrays can be the same array, * in which case copying is performed as if the source elements * are first copied into a temporary array and then into the * destination array. * * @param src * the source array to copy the content. * @param srcPos * the starting index of the content in {@code src}. * @param dst * the destination array to copy the data into. * @param dstPos * the starting index for the copied content in {@code dst}. * @param length * the number of elements to be copied. */ public static native void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length); /** * The char array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD = 32; /** * The char[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD) { // Copy char by char for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyCharUnchecked(src, srcPos, dst, dstPos, length); } } /** * The char[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyCharUnchecked(char[] src, int srcPos, char[] dst, int dstPos, int length); /** * The byte array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_BYTE_ARRAY_THRESHOLD = 32; /** * The byte[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_BYTE_ARRAY_THRESHOLD) { // Copy byte by byte for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyByteUnchecked(src, srcPos, dst, dstPos, length); } } /** * The byte[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyByteUnchecked(byte[] src, int srcPos, byte[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_SHORT_ARRAY_THRESHOLD = 32; /** * The short[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_SHORT_ARRAY_THRESHOLD) { // Copy short by short for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyShortUnchecked(src, srcPos, dst, dstPos, length); } } /** * The short[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyShortUnchecked(short[] src, int srcPos, short[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_INT_ARRAY_THRESHOLD = 32; /** * The int[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_INT_ARRAY_THRESHOLD) { // Copy int by int for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyIntUnchecked(src, srcPos, dst, dstPos, length); } } /** * The int[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyIntUnchecked(int[] src, int srcPos, int[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_LONG_ARRAY_THRESHOLD = 32; /** * The long[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_LONG_ARRAY_THRESHOLD) { // Copy long by long for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyLongUnchecked(src, srcPos, dst, dstPos, length); } } /** * The long[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyLongUnchecked(long[] src, int srcPos, long[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_FLOAT_ARRAY_THRESHOLD = 32; /** * The float[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_FLOAT_ARRAY_THRESHOLD) { // Copy float by float for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for floater arrays. arraycopyFloatUnchecked(src, srcPos, dst, dstPos, length); } } /** * The float[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyFloatUnchecked(float[] src, int srcPos, float[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_DOUBLE_ARRAY_THRESHOLD = 32; /** * The double[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_DOUBLE_ARRAY_THRESHOLD) { // Copy double by double for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for floater arrays. arraycopyDoubleUnchecked(src, srcPos, dst, dstPos, length); } } /** * The double[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyDoubleUnchecked(double[] src, int srcPos, double[] dst, int dstPos, int length); /** * The short array length threshold below which to use a Java * (non-native) version of arraycopy() instead of the native * version. See b/7103825. */ private static final int ARRAYCOPY_SHORT_BOOLEAN_ARRAY_THRESHOLD = 32; /** * The boolean[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_BOOLEAN_ARRAY_THRESHOLD) { // Copy boolean by boolean for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for floater arrays. arraycopyBooleanUnchecked(src, srcPos, dst, dstPos, length); } } /** * The boolean[] specialized, unchecked, native version of * arraycopy(). This assumes error checking has been done. */ private static native void arraycopyBooleanUnchecked(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length); /** * Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC. * *

This method always returns UTC times, regardless of the system's time zone. * This is often called "Unix time" or "epoch time". * Use a {@link java.text.DateFormat} instance to format this time for display to a human. * *

This method shouldn't be used for measuring timeouts or * other elapsed time measurements, as changing the system time can affect * the results. Use {@link #nanoTime} for that. */ public static native long currentTimeMillis(); /** * Returns the current timestamp of the most precise timer available on the * local system, in nanoseconds. Equivalent to Linux's {@code CLOCK_MONOTONIC}. * *

This timestamp should only be used to measure a duration by comparing it * against another timestamp on the same device. * Values returned by this method do not have a defined correspondence to * wall clock times; the zero value is typically whenever the device last booted. * Use {@link #currentTimeMillis} if you want to know what time it is. */ public static native long nanoTime(); /** * Causes the VM to stop running and the program to exit with the given exit status. * If {@link #runFinalizersOnExit(boolean)} has been previously invoked with a * {@code true} argument, then all objects will be properly * garbage-collected and finalized first. */ public static void exit(int code) { Runtime.getRuntime().exit(code); } /** * Indicates to the VM that it would be a good time to run the * garbage collector. Note that this is a hint only. There is no guarantee * that the garbage collector will actually be run. */ public static void gc() { boolean shouldRunGC; synchronized(lock) { shouldRunGC = justRanFinalization; if (shouldRunGC) { justRanFinalization = false; } else { runGC = true; } } if (shouldRunGC) { Runtime.getRuntime().gc(); } } /** * Returns the value of the environment variable with the given name, or null if no such * variable exists. */ public static String getenv(String name) { if (name == null) { throw new NullPointerException("name == null"); } return Libcore.os.getenv(name); } /** * Returns an unmodifiable map of all environment variables to their values. */ public static Map getenv() { Map map = new HashMap(); for (String entry : Libcore.os.environ()) { int index = entry.indexOf('='); if (index != -1) { map.put(entry.substring(0, index), entry.substring(index + 1)); } } return new SystemEnvironment(map); } /** * Returns the inherited channel from the creator of the current virtual * machine. * * @return the inherited {@link Channel} or {@code null} if none exists. * @throws IOException * if an I/O error occurred. * @see SelectorProvider * @see SelectorProvider#inheritedChannel() */ public static Channel inheritedChannel() throws IOException { return SelectorProvider.provider().inheritedChannel(); } /** * Returns the system properties. Note that this is not a copy, so that * changes made to the returned Properties object will be reflected in * subsequent calls to getProperty and getProperties. * * @return the system properties. */ public static Properties getProperties() { return systemProperties; } private static Properties initUnchangeableSystemProperties() { VMRuntime runtime = VMRuntime.getRuntime(); Properties p = new Properties(); String projectUrl = "http://www.android.com/"; String projectName = "The Android Project"; p.put("java.boot.class.path", runtime.bootClassPath()); p.put("java.class.path", runtime.classPath()); // None of these four are meaningful on Android, but these keys are guaranteed // to be present for System.getProperty. For java.class.version, we use the maximum // class file version that dx currently supports. p.put("java.class.version", "50.0"); p.put("java.compiler", ""); p.put("java.ext.dirs", ""); p.put("java.version", "0"); // TODO: does this make any sense? Should we just leave java.home unset? String javaHome = getenv("JAVA_HOME"); if (javaHome == null) { javaHome = "/system"; } p.put("java.home", javaHome); p.put("java.specification.name", "Dalvik Core Library"); p.put("java.specification.vendor", projectName); p.put("java.specification.version", "0.9"); p.put("java.vendor", projectName); p.put("java.vendor.url", projectUrl); p.put("java.vm.name", "Dalvik"); p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification"); p.put("java.vm.specification.vendor", projectName); p.put("java.vm.specification.version", "0.9"); p.put("java.vm.vendor", projectName); p.put("java.vm.version", runtime.vmVersion()); p.put("java.runtime.name", "Android Runtime"); p.put("java.runtime.version", "0.9"); p.put("java.vm.vendor.url", projectUrl); p.put("file.encoding", "UTF-8"); try { StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid()); p.put("user.name", passwd.pw_name); } catch (ErrnoException exception) { throw new AssertionError(exception); } StructUtsname info = Libcore.os.uname(); p.put("os.arch", info.machine); p.put("os.name", info.sysname); p.put("os.version", info.release); // Undocumented Android-only properties. p.put("android.icu.library.version", ICU.getIcuVersion()); p.put("android.icu.unicode.version", ICU.getUnicodeVersion()); p.put("android.icu.cldr.version", ICU.getCldrVersion()); // Property override for ICU4J : this is the location of the ICU4C data. This // is prioritized over the properties in ICUConfig.properties. The issue with using // that is that it doesn't play well with jarjar and it needs complicated build rules // to change its default value. String icuDataPath = generateIcuDataPath(); p.put("android.icu.impl.ICUBinary.dataPath", icuDataPath); parsePropertyAssignments(p, specialProperties()); // Override built-in properties with settings from the command line. parsePropertyAssignments(p, runtime.properties()); if (p.containsKey("file.separator")) { logE("Ignoring command line argument: -Dfile.separator"); } if (p.containsKey("line.separator")) { logE("Ignoring command line argument: -Dline.separator"); } if (p.containsKey("path.separator")) { logE("Ignoring command line argument: -Dpath.separator"); } // We ignore values for "file.separator", "line.separator" and "path.separator" from // the command line. They're fixed on the operating systems we support. p.put("file.separator", FILE_SEPARATOR); p.put("line.separator", LINE_SEPARATOR); p.put("path.separator", PATH_SEPARATOR); return p; } /** * Inits an unchangeable system property with the given value. * * This is called from native code when the environment needs to change under native * bridge emulation. * * @hide also visible for tests. */ public static void setUnchangeableSystemProperty(String name, String value) { checkPropertyName(name); unchangeableSystemProperties.put(name, value); } private static void setDefaultChangeableProperties(Properties p) { // On Android, each app gets its own temporary directory. // (See android.app.ActivityThread.) This is just a fallback default, // useful only on the host. p.put("java.io.tmpdir", "/tmp"); // Android has always had an empty "user.home" (see docs for getProperty). // This is not useful for normal android apps which need to use android specific // APIs such as {@code Context.getFilesDir} and {@code Context.getCacheDir} but // we make it changeable for backward compatibility, so that they can change it // to a writeable location if required. p.put("user.home", ""); } private static Properties createSystemProperties() { Properties p = new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties); setDefaultChangeableProperties(p); return p; } private static String generateIcuDataPath() { StringBuilder icuDataPathBuilder = new StringBuilder(); // ICU should first look in ANDROID_DATA. This is used for (optional) timezone data. String dataIcuDataPath = getEnvironmentPath("ANDROID_DATA", "/misc/zoneinfo/current/icu"); if (dataIcuDataPath != null) { icuDataPathBuilder.append(dataIcuDataPath); } // ICU should always look in ANDROID_ROOT. String systemIcuDataPath = getEnvironmentPath("ANDROID_ROOT", "/usr/icu"); if (systemIcuDataPath != null) { if (icuDataPathBuilder.length() > 0) { icuDataPathBuilder.append(":"); } icuDataPathBuilder.append(systemIcuDataPath); } return icuDataPathBuilder.toString(); } /** * Creates a path by combining the value of an environment variable with a relative path. * Returns {@code null} if the environment variable is not set. */ private static String getEnvironmentPath(String environmentVariable, String path) { String variable = getenv(environmentVariable); if (variable == null) { return null; } return variable + path; } /** * Returns an array of "key=value" strings containing information not otherwise * easily available, such as #defined library versions. */ private static native String[] specialProperties(); /** * Adds each element of 'assignments' to 'p', treating each element as an * assignment in the form "key=value". */ private static void parsePropertyAssignments(Properties p, String[] assignments) { for (String assignment : assignments) { int split = assignment.indexOf('='); String key = assignment.substring(0, split); String value = assignment.substring(split + 1); p.put(key, value); } } /** * Returns the value of a particular system property or {@code null} if no * such property exists. * *

The following properties are always provided by the Dalvik VM:

*

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Name Meaning Example
file.separator {@link java.io.File#separator} {@code /}
java.class.path System class path {@code .}
java.class.version (Not useful on Android) {@code 50.0}
java.compiler (Not useful on Android) Empty
java.ext.dirs (Not useful on Android) Empty
java.home Location of the VM on the file system {@code /system}
java.io.tmpdir See {@link java.io.File#createTempFile} {@code /sdcard}
java.library.path Search path for JNI libraries {@code /vendor/lib:/system/lib}
java.vendor Human-readable VM vendor {@code The Android Project}
java.vendor.url URL for VM vendor's web site {@code http://www.android.com/}
java.version (Not useful on Android) {@code 0}
java.specification.version VM libraries version {@code 0.9}
java.specification.vendor VM libraries vendor {@code The Android Project}
java.specification.name VM libraries name {@code Dalvik Core Library}
java.vm.version VM implementation version {@code 1.2.0}
java.vm.vendor VM implementation vendor {@code The Android Project}
java.vm.name VM implementation name {@code Dalvik}
java.vm.specification.version VM specification version {@code 0.9}
java.vm.specification.vendor VM specification vendor {@code The Android Project}
java.vm.specification.name VM specification name {@code Dalvik Virtual Machine Specification}
line.separator The system line separator {@code \n}
os.arch OS architecture {@code armv7l}
os.name OS (kernel) name {@code Linux}
os.version OS (kernel) version {@code 2.6.32.9-g103d848}
path.separator See {@link java.io.File#pathSeparator} {@code :}
user.dir Base of non-absolute paths {@code /}
user.home (Not useful on Android) Empty
user.name (Not useful on Android) Empty
* *

All of the above properties except for {@code user.home} and {@code java.io.tmpdir} * cannot be modified. Any attempt to change them will be a no-op. * * @param propertyName * the name of the system property to look up. * @return the value of the specified system property or {@code null} if the * property doesn't exist. */ public static String getProperty(String propertyName) { return getProperty(propertyName, null); } /** * Returns the value of a particular system property. The {@code * defaultValue} will be returned if no such property has been found. */ public static String getProperty(String name, String defaultValue) { checkPropertyName(name); return systemProperties.getProperty(name, defaultValue); } /** * Sets the value of a particular system property. Most system properties * are read only and cannot be cleared or modified. See {@link #getProperty} for a * list of such properties. * * @return the old value of the property or {@code null} if the property * didn't exist. */ public static String setProperty(String name, String value) { checkPropertyName(name); return (String) systemProperties.setProperty(name, value); } /** * Removes a specific system property. Most system properties * are read only and cannot be cleared or modified. See {@link #getProperty} for a * list of such properties. * * @return the property value or {@code null} if the property didn't exist. * @throws NullPointerException * if the argument is {@code null}. * @throws IllegalArgumentException * if the argument is empty. */ public static String clearProperty(String name) { checkPropertyName(name); return (String) systemProperties.remove(name); } private static void checkPropertyName(String name) { if (name == null) { throw new NullPointerException("name == null"); } if (name.isEmpty()) { throw new IllegalArgumentException("name is empty"); } } /** * Returns the {@link java.io.Console} associated with this VM, or null. * Not all VMs will have an associated console. A console is typically only * available for programs run from the command line. * @since 1.6 */ public static Console console() { return Console.getConsole(); } /** * Returns null. Android does not use {@code SecurityManager}. This method * is only provided for source compatibility. * * @return null */ public static SecurityManager getSecurityManager() { return null; } /** * Returns an integer hash code for the parameter. The hash code returned is * the same one that would be returned by the method {@code * java.lang.Object.hashCode()}, whether or not the object's class has * overridden hashCode(). The hash code for {@code null} is {@code 0}. * * @param anObject * the object to calculate the hash code. * @return the hash code for the given object. * @see java.lang.Object#hashCode */ public static native int identityHashCode(Object anObject); /** * Returns the system's line separator. On Android, this is {@code "\n"}. The value comes from * the value of the {@code line.separator} system property. * *

On Android versions before Lollipop the {@code line.separator} system property can be * modified but this method continues to return the original value. The system property cannot * be modified on later versions of Android. * * @since 1.7 */ public static String lineSeparator() { return LINE_SEPARATOR; } /** * See {@link Runtime#load}. */ public static void load(String pathName) { Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader()); } /** * See {@link Runtime#loadLibrary}. */ public static void loadLibrary(String libName) { Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); } /** * @hide internal use only */ public static void logE(String message) { log('E', message, null); } /** * @hide internal use only */ public static void logE(String message, Throwable th) { log('E', message, th); } /** * @hide internal use only */ public static void logI(String message) { log('I', message, null); } /** * @hide internal use only */ public static void logI(String message, Throwable th) { log('I', message, th); } /** * @hide internal use only */ public static void logW(String message) { log('W', message, null); } /** * @hide internal use only */ public static void logW(String message, Throwable th) { log('W', message, th); } private static native void log(char type, String message, Throwable th); /** * Provides a hint to the VM that it would be useful to attempt * to perform any outstanding object finalization. */ public static void runFinalization() { boolean shouldRunGC; synchronized(lock) { shouldRunGC = runGC; runGC = false; } if (shouldRunGC) { Runtime.getRuntime().gc(); } Runtime.getRuntime().runFinalization(); synchronized(lock) { justRanFinalization = true; } } /** * Ensures that, when the VM is about to exit, all objects are * finalized. Note that all finalization which occurs when the system is * exiting is performed after all running threads have been terminated. * * @param flag * the flag determines if finalization on exit is enabled. * @deprecated This method is unsafe. */ @SuppressWarnings("deprecation") @Deprecated public static void runFinalizersOnExit(boolean flag) { Runtime.runFinalizersOnExit(flag); } /** * Attempts to set all system properties. Copies all properties from * {@code p} and discards system properties that are read only and cannot * be modified. See {@link #getProperty} for a list of such properties. */ public static void setProperties(Properties p) { PropertiesWithNonOverrideableDefaults userProperties = new PropertiesWithNonOverrideableDefaults(unchangeableSystemProperties); if (p != null) { userProperties.putAll(p); } else { // setProperties(null) is documented to restore defaults. setDefaultChangeableProperties(userProperties); } systemProperties = userProperties; } /** * Throws {@code SecurityException}. * *

Security managers do not provide a secure environment for * executing untrusted code and are unsupported on Android. Untrusted code * cannot be safely isolated within a single VM on Android, so this method * always throws a {@code SecurityException}. * * @param sm a security manager * @throws SecurityException always */ public static void setSecurityManager(SecurityManager sm) { if (sm != null) { throw new SecurityException(); } } /** * Returns the platform specific file name format for the shared library * named by the argument. On Android, this would turn {@code "MyLibrary"} into * {@code "libMyLibrary.so"}. */ public static String mapLibraryName(String nickname) { if (nickname == null) { throw new NullPointerException("nickname == null"); } return "lib" + nickname + ".so"; } /** * Used to set System.err, System.in, and System.out. */ private static native void setFieldImpl(String field, String signature, Object stream); /** * A properties class that prohibits changes to any of the properties * contained in its defaults. */ static final class PropertiesWithNonOverrideableDefaults extends Properties { PropertiesWithNonOverrideableDefaults(Properties defaults) { super(defaults); } @Override public Object put(Object key, Object value) { if (defaults.containsKey(key)) { logE("Ignoring attempt to set property \"" + key + "\" to value \"" + value + "\"."); return defaults.get(key); } return super.put(key, value); } @Override public Object remove(Object key) { if (defaults.containsKey(key)) { logE("Ignoring attempt to remove property \"" + key + "\"."); return null; } return super.remove(key); } } /** * The unmodifiable environment variables map. System.getenv() specifies * that this map must throw when passed non-String keys. */ static class SystemEnvironment extends AbstractMap { private final Map map; public SystemEnvironment(Map map) { this.map = Collections.unmodifiableMap(map); } @Override public Set> entrySet() { return map.entrySet(); } @Override public String get(Object key) { return map.get(toNonNullString(key)); } @Override public boolean containsKey(Object key) { return map.containsKey(toNonNullString(key)); } @Override public boolean containsValue(Object value) { return map.containsValue(toNonNullString(value)); } private String toNonNullString(Object o) { if (o == null) { throw new NullPointerException("o == null"); } return (String) o; } } }

你可能感兴趣的:(Android)