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}.
     *
     * <p>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.
     *
     * <p>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.
     *
     * <p>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}.
     *
     * <p>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<String, String> getenv() {
        Map<String, String> map = new HashMap<String, String>();
        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.
     *
     * <p>The following properties are always provided by the Dalvik VM:</p>
     * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
     * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
     *     <td><b>Name</b></td>        <td><b>Meaning</b></td>                    <td><b>Example</b></td></tr>
     * <tr><td>file.separator</td>     <td>{@link java.io.File#separator}</td>    <td>{@code /}</td></tr>
     *
     * <tr><td>java.class.path</td>    <td>System class path</td>                 <td>{@code .}</td></tr>
     * <tr><td>java.class.version</td> <td>(Not useful on Android)</td>           <td>{@code 50.0}</td></tr>
     * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
     * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
     * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
     * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /vendor/lib:/system/lib}</td></tr>
     * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
     * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
     * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
     *
     * <tr><td>java.specification.version</td>    <td>VM libraries version</td>        <td>{@code 0.9}</td></tr>
     * <tr><td>java.specification.vendor</td>     <td>VM libraries vendor</td>         <td>{@code The Android Project}</td></tr>
     * <tr><td>java.specification.name</td>       <td>VM libraries name</td>           <td>{@code Dalvik Core Library}</td></tr>
     * <tr><td>java.vm.version</td>               <td>VM implementation version</td>   <td>{@code 1.2.0}</td></tr>
     * <tr><td>java.vm.vendor</td>                <td>VM implementation vendor</td>    <td>{@code The Android Project}</td></tr>
     * <tr><td>java.vm.name</td>                  <td>VM implementation name</td>      <td>{@code Dalvik}</td></tr>
     * <tr><td>java.vm.specification.version</td> <td>VM specification version</td>    <td>{@code 0.9}</td></tr>
     * <tr><td>java.vm.specification.vendor</td>  <td>VM specification vendor</td>     <td>{@code The Android Project}</td></tr>
     * <tr><td>java.vm.specification.name</td>    <td>VM specification name</td>       <td>{@code Dalvik Virtual Machine Specification}</td></tr>
     *
     * <tr><td>line.separator</td>     <td>The system line separator</td>         <td>{@code \n}</td></tr>
     *
     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
     * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
     *
     * <tr><td>path.separator</td>     <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
     *
     * <tr><td>user.dir</td>           <td>Base of non-absolute paths</td>        <td>{@code /}</td></tr>
     * <tr><td>user.home</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
     * <tr><td>user.name</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
     *
     * </table>
     *
     * <p> All of the above properties except for {@code user.home} and {@code java.io.tmpdir}
     * <b>cannot be modified</b>. 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.
     *
     * <p>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}.
     *
     * <p>Security managers do <i>not</i> 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
     * <i>always</i> 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<String, String> {
        private final Map<String, String> map;

        public SystemEnvironment(Map<String, String> map) {
            this.map = Collections.unmodifiableMap(map);
        }

        @Override public Set<Entry<String, String>> 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;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值