| 1 | /* Runtime.java -- access to the VM process
|
|---|
| 2 | Copyright (C) 1998, 2002 Free Software Foundation
|
|---|
| 3 |
|
|---|
| 4 | This file is part of GNU Classpath.
|
|---|
| 5 |
|
|---|
| 6 | GNU Classpath is free software; you can redistribute it and/or modify
|
|---|
| 7 | it under the terms of the GNU General Public License as published by
|
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 9 | any later version.
|
|---|
| 10 |
|
|---|
| 11 | GNU Classpath is distributed in the hope that it will be useful, but
|
|---|
| 12 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU General Public License
|
|---|
| 17 | along with GNU Classpath; see the file COPYING. If not, write to the
|
|---|
| 18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|---|
| 19 | 02111-1307 USA.
|
|---|
| 20 |
|
|---|
| 21 | Linking this library statically or dynamically with other modules is
|
|---|
| 22 | making a combined work based on this library. Thus, the terms and
|
|---|
| 23 | conditions of the GNU General Public License cover the whole
|
|---|
| 24 | combination.
|
|---|
| 25 |
|
|---|
| 26 | As a special exception, the copyright holders of this library give you
|
|---|
| 27 | permission to link this library with independent modules to produce an
|
|---|
| 28 | executable, regardless of the license terms of these independent
|
|---|
| 29 | modules, and to copy and distribute the resulting executable under
|
|---|
| 30 | terms of your choice, provided that you also meet, for each linked
|
|---|
| 31 | independent module, the terms and conditions of the license of that
|
|---|
| 32 | module. An independent module is a module which is not derived from
|
|---|
| 33 | or based on this library. If you modify this library, you may extend
|
|---|
| 34 | this exception to your version of the library, but you are not
|
|---|
| 35 | obligated to do so. If you do not wish to do so, delete this
|
|---|
| 36 | exception statement from your version. */
|
|---|
| 37 |
|
|---|
| 38 | package java.lang;
|
|---|
| 39 |
|
|---|
| 40 | import java.io.File;
|
|---|
| 41 | import java.io.InputStream;
|
|---|
| 42 | import java.io.IOException;
|
|---|
| 43 | import java.io.OutputStream;
|
|---|
| 44 | import java.util.HashSet;
|
|---|
| 45 | import java.util.Iterator;
|
|---|
| 46 | import java.util.Properties;
|
|---|
| 47 | import java.util.Set;
|
|---|
| 48 | import java.util.StringTokenizer;
|
|---|
| 49 |
|
|---|
| 50 | /**
|
|---|
| 51 | * Runtime represents the Virtual Machine.
|
|---|
| 52 | *
|
|---|
| 53 | * @author John Keiser
|
|---|
| 54 | * @author Eric Blake <[email protected]>
|
|---|
| 55 | * @status still missing 1.4 functionality
|
|---|
| 56 | */
|
|---|
| 57 | // No idea why this class isn't final, since you can't build a subclass!
|
|---|
| 58 | public class Runtime
|
|---|
| 59 | {
|
|---|
| 60 | /**
|
|---|
| 61 | * The library path, to search when loading libraries. We can also safely use
|
|---|
| 62 | * this as a lock for synchronization.
|
|---|
| 63 | */
|
|---|
| 64 | private final String[] libpath;
|
|---|
| 65 |
|
|---|
| 66 | /**
|
|---|
| 67 | * The current security manager. This is located here instead of in
|
|---|
| 68 | * Runtime, to avoid security problems, as well as bootstrap issues.
|
|---|
| 69 | * Make sure to access it in a thread-safe manner; it is package visible
|
|---|
| 70 | * to avoid overhead in java.lang.
|
|---|
| 71 | */
|
|---|
| 72 | static SecurityManager securityManager;
|
|---|
| 73 |
|
|---|
| 74 | /**
|
|---|
| 75 | * The default properties defined by the system. This is likewise located
|
|---|
| 76 | * here instead of in Runtime, to avoid bootstrap issues; it is package
|
|---|
| 77 | * visible to avoid overhead in java.lang. Note that System will add a
|
|---|
| 78 | * few more properties to this collection, but that after that, it is
|
|---|
| 79 | * treated as read-only.
|
|---|
| 80 | *
|
|---|
| 81 | * No matter what class you start initialization with, it defers to the
|
|---|
| 82 | * superclass, therefore Object.<clinit> will be the first Java code
|
|---|
| 83 | * executed. From there, the bootstrap sequence, up to the point that
|
|---|
| 84 | * native libraries are loaded (as of March 24, when I traced this
|
|---|
| 85 | * manually) is as follows:
|
|---|
| 86 | *
|
|---|
| 87 | * Object.<clinit> uses a String literal, possibly triggering initialization
|
|---|
| 88 | * String.<clinit> calls WeakHashMap.<init>, triggering initialization
|
|---|
| 89 | * AbstractMap, WeakHashMap, WeakHashMap$1 have no dependencies
|
|---|
| 90 | * String.<clinit> calls CaseInsensitiveComparator.<init>, triggering
|
|---|
| 91 | * initialization
|
|---|
| 92 | * CaseInsensitiveComparator has no dependencies
|
|---|
| 93 | * Object.<clinit> calls System.loadLibrary, triggering initialization
|
|---|
| 94 | * System.<clinit> calls System.loadLibrary
|
|---|
| 95 | * System.loadLibrary calls Runtime.getRuntime, triggering initialization
|
|---|
| 96 | * Runtime.<clinit> calls Properties.<init>, triggering initialization
|
|---|
| 97 | * Dictionary, Hashtable, and Properties have no dependencies
|
|---|
| 98 | * Runtime.<clinit> calls insertSystemProperties; the VM must make sure
|
|---|
| 99 | * that there are not any harmful dependencies
|
|---|
| 100 | * Runtime.<clinit> calls Runtime.<init>
|
|---|
| 101 | * Runtime.<init> calls StringTokenizer.<init>, triggering initialization
|
|---|
| 102 | * StringTokenizer has no dependencies
|
|---|
| 103 | * System.loadLibrary calls Runtime.loadLibrary
|
|---|
| 104 | * Runtime.loadLibrary should be able to load the library, although it
|
|---|
| 105 | * will probably set off another string of initializations from
|
|---|
| 106 | * ClassLoader first
|
|---|
| 107 | */
|
|---|
| 108 | static Properties defaultProperties = new Properties();
|
|---|
| 109 | static
|
|---|
| 110 | {
|
|---|
| 111 | insertSystemProperties(defaultProperties);
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | /**
|
|---|
| 115 | * The thread that started the exit sequence. Access to this field must
|
|---|
| 116 | * be thread-safe; lock on libpath to avoid deadlock with user code.
|
|---|
| 117 | * <code>runFinalization()</code> may want to look at this to see if ALL
|
|---|
| 118 | * finalizers should be run, because the virtual machine is about to halt.
|
|---|
| 119 | */
|
|---|
| 120 | private Thread exitSequence;
|
|---|
| 121 |
|
|---|
| 122 | /**
|
|---|
| 123 | * All shutdown hooks. This is initialized lazily, and set to null once all
|
|---|
| 124 | * shutdown hooks have run. Access to this field must be thread-safe; lock
|
|---|
| 125 | * on libpath to avoid deadlock with user code.
|
|---|
| 126 | */
|
|---|
| 127 | private Set shutdownHooks;
|
|---|
| 128 |
|
|---|
| 129 | /** True if we should finalize on exit. */
|
|---|
| 130 | private boolean finalizeOnExit;
|
|---|
| 131 |
|
|---|
| 132 | /**
|
|---|
| 133 | * The one and only runtime instance. This must appear after the default
|
|---|
| 134 | * properties have been initialized by the VM.
|
|---|
| 135 | */
|
|---|
| 136 | private static final Runtime current = new Runtime();
|
|---|
| 137 |
|
|---|
| 138 | /**
|
|---|
| 139 | * Not instantiable by a user, this should only create one instance.
|
|---|
| 140 | */
|
|---|
| 141 | private Runtime()
|
|---|
| 142 | {
|
|---|
| 143 | if (current != null)
|
|---|
| 144 | throw new InternalError("Attempt to recreate Runtime");
|
|---|
| 145 |
|
|---|
| 146 | // We don't use libpath in the libgcj implementation. We still
|
|---|
| 147 | // set it to something to allow the various synchronizations to
|
|---|
| 148 | // work.
|
|---|
| 149 | libpath = new String[0];
|
|---|
| 150 |
|
|---|
| 151 | init ();
|
|---|
| 152 | }
|
|---|
| 153 |
|
|---|
| 154 | /**
|
|---|
| 155 | * Get the current Runtime object for this JVM. This is necessary to access
|
|---|
| 156 | * the many instance methods of this class.
|
|---|
| 157 | *
|
|---|
| 158 | * @return the current Runtime object
|
|---|
| 159 | */
|
|---|
| 160 | public static Runtime getRuntime()
|
|---|
| 161 | {
|
|---|
| 162 | return current;
|
|---|
| 163 | }
|
|---|
| 164 |
|
|---|
| 165 | /**
|
|---|
| 166 | * Exit the Java runtime. This method will either throw a SecurityException
|
|---|
| 167 | * or it will never return. The status code is returned to the system; often
|
|---|
| 168 | * a non-zero status code indicates an abnormal exit. Of course, there is a
|
|---|
| 169 | * security check, <code>checkExit(status)</code>.
|
|---|
| 170 | *
|
|---|
| 171 | * <p>First, all shutdown hooks are run, in unspecified order, and
|
|---|
| 172 | * concurrently. Next, if finalization on exit has been enabled, all pending
|
|---|
| 173 | * finalizers are run. Finally, the system calls <code>halt</code>.
|
|---|
| 174 | *
|
|---|
| 175 | * <p>If this is run a second time after shutdown has already started, there
|
|---|
| 176 | * are two actions. If shutdown hooks are still executing, it blocks
|
|---|
| 177 | * indefinitely. Otherwise, if the status is nonzero it halts immediately;
|
|---|
| 178 | * if it is zero, it blocks indefinitely. This is typically called by
|
|---|
| 179 | * <code>System.exit</code>.
|
|---|
| 180 | *
|
|---|
| 181 | * @param status the status to exit with
|
|---|
| 182 | * @throws SecurityException if permission is denied
|
|---|
| 183 | * @see #addShutdownHook(Thread)
|
|---|
| 184 | * @see #runFinalizersOnExit(boolean)
|
|---|
| 185 | * @see #runFinalization()
|
|---|
| 186 | * @see #halt(int)
|
|---|
| 187 | */
|
|---|
| 188 | public void exit(int status)
|
|---|
| 189 | {
|
|---|
| 190 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 191 | if (sm != null)
|
|---|
| 192 | sm.checkExit(status);
|
|---|
| 193 | boolean first = false;
|
|---|
| 194 | synchronized (libpath) // Synch on libpath, not this, to avoid deadlock.
|
|---|
| 195 | {
|
|---|
| 196 | if (exitSequence == null)
|
|---|
| 197 | {
|
|---|
| 198 | first = true;
|
|---|
| 199 | exitSequence = Thread.currentThread();
|
|---|
| 200 | if (shutdownHooks != null)
|
|---|
| 201 | {
|
|---|
| 202 | Iterator i = shutdownHooks.iterator();
|
|---|
| 203 | while (i.hasNext()) // Start all shutdown hooks.
|
|---|
| 204 | try
|
|---|
| 205 | {
|
|---|
| 206 | ((Thread) i.next()).start();
|
|---|
| 207 | }
|
|---|
| 208 | catch (IllegalThreadStateException e)
|
|---|
| 209 | {
|
|---|
| 210 | i.remove();
|
|---|
| 211 | }
|
|---|
| 212 | }
|
|---|
| 213 | }
|
|---|
| 214 | }
|
|---|
| 215 | if (first)
|
|---|
| 216 | {
|
|---|
| 217 | if (shutdownHooks != null)
|
|---|
| 218 | {
|
|---|
| 219 | // Check progress of all shutdown hooks. As a hook completes,
|
|---|
| 220 | // remove it from the set. If a hook calls exit, it removes
|
|---|
| 221 | // itself from the set, then waits indefinitely on the
|
|---|
| 222 | // exitSequence thread. Once the set is empty, set it to null to
|
|---|
| 223 | // signal all finalizer threads that halt may be called.
|
|---|
| 224 | while (! shutdownHooks.isEmpty())
|
|---|
| 225 | {
|
|---|
| 226 | Thread[] hooks;
|
|---|
| 227 | synchronized (libpath)
|
|---|
| 228 | {
|
|---|
| 229 | hooks = new Thread[shutdownHooks.size()];
|
|---|
| 230 | shutdownHooks.toArray(hooks);
|
|---|
| 231 | }
|
|---|
| 232 | for (int i = hooks.length; --i >= 0; )
|
|---|
| 233 | if (! hooks[i].isAlive())
|
|---|
| 234 | synchronized (libpath)
|
|---|
| 235 | {
|
|---|
| 236 | shutdownHooks.remove(hooks[i]);
|
|---|
| 237 | }
|
|---|
| 238 | try
|
|---|
| 239 | {
|
|---|
| 240 | exitSequence.sleep(1); // Give other threads a chance.
|
|---|
| 241 | }
|
|---|
| 242 | catch (InterruptedException e)
|
|---|
| 243 | {
|
|---|
| 244 | // Ignore, the next loop just starts sooner.
|
|---|
| 245 | }
|
|---|
| 246 | }
|
|---|
| 247 | synchronized (libpath)
|
|---|
| 248 | {
|
|---|
| 249 | shutdownHooks = null;
|
|---|
| 250 | }
|
|---|
| 251 | }
|
|---|
| 252 | // XXX Right now, it is the VM that knows whether runFinalizersOnExit
|
|---|
| 253 | // is true; so the VM must look at exitSequence to decide whether
|
|---|
| 254 | // this should be run on every object.
|
|---|
| 255 | runFinalization();
|
|---|
| 256 | }
|
|---|
| 257 | else
|
|---|
| 258 | synchronized (libpath)
|
|---|
| 259 | {
|
|---|
| 260 | if (shutdownHooks != null)
|
|---|
| 261 | {
|
|---|
| 262 | shutdownHooks.remove(Thread.currentThread());
|
|---|
| 263 | status = 0; // Change status to enter indefinite wait.
|
|---|
| 264 | }
|
|---|
| 265 | }
|
|---|
| 266 |
|
|---|
| 267 | if (first || status > 0)
|
|---|
| 268 | halt(status);
|
|---|
| 269 | while (true)
|
|---|
| 270 | try
|
|---|
| 271 | {
|
|---|
| 272 | exitSequence.join();
|
|---|
| 273 | }
|
|---|
| 274 | catch (InterruptedException e)
|
|---|
| 275 | {
|
|---|
| 276 | // Ignore, we've suspended indefinitely to let all shutdown
|
|---|
| 277 | // hooks complete, and to let any non-zero exits through, because
|
|---|
| 278 | // this is a duplicate call to exit(0).
|
|---|
| 279 | }
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | /**
|
|---|
| 283 | * Register a new shutdown hook. This is invoked when the program exits
|
|---|
| 284 | * normally (because all non-daemon threads ended, or because
|
|---|
| 285 | * <code>System.exit</code> was invoked), or when the user terminates
|
|---|
| 286 | * the virtual machine (such as by typing ^C, or logging off). There is
|
|---|
| 287 | * a security check to add hooks,
|
|---|
| 288 | * <code>RuntimePermission("shutdownHooks")<code>.
|
|---|
| 289 | *
|
|---|
| 290 | * <p>The hook must be an initialized, but unstarted Thread. The threads
|
|---|
| 291 | * are run concurrently, and started in an arbitrary order; and user
|
|---|
| 292 | * threads or daemons may still be running. Once shutdown hooks have
|
|---|
| 293 | * started, they must all complete, or else you must use <code>halt</code>,
|
|---|
| 294 | * to actually finish the shutdown sequence. Attempts to modify hooks
|
|---|
| 295 | * after shutdown has started result in IllegalStateExceptions.
|
|---|
| 296 | *
|
|---|
| 297 | * <p>It is imperative that you code shutdown hooks defensively, as you
|
|---|
| 298 | * do not want to deadlock, and have no idea what other hooks will be
|
|---|
| 299 | * running concurrently. It is also a good idea to finish quickly, as the
|
|---|
| 300 | * virtual machine really wants to shut down!
|
|---|
| 301 | *
|
|---|
| 302 | * <p>There are no guarantees that such hooks will run, as there are ways
|
|---|
| 303 | * to forcibly kill a process. But in such a drastic case, shutdown hooks
|
|---|
| 304 | * would do little for you in the first place.
|
|---|
| 305 | *
|
|---|
| 306 | * @param hook an initialized, unstarted Thread
|
|---|
| 307 | * @throws IllegalArgumentException if the hook is already registered or run
|
|---|
| 308 | * @throws IllegalStateException if the virtual machine is already in
|
|---|
| 309 | * the shutdown sequence
|
|---|
| 310 | * @throws SecurityException if permission is denied
|
|---|
| 311 | * @since 1.3
|
|---|
| 312 | * @see #removeShutdownHook(Thread)
|
|---|
| 313 | * @see #exit(int)
|
|---|
| 314 | * @see #halt(int)
|
|---|
| 315 | */
|
|---|
| 316 | public void addShutdownHook(Thread hook)
|
|---|
| 317 | {
|
|---|
| 318 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 319 | if (sm != null)
|
|---|
| 320 | sm.checkPermission(new RuntimePermission("shutdownHooks"));
|
|---|
| 321 | if (hook.isAlive() || hook.getThreadGroup() == null)
|
|---|
| 322 | throw new IllegalArgumentException();
|
|---|
| 323 | synchronized (libpath)
|
|---|
| 324 | {
|
|---|
| 325 | if (exitSequence != null)
|
|---|
| 326 | throw new IllegalStateException();
|
|---|
| 327 | if (shutdownHooks == null)
|
|---|
| 328 | shutdownHooks = new HashSet(); // Lazy initialization.
|
|---|
| 329 | if (! shutdownHooks.add(hook))
|
|---|
| 330 | throw new IllegalArgumentException();
|
|---|
| 331 | }
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | /**
|
|---|
| 335 | * De-register a shutdown hook. As when you registered it, there is a
|
|---|
| 336 | * security check to remove hooks,
|
|---|
| 337 | * <code>RuntimePermission("shutdownHooks")<code>.
|
|---|
| 338 | *
|
|---|
| 339 | * @param hook the hook to remove
|
|---|
| 340 | * @return true if the hook was successfully removed, false if it was not
|
|---|
| 341 | * registered in the first place
|
|---|
| 342 | * @throws IllegalStateException if the virtual machine is already in
|
|---|
| 343 | * the shutdown sequence
|
|---|
| 344 | * @throws SecurityException if permission is denied
|
|---|
| 345 | * @since 1.3
|
|---|
| 346 | * @see #addShutdownHook(Thread)
|
|---|
| 347 | * @see #exit(int)
|
|---|
| 348 | * @see #halt(int)
|
|---|
| 349 | */
|
|---|
| 350 | public boolean removeShutdownHook(Thread hook)
|
|---|
| 351 | {
|
|---|
| 352 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 353 | if (sm != null)
|
|---|
| 354 | sm.checkPermission(new RuntimePermission("shutdownHooks"));
|
|---|
| 355 | synchronized (libpath)
|
|---|
| 356 | {
|
|---|
| 357 | if (exitSequence != null)
|
|---|
| 358 | throw new IllegalStateException();
|
|---|
| 359 | if (shutdownHooks != null)
|
|---|
| 360 | return shutdownHooks.remove(hook);
|
|---|
| 361 | }
|
|---|
| 362 | return false;
|
|---|
| 363 | }
|
|---|
| 364 |
|
|---|
| 365 | /**
|
|---|
| 366 | * Forcibly terminate the virtual machine. This call never returns. It is
|
|---|
| 367 | * much more severe than <code>exit</code>, as it bypasses all shutdown
|
|---|
| 368 | * hooks and initializers. Use caution in calling this! Of course, there is
|
|---|
| 369 | * a security check, <code>checkExit(status)</code>.
|
|---|
| 370 | *
|
|---|
| 371 | * @param status the status to exit with
|
|---|
| 372 | * @throws SecurityException if permission is denied
|
|---|
| 373 | * @since 1.3
|
|---|
| 374 | * @see #exit(int)
|
|---|
| 375 | * @see #addShutdownHook(Thread)
|
|---|
| 376 | */
|
|---|
| 377 | public void halt(int status)
|
|---|
| 378 | {
|
|---|
| 379 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 380 | if (sm != null)
|
|---|
| 381 | sm.checkExit(status);
|
|---|
| 382 | exitInternal(status);
|
|---|
| 383 | }
|
|---|
| 384 |
|
|---|
| 385 | /**
|
|---|
| 386 | * Tell the VM to run the finalize() method on every single Object before
|
|---|
| 387 | * it exits. Note that the JVM may still exit abnormally and not perform
|
|---|
| 388 | * this, so you still don't have a guarantee. And besides that, this is
|
|---|
| 389 | * inherently unsafe in multi-threaded code, as it may result in deadlock
|
|---|
| 390 | * as multiple threads compete to manipulate objects. This value defaults to
|
|---|
| 391 | * <code>false</code>. There is a security check, <code>checkExit(0)</code>.
|
|---|
| 392 | *
|
|---|
| 393 | * @param finalizeOnExit whether to finalize all Objects on exit
|
|---|
| 394 | * @throws SecurityException if permission is denied
|
|---|
| 395 | * @see #exit(int)
|
|---|
| 396 | * @see #gc()
|
|---|
| 397 | * @since 1.1
|
|---|
| 398 | * @deprecated never rely on finalizers to do a clean, thread-safe,
|
|---|
| 399 | * mop-up from your code
|
|---|
| 400 | */
|
|---|
| 401 | public static void runFinalizersOnExit(boolean finalizeOnExit)
|
|---|
| 402 | {
|
|---|
| 403 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 404 | if (sm != null)
|
|---|
| 405 | sm.checkExit(0);
|
|---|
| 406 | current.finalizeOnExit = finalizeOnExit;
|
|---|
| 407 | }
|
|---|
| 408 |
|
|---|
| 409 | /**
|
|---|
| 410 | * Create a new subprocess with the specified command line. Calls
|
|---|
| 411 | * <code>exec(cmdline, null, null)<code>. A security check is performed,
|
|---|
| 412 | * <code>checkExec</code>.
|
|---|
| 413 | *
|
|---|
| 414 | * @param cmdline the command to call
|
|---|
| 415 | * @return the Process object
|
|---|
| 416 | * @throws SecurityException if permission is denied
|
|---|
| 417 | * @throws IOException if an I/O error occurs
|
|---|
| 418 | * @throws NullPointerException if cmdline is null
|
|---|
| 419 | * @throws IndexOutOfBoundsException if cmdline is ""
|
|---|
| 420 | */
|
|---|
| 421 | public Process exec(String cmdline) throws IOException
|
|---|
| 422 | {
|
|---|
| 423 | return exec(cmdline, null, null);
|
|---|
| 424 | }
|
|---|
| 425 |
|
|---|
| 426 | /**
|
|---|
| 427 | * Create a new subprocess with the specified command line and environment.
|
|---|
| 428 | * If the environment is null, the process inherits the environment of
|
|---|
| 429 | * this process. Calls <code>exec(cmdline, env, null)</code>. A security
|
|---|
| 430 | * check is performed, <code>checkExec</code>.
|
|---|
| 431 | *
|
|---|
| 432 | * @param cmdline the command to call
|
|---|
| 433 | * @param env the environment to use, in the format name=value
|
|---|
| 434 | * @return the Process object
|
|---|
| 435 | * @throws SecurityException if permission is denied
|
|---|
| 436 | * @throws IOException if an I/O error occurs
|
|---|
| 437 | * @throws NullPointerException if cmdline is null, or env has null entries
|
|---|
| 438 | * @throws IndexOutOfBoundsException if cmdline is ""
|
|---|
| 439 | */
|
|---|
| 440 | public Process exec(String cmdline, String[] env) throws IOException
|
|---|
| 441 | {
|
|---|
| 442 | return exec(cmdline, env, null);
|
|---|
| 443 | }
|
|---|
| 444 |
|
|---|
| 445 | /**
|
|---|
| 446 | * Create a new subprocess with the specified command line, environment, and
|
|---|
| 447 | * working directory. If the environment is null, the process inherits the
|
|---|
| 448 | * environment of this process. If the directory is null, the process uses
|
|---|
| 449 | * the current working directory. This splits cmdline into an array, using
|
|---|
| 450 | * the default StringTokenizer, then calls
|
|---|
| 451 | * <code>exec(cmdArray, env, dir)</code>. A security check is performed,
|
|---|
| 452 | * <code>checkExec</code>.
|
|---|
| 453 | *
|
|---|
| 454 | * @param cmdline the command to call
|
|---|
| 455 | * @param env the environment to use, in the format name=value
|
|---|
| 456 | * @param dir the working directory to use
|
|---|
| 457 | * @return the Process object
|
|---|
| 458 | * @throws SecurityException if permission is denied
|
|---|
| 459 | * @throws IOException if an I/O error occurs
|
|---|
| 460 | * @throws NullPointerException if cmdline is null, or env has null entries
|
|---|
| 461 | * @throws IndexOutOfBoundsException if cmdline is ""
|
|---|
| 462 | * @since 1.3
|
|---|
| 463 | */
|
|---|
| 464 | public Process exec(String cmdline, String[] env, File dir)
|
|---|
| 465 | throws IOException
|
|---|
| 466 | {
|
|---|
| 467 | StringTokenizer t = new StringTokenizer(cmdline);
|
|---|
| 468 | String[] cmd = new String[t.countTokens()];
|
|---|
| 469 | for (int i = 0; i < cmd.length; i++)
|
|---|
| 470 | cmd[i] = t.nextToken();
|
|---|
| 471 | return exec(cmd, env, dir);
|
|---|
| 472 | }
|
|---|
| 473 |
|
|---|
| 474 | /**
|
|---|
| 475 | * Create a new subprocess with the specified command line, already
|
|---|
| 476 | * tokenized. Calls <code>exec(cmd, null, null)</code>. A security check
|
|---|
| 477 | * is performed, <code>checkExec</code>.
|
|---|
| 478 | *
|
|---|
| 479 | * @param cmd the command to call
|
|---|
| 480 | * @return the Process object
|
|---|
| 481 | * @throws SecurityException if permission is denied
|
|---|
| 482 | * @throws IOException if an I/O error occurs
|
|---|
| 483 | * @throws NullPointerException if cmd is null, or has null entries
|
|---|
| 484 | * @throws IndexOutOfBoundsException if cmd is length 0
|
|---|
| 485 | */
|
|---|
| 486 | public Process exec(String[] cmd) throws IOException
|
|---|
| 487 | {
|
|---|
| 488 | return exec(cmd, null, null);
|
|---|
| 489 | }
|
|---|
| 490 |
|
|---|
| 491 | /**
|
|---|
| 492 | * Create a new subprocess with the specified command line, already
|
|---|
| 493 | * tokenized, and specified environment. If the environment is null, the
|
|---|
| 494 | * process inherits the environment of this process. Calls
|
|---|
| 495 | * <code>exec(cmd, env, null)</code>. A security check is performed,
|
|---|
| 496 | * <code>checkExec</code>.
|
|---|
| 497 | *
|
|---|
| 498 | * @param cmd the command to call
|
|---|
| 499 | * @param env the environment to use, in the format name=value
|
|---|
| 500 | * @return the Process object
|
|---|
| 501 | * @throws SecurityException if permission is denied
|
|---|
| 502 | * @throws IOException if an I/O error occurs
|
|---|
| 503 | * @throws NullPointerException if cmd is null, or cmd or env has null
|
|---|
| 504 | * entries
|
|---|
| 505 | * @throws IndexOutOfBoundsException if cmd is length 0
|
|---|
| 506 | */
|
|---|
| 507 | public Process exec(String[] cmd, String[] env) throws IOException
|
|---|
| 508 | {
|
|---|
| 509 | return exec(cmd, env, null);
|
|---|
| 510 | }
|
|---|
| 511 |
|
|---|
| 512 | /**
|
|---|
| 513 | * Create a new subprocess with the specified command line, already
|
|---|
| 514 | * tokenized, and the specified environment and working directory. If the
|
|---|
| 515 | * environment is null, the process inherits the environment of this
|
|---|
| 516 | * process. If the directory is null, the process uses the current working
|
|---|
| 517 | * directory. A security check is performed, <code>checkExec</code>.
|
|---|
| 518 | *
|
|---|
| 519 | * @param cmd the command to call
|
|---|
| 520 | * @param env the environment to use, in the format name=value
|
|---|
| 521 | * @param dir the working directory to use
|
|---|
| 522 | * @return the Process object
|
|---|
| 523 | * @throws SecurityException if permission is denied
|
|---|
| 524 | * @throws IOException if an I/O error occurs
|
|---|
| 525 | * @throws NullPointerException if cmd is null, or cmd or env has null
|
|---|
| 526 | * entries
|
|---|
| 527 | * @throws IndexOutOfBoundsException if cmd is length 0
|
|---|
| 528 | * @since 1.3
|
|---|
| 529 | */
|
|---|
| 530 | public Process exec(String[] cmd, String[] env, File dir)
|
|---|
| 531 | throws IOException
|
|---|
| 532 | {
|
|---|
| 533 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 534 | if (sm != null)
|
|---|
| 535 | sm.checkExec(cmd[0]);
|
|---|
| 536 | return execInternal(cmd, env, dir);
|
|---|
| 537 | }
|
|---|
| 538 |
|
|---|
| 539 | /**
|
|---|
| 540 | * Returns the number of available processors currently available to the
|
|---|
| 541 | * virtual machine. This number may change over time; so a multi-processor
|
|---|
| 542 | * program want to poll this to determine maximal resource usage.
|
|---|
| 543 | *
|
|---|
| 544 | * @return the number of processors available, at least 1
|
|---|
| 545 | */
|
|---|
| 546 | public native int availableProcessors();
|
|---|
| 547 |
|
|---|
| 548 | /**
|
|---|
| 549 | * Find out how much memory is still free for allocating Objects on the heap.
|
|---|
| 550 | *
|
|---|
| 551 | * @return the number of bytes of free memory for more Objects
|
|---|
| 552 | */
|
|---|
| 553 | public native long freeMemory();
|
|---|
| 554 |
|
|---|
| 555 | /**
|
|---|
| 556 | * Find out how much memory total is available on the heap for allocating
|
|---|
| 557 | * Objects.
|
|---|
| 558 | *
|
|---|
| 559 | * @return the total number of bytes of memory for Objects
|
|---|
| 560 | */
|
|---|
| 561 | public native long totalMemory();
|
|---|
| 562 |
|
|---|
| 563 | /**
|
|---|
| 564 | * Returns the maximum amount of memory the virtual machine can attempt to
|
|---|
| 565 | * use. This may be <code>Long.MAX_VALUE</code> if there is no inherent
|
|---|
| 566 | * limit (or if you really do have a 8 exabyte memory!).
|
|---|
| 567 | *
|
|---|
| 568 | * @return the maximum number of bytes the virtual machine will attempt
|
|---|
| 569 | * to allocate
|
|---|
| 570 | */
|
|---|
| 571 | public native long maxMemory();
|
|---|
| 572 |
|
|---|
| 573 | /**
|
|---|
| 574 | * Run the garbage collector. This method is more of a suggestion than
|
|---|
| 575 | * anything. All this method guarantees is that the garbage collector will
|
|---|
| 576 | * have "done its best" by the time it returns. Notice that garbage
|
|---|
| 577 | * collection takes place even without calling this method.
|
|---|
| 578 | */
|
|---|
| 579 | public native void gc();
|
|---|
| 580 |
|
|---|
| 581 | /**
|
|---|
| 582 | * Run finalization on all Objects that are waiting to be finalized. Again,
|
|---|
| 583 | * a suggestion, though a stronger one than {@link #gc()}. This calls the
|
|---|
| 584 | * <code>finalize</code> method of all objects waiting to be collected.
|
|---|
| 585 | *
|
|---|
| 586 | * @see #finalize()
|
|---|
| 587 | */
|
|---|
| 588 | public native void runFinalization();
|
|---|
| 589 |
|
|---|
| 590 | /**
|
|---|
| 591 | * Tell the VM to trace every bytecode instruction that executes (print out
|
|---|
| 592 | * a trace of it). No guarantees are made as to where it will be printed,
|
|---|
| 593 | * and the VM is allowed to ignore this request.
|
|---|
| 594 | *
|
|---|
| 595 | * @param on whether to turn instruction tracing on
|
|---|
| 596 | */
|
|---|
| 597 | public native void traceInstructions(boolean on);
|
|---|
| 598 |
|
|---|
| 599 | /**
|
|---|
| 600 | * Tell the VM to trace every method call that executes (print out a trace
|
|---|
| 601 | * of it). No guarantees are made as to where it will be printed, and the
|
|---|
| 602 | * VM is allowed to ignore this request.
|
|---|
| 603 | *
|
|---|
| 604 | * @param on whether to turn method tracing on
|
|---|
| 605 | */
|
|---|
| 606 | public native void traceMethodCalls(boolean on);
|
|---|
| 607 |
|
|---|
| 608 | /**
|
|---|
| 609 | * Load a native library using the system-dependent filename. This is similar
|
|---|
| 610 | * to loadLibrary, except the only name mangling done is inserting "_g"
|
|---|
| 611 | * before the final ".so" if the VM was invoked by the name "java_g". There
|
|---|
| 612 | * may be a security check, of <code>checkLink</code>.
|
|---|
| 613 | *
|
|---|
| 614 | * @param filename the file to load
|
|---|
| 615 | * @throws SecurityException if permission is denied
|
|---|
| 616 | * @throws UnsatisfiedLinkError if the library is not found
|
|---|
| 617 | */
|
|---|
| 618 | public void load(String filename)
|
|---|
| 619 | {
|
|---|
| 620 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 621 | if (sm != null)
|
|---|
| 622 | sm.checkLink(filename);
|
|---|
| 623 | _load(filename, false);
|
|---|
| 624 | }
|
|---|
| 625 |
|
|---|
| 626 | /**
|
|---|
| 627 | * Load a native library using a system-independent "short name" for the
|
|---|
| 628 | * library. It will be transformed to a correct filename in a
|
|---|
| 629 | * system-dependent manner (for example, in Windows, "mylib" will be turned
|
|---|
| 630 | * into "mylib.dll"). This is done as follows: if the context that called
|
|---|
| 631 | * load has a ClassLoader cl, then <code>cl.findLibrary(libpath)</code> is
|
|---|
| 632 | * used to convert the name. If that result was null, or there was no class
|
|---|
| 633 | * loader, this searches each directory of the system property
|
|---|
| 634 | * <code>java.library.path</code> for a file named
|
|---|
| 635 | * <code>System.mapLibraryName(libname)</code>. There may be a security
|
|---|
| 636 | * check, of <code>checkLink</code>.
|
|---|
| 637 | *
|
|---|
| 638 | * @param filename the file to load
|
|---|
| 639 | * @throws SecurityException if permission is denied
|
|---|
| 640 | * @throws UnsatisfiedLinkError if the library is not found
|
|---|
| 641 | * @see System#mapLibraryName(String)
|
|---|
| 642 | * @see ClassLoader#findLibrary(String)
|
|---|
| 643 | */
|
|---|
| 644 | public void loadLibrary(String libname)
|
|---|
| 645 | {
|
|---|
| 646 | // This is different from the Classpath implementation, but I
|
|---|
| 647 | // believe it is more correct.
|
|---|
| 648 | SecurityManager sm = securityManager; // Be thread-safe!
|
|---|
| 649 | if (sm != null)
|
|---|
| 650 | sm.checkLink(libname);
|
|---|
| 651 | _load(libname, true);
|
|---|
| 652 | }
|
|---|
| 653 |
|
|---|
| 654 | /**
|
|---|
| 655 | * Return a localized version of this InputStream, meaning all characters
|
|---|
| 656 | * are localized before they come out the other end.
|
|---|
| 657 | *
|
|---|
| 658 | * @param in the stream to localize
|
|---|
| 659 | * @return the localized stream
|
|---|
| 660 | * @deprecated <code>InputStreamReader</code> is the preferred way to read
|
|---|
| 661 | * local encodings
|
|---|
| 662 | */
|
|---|
| 663 | public InputStream getLocalizedInputStream(InputStream in)
|
|---|
| 664 | {
|
|---|
| 665 | return in;
|
|---|
| 666 | }
|
|---|
| 667 |
|
|---|
| 668 | /**
|
|---|
| 669 | * Return a localized version of this OutputStream, meaning all characters
|
|---|
| 670 | * are localized before they are sent to the other end.
|
|---|
| 671 | *
|
|---|
| 672 | * @param out the stream to localize
|
|---|
| 673 | * @return the localized stream
|
|---|
| 674 | * @deprecated <code>OutputStreamWriter</code> is the preferred way to write
|
|---|
| 675 | * local encodings
|
|---|
| 676 | */
|
|---|
| 677 | public OutputStream getLocalizedOutputStream(OutputStream out)
|
|---|
| 678 | {
|
|---|
| 679 | return out;
|
|---|
| 680 | }
|
|---|
| 681 |
|
|---|
| 682 | /**
|
|---|
| 683 | * Native method that actually shuts down the virtual machine.
|
|---|
| 684 | *
|
|---|
| 685 | * @param status the status to end the process with
|
|---|
| 686 | */
|
|---|
| 687 | native void exitInternal(int status);
|
|---|
| 688 |
|
|---|
| 689 | /**
|
|---|
| 690 | * Load a file. If it has already been loaded, do nothing. The name has
|
|---|
| 691 | * already been mapped to a true filename.
|
|---|
| 692 | *
|
|---|
| 693 | * @param filename the file to load
|
|---|
| 694 | * @param do_search True if we should search the load path for the file
|
|---|
| 695 | */
|
|---|
| 696 | native void _load(String filename, boolean do_search);
|
|---|
| 697 |
|
|---|
| 698 | /**
|
|---|
| 699 | *This is a helper function for the ClassLoader which can load
|
|---|
| 700 | * compiled libraries. Returns true if library (which is just the
|
|---|
| 701 | * base name -- path searching is done by this function) was loaded,
|
|---|
| 702 | * false otherwise.
|
|---|
| 703 | */
|
|---|
| 704 | native boolean loadLibraryInternal(String libname);
|
|---|
| 705 |
|
|---|
| 706 | /**
|
|---|
| 707 | * A helper for the constructor which does some internal native
|
|---|
| 708 | * initialization.
|
|---|
| 709 | */
|
|---|
| 710 | private native void init ();
|
|---|
| 711 |
|
|---|
| 712 | /**
|
|---|
| 713 | * Map a system-independent "short name" to the full file name, and append
|
|---|
| 714 | * it to the path.
|
|---|
| 715 | * XXX This method is being replaced by System.mapLibraryName.
|
|---|
| 716 | *
|
|---|
| 717 | * @param pathname the path
|
|---|
| 718 | * @param libname the short version of the library name
|
|---|
| 719 | * @return the full filename
|
|---|
| 720 | */
|
|---|
| 721 | static native String nativeGetLibname(String pathname, String libname);
|
|---|
| 722 |
|
|---|
| 723 | /**
|
|---|
| 724 | * Execute a process. The command line has already been tokenized, and
|
|---|
| 725 | * the environment should contain name=value mappings. If directory is null,
|
|---|
| 726 | * use the current working directory; otherwise start the process in that
|
|---|
| 727 | * directory.
|
|---|
| 728 | *
|
|---|
| 729 | * @param cmd the non-null command tokens
|
|---|
| 730 | * @param env the non-null environment setup
|
|---|
| 731 | * @param dir the directory to use, may be null
|
|---|
| 732 | * @return the newly created process
|
|---|
| 733 | * @throws NullPointerException if cmd or env have null elements
|
|---|
| 734 | */
|
|---|
| 735 | native Process execInternal(String[] cmd, String[] env, File dir);
|
|---|
| 736 |
|
|---|
| 737 | /**
|
|---|
| 738 | * Get the system properties. This is done here, instead of in System,
|
|---|
| 739 | * because of the bootstrap sequence. Note that the native code should
|
|---|
| 740 | * not try to use the Java I/O classes yet, as they rely on the properties
|
|---|
| 741 | * already existing. The only safe method to use to insert these default
|
|---|
| 742 | * system properties is {@link Properties#setProperty(String, String)}.
|
|---|
| 743 | *
|
|---|
| 744 | * <p>These properties MUST include:
|
|---|
| 745 | * <dl>
|
|---|
| 746 | * <dt>java.version <dd>Java version number
|
|---|
| 747 | * <dt>java.vendor <dd>Java vendor specific string
|
|---|
| 748 | * <dt>java.vendor.url <dd>Java vendor URL
|
|---|
| 749 | * <dt>java.home <dd>Java installation directory
|
|---|
| 750 | * <dt>java.vm.specification.version <dd>VM Spec version
|
|---|
| 751 | * <dt>java.vm.specification.vendor <dd>VM Spec vendor
|
|---|
| 752 | * <dt>java.vm.specification.name <dd>VM Spec name
|
|---|
| 753 | * <dt>java.vm.version <dd>VM implementation version
|
|---|
| 754 | * <dt>java.vm.vendor <dd>VM implementation vendor
|
|---|
| 755 | * <dt>java.vm.name <dd>VM implementation name
|
|---|
| 756 | * <dt>java.specification.version <dd>Java Runtime Environment version
|
|---|
| 757 | * <dt>java.specification.vendor <dd>Java Runtime Environment vendor
|
|---|
| 758 | * <dt>java.specification.name <dd>Java Runtime Environment name
|
|---|
| 759 | * <dt>java.class.version <dd>Java class version number
|
|---|
| 760 | * <dt>java.class.path <dd>Java classpath
|
|---|
| 761 | * <dt>java.library.path <dd>Path for finding Java libraries
|
|---|
| 762 | * <dt>java.io.tmpdir <dd>Default temp file path
|
|---|
| 763 | * <dt>java.compiler <dd>Name of JIT to use
|
|---|
| 764 | * <dt>java.ext.dirs <dd>Java extension path
|
|---|
| 765 | * <dt>os.name <dd>Operating System Name
|
|---|
| 766 | * <dt>os.arch <dd>Operating System Architecture
|
|---|
| 767 | * <dt>os.version <dd>Operating System Version
|
|---|
| 768 | * <dt>file.separator <dd>File separator ("/" on Unix)
|
|---|
| 769 | * <dt>path.separator <dd>Path separator (":" on Unix)
|
|---|
| 770 | * <dt>line.separator <dd>Line separator ("\n" on Unix)
|
|---|
| 771 | * <dt>user.name <dd>User account name
|
|---|
| 772 | * <dt>user.home <dd>User home directory
|
|---|
| 773 | * <dt>user.dir <dd>User's current working directory
|
|---|
| 774 | * </dl>
|
|---|
| 775 | *
|
|---|
| 776 | * @param p the Properties object to insert the system properties into
|
|---|
| 777 | */
|
|---|
| 778 | static native void insertSystemProperties(Properties p);
|
|---|
| 779 | } // class Runtime
|
|---|