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