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