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