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