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