0001: /*
0002: *
0003: *
0004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package com.sun.cldc.isolate;
0028:
0029: import java.util.Vector;
0030: import java.util.Hashtable;
0031: import java.util.Enumeration;
0032: import java.io.IOException;
0033: import com.sun.cldchi.jvm.JVM;
0034:
0035: /**
0036: * <blockquote>
0037: * <hr>
0038: * Last modified: 05/03/31 13:22:49. <p>
0039: * Note: this document is still a draft. Details in the API are
0040: * subject to change. <p>
0041: * <hr>
0042: * </blockquote>
0043: * The <code>Isolate</code> class provides the means of creating and managing
0044: * isolated computations and arranging for their communication with each
0045: * other.
0046: * <p>
0047: * <h3>Terminology</h3>
0048: *
0049: * Each isolated computation is called a <b>Task</b>. An <b>Isolate
0050: * object</b> is a Java representation of the task. Multiple
0051: * Isolate objects may be created to represent the same task. Where
0052: * the context is clear, the words "task", "isolate" and "isolate
0053: * object" may be used interchangeably. When a distinction needs to be
0054: * made, the word "task" is used to describe the underlying
0055: * computation, and the word "isolate" is used to describe the Java
0056: * object(s) that represent the computation. <p>
0057: *
0058: * When two Isolate objects represent the same task, they are said to
0059: * be <b>equivalent</b> to each other. Equivalent Isolate objects are
0060: * created to avoid the sharing of Isolate objects across task
0061: * boundaries. For example, in the following program, task A launches
0062: * task B using the object <code>b1</code>, and task B gets a
0063: * reference to itself using the object
0064: * <code>b2</code>. <code>b1</code> and <code>b2</code> are two
0065: * distinct objects: <p>
0066: *
0067: *<blockquote><pre>
0068: *class TaskA {
0069: * void launchB() {
0070: * Isolate <b>b1</b> = new Isolate("TaskB", ....);
0071: * b1.start();
0072: * }
0073: *}
0074: *class TaskB {
0075: * public static void main(String args[]) {
0076: * Isolate <b>b2</b> = Isolate.currentIsolate();
0077: * }
0078: *}</pre></blockquote>
0079: *
0080: * <h3>Degree of Isolation</h3>
0081: *
0082: * Tasks in the CLDC environment are isolated in the following sense:
0083: * <ul>
0084: * <li> Each task has a separate namespace for loading Java classes.
0085: * <li> Each task has a separate set of static variables for Java classes
0086: * <li> A <code>synchronized static</code> method uses a different
0087: * monitor object inside each task.
0088: * <li> Typically no Java objects are shared across task boundaries.
0089: * (see <a href=#classdoc_sharing>Object Sharing</a> below for
0090: * exceptions).
0091: * <li> Resource quotas are controlled by the runtime environment to
0092: * prevent tasks to use excessive amount of resources. The
0093: * implementation currently supports resource control for
0094: * memory or CPU cycles.
0095: * </ul>
0096: *
0097: * <a name="classdoc_class_path"><h3>Class path</h3></a>
0098: *
0099: * <p>Part of the definition of an isolate is its
0100: * classpath, where the basic classes for the isolate are found.
0101: * The CLDC runtime searches for classes in three sets of
0102: * locations:
0103: * <ul>
0104: * <li>The romized system classes.
0105: * <li>The isolate system class path.
0106: * <li>The isolate application class path.
0107: * </ul>
0108: *
0109: * <p><i>System</i> and <i>application</i> class paths are specified separately
0110: * for an isolate when it is created. Classes on system and application class
0111: * paths have different access rights:
0112: * <ul>
0113: * <li>Only classes loaded from the system class path can access
0114: * hidden classes.
0115: * <li>Only classes on the system class path can be loaded to restricted
0116: * packages.
0117: * </ul>
0118: * For the definition of hidden and restricted packages, see
0119: * doc/misc/Romizer.html.
0120: *
0121: * <p>When an isolate requests a class, the class is first looked up the
0122: * romized system classes, then searched in the isolate system class path,
0123: * and then searched in the isolate application class path.
0124: *
0125: * <p>User application classes should be put on the application class path,
0126: * system class path can contain only trusted system classes.
0127: *
0128: * <p>WARNING: UNTRUSTED USER APPLICATION CLASSES MUST NEVER BE PUT ON THE
0129: * SYSTEM CLASS PATH, AS IT GRANTS THEM ACCESS TO SYSTEM INTERNALS AND BREAKS
0130: * SYSTEM SECURITY.
0131: *
0132: * <a name="classdoc_sharing"><h3>Object Sharing</h3></a>
0133: *
0134: * The Isolate API in CLDC does not support the sharing of arbitrary
0135: * Java object across Isolate boundaries. The only exception is String
0136: * objects: String objects may be passed as arguments from a parent
0137: * isolate to a child isolate's <code>main()</code> method. Such
0138: * Strings are passed by reference instead of by value in order to
0139: * conserve resource. Also, interned Strings (such as literal Strings
0140: * that appear inside Java source code) may be shared across Isolate
0141: * boundaries. <p>
0142: *
0143: * Even though String objects may be shared across isolates, different
0144: * isolates should not attempt to coordinate their activities by
0145: * synchronizing on these Strings. Specifically, an interned Strings cannot
0146: * be synchronized across isolate boundaries because it uses a different
0147: * monitor object in each Isolate. <p>
0148: *
0149: * <h3>Inter-Isolate Communication</h3>
0150: *
0151: * Isolates may need to communicate with each to coordinate their
0152: * activities. The recommended method of inter-isolate communication
0153: * is a <b>native event queue</b>. On many CLDC/MIDP environments a native
0154: * event queue already exists. Such event queues can be extended for
0155: * one isolate to send events to another isolate. <p>
0156: *
0157: * Some CLDC/MIDP implementors may be tempted to use native code to
0158: * pass shared objects from one isolate to another, and use
0159: * traditional Java object-level synchronization to perform
0160: * inter-isolate communication. In our experience this could easily
0161: * lead to inter-isolate deadlock that could be exploited by
0162: * downloaded malicious Midlets. For example, if a shared object is
0163: * used to synchronize screen painting, a malicious Midlet may stop
0164: * other Midlets from painting by not returning from its
0165: * <code>paint()</code> method. <p>
0166: *
0167: * In our experience, with shared objects, it would take significant
0168: * effort to design a system that can prevent such attacks. In
0169: * contrast, event queues are much more easily understood to design
0170: * a safe environment. Thus, we strongly recommend against using
0171: * shared objects for inter-isolate communication.<p>
0172: *
0173: * The following code is an example of how an isolate can create other
0174: * isolates:
0175: *
0176: *<blockquote><pre>import com.sun.cldc.isolate.*;
0177: *
0178: *class HelloWorld {
0179: *
0180: * // Usage: cldc_vm -classpath <XX> HelloWorld HelloWorld2 <classpath>
0181: * public static void main(String [] argv) {
0182: * System.out.println("HelloWorld");
0183: * for (int i = 0; i < 6; i++) {
0184: * try {
0185: * // pass i as an argument to the isolate just for fun
0186: * String[] isoArgs = {Integer.toString(i)};
0187: * Isolate iso = new Isolate(argv[0], isoArgs);
0188: * iso.start();
0189: * } catch (Exception e) {
0190: * System.out.println("caught exception " + e);
0191: * e.printStackTrace();
0192: * }
0193: * System.out.println("HelloWorld: Iso " + i + " started.");
0194: *
0195: * }
0196: * }
0197: *}
0198: *
0199: *
0200: *class HelloWorld2 {
0201: * static String st = "HelloWorld2[";
0202: *
0203: * public static void main(String [] argv) {
0204: * st = st.concat(argv[0]);
0205: * st = st.concat("]");
0206: * System.out.println("st is " + st);
0207: * System.exit(42);
0208: * }
0209: *} </pre></blockquote>
0210: *
0211: * @see javax.isolate.IsolateStartupException
0212: **/
0213: public final class Isolate {
0214: /**
0215: * Controls access to each public API entry point. The
0216: * isolate creator can grant API access to the child.
0217: * Note this is a static so it is private to each Isolate
0218: */
0219: private static int _API_access_ok;
0220:
0221: /**
0222: * Priority level of this Isolate that was set using setPriority before
0223: * the isolate has started.
0224: */
0225: private int _priority;
0226:
0227: /**
0228: * Links to the next Isolate in a task's _seen_isolates list. See
0229: * Task.cpp for more information.
0230: */
0231: private Isolate _next;
0232:
0233: /**
0234: * A number that uniquely identifies the task represented by this
0235: * Isolate object.
0236: */
0237: private long _uniqueId;
0238:
0239: /**
0240: * Called by native code when the task corresponding to this Isolate
0241: * has terminated
0242: */
0243: private int _terminated;
0244:
0245: /**
0246: * If this isolate has terminated, this variable saves the exit code --
0247: * Normally the exitCode() method would retrieve the exit code from
0248: * the Task. _saved_exit_code is used only if this Isolate object
0249: * has been dis-associated from the Task (i.e., the Task has
0250: * exited).
0251: */
0252: private int _saved_exit_code;
0253:
0254: /**
0255: * Saves the mainClass parameter passed to Isolate() constructor.
0256: */
0257: private String _mainClass;
0258:
0259: /**
0260: * Saves the mainArgs parameter passed to Isolate() constructor.
0261: */
0262: private String[] _mainArgs;
0263:
0264: /**
0265: * Saves app_classpath[] parameter passed to Isolate() constructor.
0266: */
0267: private String[] _app_classpath;
0268:
0269: /**
0270: * Saves sys_classpath[] parameter passed to Isolate() constructor.
0271: */
0272: private String[] _sys_classpath;
0273:
0274: /**
0275: * Packages we want to be hidden in this Isolate. See definition of hidden package in
0276: * doc/misc/Romizer.html
0277: */
0278: private String[] _hidden_packages;
0279: /**
0280: * Packages we want to be restricted in this Isolate. See definition of restricted package in
0281: * doc/misc/Romizer.html
0282: */
0283: private String[] _restricted_packages;
0284:
0285: /**
0286: * Amount of memory reserved for this isolate
0287: * The isolate cannot get OutOfMemory exception until it
0288: * allocates at least memoryReserve bytes.
0289: * If the system cannot reserve the requested amount,
0290: * the isolate will not start.
0291: */
0292: private int _memoryReserve = 0;
0293:
0294: /**
0295: * Memory allocation limit for this isolate
0296: * OutOfMemoryError exception is thrown if
0297: * - the isolate exceeds its memory allocation limit
0298: * - excess over the reserved amount for this isolate
0299: * cannot be allocated in the heap or
0300: * conflicts with reserves of other isolates
0301: */
0302: private int _memoryLimit = Integer.MAX_VALUE;
0303:
0304: /**
0305: * Used during bootstrap of new Isolate to store API access value
0306: */
0307: private int _APIAccess = 0;
0308:
0309: private int _ConnectDebugger = 0;
0310:
0311: private int _UseVerifier = 1;
0312:
0313: private int _profileId = DEFAULT_PROFILE_ID;
0314:
0315: /**
0316: * ID of default profile.
0317: */
0318: private final static int DEFAULT_PROFILE_ID = -1;
0319: /**
0320: * A special priority level to indicate that an Isolate is suspended.
0321: */
0322: private final static int SUSPEND = 0;
0323:
0324: /**
0325: * The minimum priority that an Isolate can have.
0326: */
0327: public final static int MIN_PRIORITY = 1;
0328:
0329: /**
0330: * The default priority that is assigned to an Isolate.
0331: */
0332: public final static int NORM_PRIORITY = 2;
0333:
0334: /**
0335: * The maximum priority that an Isolate can have.
0336: */
0337: public final static int MAX_PRIORITY = 3;
0338:
0339: /**
0340: * Creates a new isolated java application with a default configuration.
0341: *
0342: * <p>This constructor has the same effect as invoking
0343: * {@link #Isolate(String,String[],String[])}
0344: * and passing <code>null</code> for the <code>app_classpath</code>
0345: * and <code>sys_classpath</code> parameters.
0346: * See the long constructor documentation for more details.
0347: *
0348: * @param mainClass fully qualified name of the main method class
0349: * @param mainArgs the arguments of the main method in the new isolate
0350: * @throws IsolateStartupException if an error occurs in the configuration
0351: * or startup of the new isolate before any application code is invoked
0352: **/
0353: public Isolate(String mainClass, String[] mainArgs)
0354: throws IsolateStartupException {
0355: this (mainClass, mainArgs, (String[]) null);
0356: }
0357:
0358: /**
0359: * Creates a new isolated java application with a default configuration.
0360: *
0361: * <p>This constructor has the same effect as invoking
0362: * {@link #Isolate(String,String[],String[], String[])}
0363: * and passing <code>null</code> for the <code>sys_classpath</code>
0364: * parameter.
0365: * See the long constructor documentation for more details.
0366: *
0367: * @param mainClass fully qualified name of the main method class
0368: * @param mainArgs the arguments of the main method in the new isolate
0369: * @param app_classpath the application classpath(s) for the isolate
0370: * (see <a href=#classdoc_class_path>Class path</a>)
0371: * @throws IsolateStartupException if an error occurs in the configuration
0372: * or startup of the new isolate before any application code is invoked
0373: **/
0374: public Isolate(String mainClass, String[] mainArgs,
0375: String[] app_classpath) throws IsolateStartupException {
0376: this (mainClass, mainArgs, app_classpath, (String[]) null);
0377: }
0378:
0379: /**
0380: * Creates a new Isolate with the specified arguments and
0381: * classpath. <p>
0382: *
0383: * The new isolate will execute the <code>main</code> method of
0384: * class <code>mainClass</code> with arguments
0385: * <code>mainArgs</code>. The <code>mainClass</code> parameter
0386: * must reference a class present in the romized system classes,
0387: * or in one of the classpath elements specified by the
0388: * <code>sys_classpath</code> and <code>app_classpath</code> parameters.
0389: *
0390: * <p>When the constructor returns, the new isolate is not yet
0391: * running. The new isolate does not start execution until the
0392: * {@link #start start} method is invoked. The {@link #halt halt}
0393: * and {@link #exit exit} methods will fail if before
0394: * {@link #start start} is invoked.
0395: *
0396: * <p>Class resolution and loading are performed in the new task
0397: * represented by this new isolate. Any loading exceptions (such as
0398: * <code>ClassNotFoundException</code>), including the loading
0399: * exception of the specified <code>mainClass</code>, will occur
0400: * inside the new task when it is started, not the creator task.
0401: *
0402: * <p>Changes made to any of the constructor's parameters after
0403: * control returns from this constructor will have no effect on the
0404: * newly created isolate.
0405: *
0406: * <p>If <code>mainArgs</code> is <code>null</code>, a zero-length
0407: * <code>String</code> array will be provided to the main method
0408: * of <code>mainClass</code>.
0409: *
0410: * <p>User application classes should be put on <code>app_classpath</code>,
0411: * while <code>sys_classpath</code> can contain only trusted system
0412: * classes.
0413: *
0414: * <p>WARNING: UNTRUSTED USER APPLICATION CLASSES MUST NEVER BE PUT ON THE
0415: * SYSTEM CLASS PATH, AS IT GRANTS THEM ACCESS TO SYSTEM INTERNALS AND
0416: * BREAKS SYSTEM SECURITY.
0417: *
0418: * @param mainClass fully qualified name of the main method class
0419: * @param mainArgs the arguments of the main method in the new isolate
0420: * @param app_classpath the application classpath(s) for the isolate
0421: * @param sys_classpath the system classpath(s) for the isolate
0422: * (see <a href=#classdoc_class_path>Class path</a>)
0423: * @throws IsolateStartupException if an error occurs in the configuration
0424: * of the new isolate before any application code is invoked
0425: * @throws IllegalArgumentException if any parameters are found to be
0426: * invalid.
0427: **/
0428: public Isolate(String mainClass, String[] mainArgs,
0429: String[] app_classpath, String[] sys_classpath)
0430: throws IsolateStartupException {
0431: securityCheck();
0432: if (mainClass == null) {
0433: throw new IllegalArgumentException(
0434: "specified class name is null");
0435: }
0436: registerNewIsolate();
0437: _priority = NORM_PRIORITY;
0438: _mainClass = mainClass;
0439: _mainArgs = argCopy(mainArgs);
0440: _app_classpath = argCopy(app_classpath);
0441: _sys_classpath = argCopy(sys_classpath);
0442:
0443: /*
0444: * <p>WARNING: DO NOT REMOVE THIS MESSAGE UNLESS YOU HAVE READ AND
0445: * UNDERSTOOD THE SECURITY IMPLICATIONS: HAVING UNTRUSTED USER
0446: * APPLICATION CLASSES ON THE SYSTEM CLASS PATH GRANTS THEM ACCESS TO
0447: * SYSTEM INTERNALS AND BREAKS SYSTEM SECURITY.
0448: */
0449: if (_sys_classpath.length != 0) {
0450: System.err.println();
0451: System.err.println("****warning****");
0452: System.err
0453: .println("****Untrusted user classes must never be put");
0454: System.err.println("****on the system class path");
0455: System.err.println("****warning****");
0456: System.err.println();
0457: }
0458: }
0459:
0460: /**
0461: * Start execution of this <code>Isolate</code>. Any code that belongs
0462: * to this <code>Isolate</code> (including static initializers)
0463: * is executed only after this method is called.
0464: * <p>
0465: * Control will return from this method when the new isolate's
0466: * first user level thread starts executing, or if an error occurs
0467: * during the initialization of the new isolate.
0468: *
0469: * <p>If any exception is thrown by this method, no code in the
0470: * <code>Isolate</code> will have executed.
0471: *
0472: * <p>Errors such as the main class being invalid or not visible in
0473: * the classpath will occur handled within the new isolate.
0474: *
0475: * @throws IsolateStartupException if an error occurs in the
0476: * initialization or configuration of the new isolate
0477: * before any application code is invoked, or if this
0478: * Isolate was already started or is terminated.
0479: * @throws IsolateResourceError if systems exceeds maximum Isolate count
0480: * @throws OutOfMemoryError if the reserved memory cannot be allocated
0481: */
0482: public synchronized void start() throws IsolateStartupException {
0483: if (getStatus() > NEW) {
0484: throw new IsolateStartupException(
0485: "Isolate has already started");
0486: }
0487:
0488: try {
0489: nativeStart();
0490: } catch (IsolateResourceError e) {
0491: throw e;
0492: } catch (OutOfMemoryError e) {
0493: throw e;
0494: } catch (Throwable t) {
0495: // To be somewhat compilant to JSR-121, we do not pass any
0496: // other errors back to the caller of start(). Instead,
0497: // the caller can use Isolate.exitCode() to discover that
0498: // the isolate has exited. See CR 6270554.
0499: }
0500:
0501: // Wait till the fate of the started isolate is known
0502: // (STARTED or STOPPED...)
0503: while (getStatus() <= NEW) {
0504: try {
0505: // Note: do NOT use wait(). See comments inside waitForExit().
0506: waitStatus(NEW);
0507: } catch (InterruptedException e) {
0508: throw new IsolateStartupException(
0509: "Exception was thrown while Isolate was starting");
0510: }
0511: }
0512: }
0513:
0514: /**
0515: * Requests normal termination of this <code>Isolate</code>.
0516: * Invocation of this method is equivalent to causing the isolate
0517: * to invoke {@link java.lang.Runtime#exit(int)}. If this method
0518: * invocation is, in fact, the cause of the isolate's termination,
0519: * the <code>status</code> supplied will be the isolate's
0520: * termination status.
0521: *
0522: * <p>No exception is thrown if this isolate is already
0523: * terminated. Even if {@link #isTerminated()} returns false prior
0524: * to invoking <code>exit</code>, an invocation of <code>exit</code> may
0525: * occur after the isolate exits on its own or is terminated by
0526: * another isolate. In these cases, the actual exit code reported by
0527: * the isolate may be different from <code>status</code>.
0528: *
0529: * <p>If this isolate is not yet started, it will be marked as
0530: * already terminated. A subsequent invocation to {@link #start()} would
0531: * result in an IsolateStartupException.
0532: *
0533: * <p>If this isolate is suspended, it will be terminated without
0534: * being resumed.
0535: *
0536: * @param status Termination status. By convention, a nonzero status
0537: * code indicates abnormal termination.
0538: **/
0539: public void exit(int status) {
0540: try {
0541: stop(status,
0542: this == currentIsolate() ? EXIT_REASON_SELF_EXIT
0543: : EXIT_REASON_OTHER_EXIT);
0544: } catch (SecurityException se) {
0545: stop(status, EXIT_REASON_SELF_EXIT);
0546: }
0547: }
0548:
0549: /**
0550: * Forces termination of this <code>Isolate</code>.
0551: *
0552: * If this method invocation is in fact the cause of the isolate's
0553: * termination, the <code>status</code> supplied will be the
0554: * isolate's termination status.
0555: *
0556: * <p>No exception is thrown if this isolate is already
0557: * terminated. Even if {@link #isTerminated()} returns false prior
0558: * to invoking <code>halt</code>, an invocation of <code>halt</code> may
0559: * occur after the isolate exits on its own or is terminated by
0560: * another isolate. In these cases, the actual exit code reported by
0561: * the isolate may be different from <code>status</code>.
0562: *
0563: * <p>If this isolate is not yet started, it will be marked as
0564: * already terminated. A subsequent invocation to {@link #start()} would
0565: * result in an IsolateStartupException.
0566: *
0567: * <p>If this isolate is suspended, it will be terminated without
0568: * being resumed.
0569: *
0570: * <h3>Implementation Note</h3>
0571: *
0572: * Implementations should strive to implement "quick" termination
0573: * with as little coordination with the target isolate as possible.
0574: * The only information required of a terminated isolate is the exit
0575: * code it was terminated with.
0576: *
0577: * @param status Termination status. By convention, a nonzero status code
0578: * indicates abnormal termination.
0579: **/
0580: public void halt(int status) {
0581: try {
0582: stop(status,
0583: this == currentIsolate() ? EXIT_REASON_SELF_HALT
0584: : EXIT_REASON_OTHER_HALT);
0585: } catch (SecurityException se) {
0586: stop(status, EXIT_REASON_SELF_HALT);
0587: }
0588: }
0589:
0590: /**
0591: * Returns true if this <code>Isolate</code> is terminated.
0592: */
0593: public boolean isTerminated() {
0594: int state = getStatus();
0595: return (state >= STOPPED);
0596: }
0597:
0598: /**
0599: * Returns the Isolate object corresponding to the currently executing
0600: * task.
0601: *
0602: * <p>This method never returns <code>null</code>.
0603: *
0604: * @return the <code>Isolate</code> object for the current task
0605: **/
0606: public static Isolate currentIsolate() {
0607: securityCheck();
0608: return currentIsolate0();
0609: }
0610:
0611: private native static Isolate currentIsolate0();
0612:
0613: /**
0614: * Returns an array of <code>Isolate</code> objects representing
0615: * all tasks that have been started but have not terminated.
0616: * New tasks may have been constructed or existing ones
0617: * terminated by the time this method returns.
0618: *
0619: * @return the active <code>Isolate</code> objects at the time
0620: * of the call
0621: **/
0622: public static Isolate[] getIsolates() {
0623: securityCheck();
0624: return getIsolates0();
0625: }
0626:
0627: private native static Isolate[] getIsolates0();
0628:
0629: ///////////////////////////////////////////////////////////////////////////
0630: // Valid state transitions are:
0631: // NEW -> { STARTED, STOPPED }
0632: // STARTED -> { STOPPING, STOPPED }
0633: // STOPPING -> { STOPPED }
0634: // { STOPPED } : final states.
0635: // { NEW} : initial states.
0636: //
0637: //
0638: // Note: only Isolate created by the current isolate can be in the NEW
0639: // state.
0640: // Hence, knowing if an isolate is started only consists of testing if
0641: // its state is > NEW.
0642:
0643: static final int INVALID_TASK_ID = -1; // invalid task id.
0644:
0645: static final int NEW = 1; // created by the current isolate
0646: static final int STARTED = 2; // start() method has been called.
0647: static final int STOPPING = 3; // isolate is stopping --
0648: // see IsolateEvent.STOPPING
0649: static final int STOPPED = 4; // isolate was terminated --
0650:
0651: // see IsolateEvent.TERMINATED
0652:
0653: /**
0654: * Returns a small integer ID that uniquely identifies this
0655: * Isolate among the current set of active Isolates. The returned
0656: * ID will remain unchanged and reserved for this Isolate during its
0657: * entire lifetime. However, after this Isolate is terminated, the ID may
0658: * be resumed for a new Isolate.
0659: *
0660: * @return -1 if the task has not been started or it has been terminated,
0661: *
0662: */
0663: public int id() {
0664: return id0();
0665: }
0666:
0667: private native int id0();
0668:
0669: /**
0670: * @return the amount of object heap memory reserved for this Isolate.
0671: */
0672: public int reservedMemory() {
0673: return _memoryReserve;
0674: }
0675:
0676: /**
0677: * @return the maximum amount of object heap memory that can be
0678: * allocated by this Isolate.
0679: */
0680: public int totalMemory() {
0681: return _memoryLimit;
0682: }
0683:
0684: /**
0685: * This function returns the approximate amount of object heap
0686: * memory currently used by this Isolate. The approximate value
0687: * may not be accurate: it may not include recent allocations
0688: * made by the Isolate, and it may count objects allocated by the
0689: * Isolate that have since become unreachable. <p>
0690: *
0691: * @return the approximate amount of object heap memory currently
0692: * used by this Isolate.
0693: */
0694: public int usedMemory() {
0695: return usedMemory0();
0696: }
0697:
0698: private native int usedMemory0();
0699:
0700: /**
0701: * Sets the object heap memory reserved and maximum limits to the
0702: * same value. Note that if the system does not have sufficient
0703: * resources to guaranteed the reserved amount, the start() method
0704: * of this Isolate would fail. This method should only be called
0705: * before the Isolate is started. Calling it after the isolate
0706: * has started will cause undetermined behavior. <p>
0707: *
0708: * @param reserved The minimum amount of memory guaranteed to be
0709: * available to the isolate at any time. Also the total
0710: * amount of memory that the isolate can reserve.
0711: */
0712: public void setMemoryQuota(int reserved) {
0713: setMemoryQuota(reserved, reserved);
0714: }
0715:
0716: /**
0717: * Sets the object heap memory quota for this Isolate. Note that
0718: * if the system does not have sufficient resources to guaranteed
0719: * the reserved amount, the start() method of this Isolate would
0720: * fail.
0721: * This method should only be called before the Isolate is
0722: * started. Calling it after the isolate has started will cause
0723: * undetermined behavior. <p>
0724: *
0725: * @param reserved The minimum amount of memory guaranteed to be
0726: * available to the isolate at any time.
0727: * @param total The total amount of memory that the isolate can
0728: * reserve.
0729: */
0730: public void setMemoryQuota(int reserved, int total) {
0731: if (reserved < 0 || reserved > total) {
0732: throw new IllegalArgumentException();
0733: }
0734: _memoryReserve = reserved;
0735: _memoryLimit = total;
0736: }
0737:
0738: /* Return true if isolate has been started.
0739: */
0740: synchronized boolean isStarted() {
0741: return getStatus() <= NEW;
0742: }
0743:
0744: private String[] argCopy(String[] args) {
0745: if (args == null) {
0746: return new String[0];
0747: }
0748: String[] result = new String[args.length];
0749: JVM.unchecked_obj_arraycopy(args, 0, result, 0, args.length);
0750: return result;
0751: }
0752:
0753: /**
0754: * Add this Isolate to the TaskDesc::_seen_isolates list of the
0755: * current task and return the globally unique isolate identifier.
0756: */
0757: private native void registerNewIsolate();
0758:
0759: /**
0760: * Stopping execution of an Isolate. Used by implementation of exit
0761: * and halt.
0762: *
0763: * <p>If this isolate is not yet started, it will be marked as
0764: * already terminated. A subsequent invocation to {@link #start()} would
0765: * result in an IsolateStartupException.
0766: *
0767: * <p>If this isolate is suspended, it will be terminated without
0768: * being resumed.
0769: */
0770: private native void stop(int exit_code, int exit_reason);
0771:
0772: /**
0773: * Adjust the priority of this Isolate. The priority controls the
0774: * amount of CPU time that VM allocates to execute threads in this
0775: * Isolate.
0776: *
0777: * Note: thread scheduling and task scheduling use separate mechanisms.
0778: * In the current imeplentation, each task is guaranteed execution time
0779: * relative to its priority.
0780: *
0781: *
0782: * @param new_priority must be between <code>MIN_PRIORITY</code>
0783: * and <code>MAX_PRIORITY</code>, or else this method call will
0784: * have no effect.
0785: */
0786: public void setPriority(int new_priority) {
0787: if (new_priority >= MIN_PRIORITY
0788: && new_priority <= MAX_PRIORITY) {
0789: _priority = new_priority;
0790: setPriority0(new_priority);
0791: }
0792: }
0793:
0794: private native void setPriority0(int new_priority);
0795:
0796: /**
0797: * Returns the priority of this isolate.
0798: *
0799: * @return the priority of this isolate. If the isolate has already
0800: * terminated, the returned value is undefined.
0801: */
0802: public int getPriority() {
0803: return _priority;
0804: }
0805:
0806: /**
0807: * Returns if this isolate has been suspended.
0808: * @return true iff the isolate has been suspended.
0809: */
0810: public boolean isSuspended() {
0811: return (isSuspended0() != 0 ? true : false);
0812: }
0813:
0814: private native int isSuspended0();
0815:
0816: /**
0817: * Suspends all threads in this isolate from execution. This
0818: * method should be used carefully if objects shared between isolates
0819: * (passed via native methods) are used for synchornization. A
0820: * suspended isolate holding a lock on such an object will stop other
0821: * tasks from ever receiving that lock.
0822: * See introduction for better ways of communicating between isolates.
0823: *
0824: * This method will suspend the isolate only if the isolate is currently
0825: * started, not suspended and not terminated. Otherwise this method
0826: * has no effect.
0827: */
0828: public void suspend() {
0829: suspend0();
0830: }
0831:
0832: private native void suspend0();
0833:
0834: /**
0835: * The opposite of the <code>suspend</code> method.
0836: *
0837: * This method will resume the isolate only if the isolate is
0838: * currently started, suspended and not terminated. Otherwise this
0839: * method has no effect.
0840: */
0841: public void resume() {
0842: resume0();
0843: }
0844:
0845: private native void resume0();
0846:
0847: /**
0848: * Returns the exit code of the isolate. If this Isolate has terminated,
0849: * this method returns the exit code parameter to the first invocation of
0850: * System.exit(), Isolate.exit() or Isolate.halt() that caused the Isolate
0851: * to terminate. If this Isolate has terminated without calling
0852: * System.exit(), Isolate.exit() or Isolate.halt(), then 0 is returned.
0853: *
0854: * If this Isolate has not started or has not terminated, 0 is returned.
0855: *
0856: * @return the exit code of the isolate.
0857: */
0858: public int exitCode() {
0859: return exitCode0();
0860: }
0861:
0862: private native int exitCode0();
0863:
0864: /**
0865: * Blocks the execution of the calling thread until this Isolate
0866: * has exited. If <code>waitForExit()</code> is called on the
0867: * current Isolate, the result is undefined.
0868: *
0869: * @throws InterruptedException (unimplemented yet): if CLDC
0870: * Specification 1.1 is enabled, when a thread is blocked
0871: * inside this method, it may be interrupted by an
0872: * invocation of Thread.interrupt, in which case an
0873: * InterruptedException is thrown regardless of the
0874: * termination status of this Isolate.
0875: */
0876: public synchronized void waitForExit() /* throws InterruptedException */{
0877: while (getStatus() <= STOPPING) {
0878: try {
0879: // Note: do NOT use wait(): When notifyStatus() is
0880: // called, the calling thread may not hold the monitor
0881: // of this object, so if we wrote the code like this
0882: // we may get into a race condition
0883: // while (getStatus() <= STOPPING) {
0884: // <thread switch/race condition may happen here>
0885: // wait();
0886: // }
0887: // waitStatus() performs the getStatus() <= STOPPING check in
0888: // native code again, where thread switch is guaranteed to
0889: // not happen. Hence we won't have a race condition.
0890: waitStatus(STOPPING);
0891: } catch (InterruptedException e) {
0892: // IMPL_NOTE: this method should throw InterruptedException!
0893: throw new Error();
0894: }
0895: }
0896: }
0897:
0898: /**
0899: * Returns the classpath the Isolate was started with.
0900: *
0901: * @return String[] that is equal to classpath argument passed to
0902: * Isolate constructor
0903: */
0904: public String[] getClassPath() {
0905: return argCopy(_app_classpath);
0906: }
0907:
0908: /**
0909: * Determine if this isolate has permission to access the API
0910: * If not, throw runtime exception
0911: */
0912: private static void securityCheck() {
0913: if (_API_access_ok == 0) {
0914: throw new SecurityException(
0915: "Access to Isolate API not allowed");
0916: }
0917: }
0918:
0919: /**
0920: * Sets the access to Isolate API for this Isolate. This method
0921: * should be used by the AMS, before the Isolate is started, to
0922: * control whether or not a created Isolate is able to call the
0923: * Isolate API. The default for all but the first Isolate is
0924: * <code>false</code>. If the AMS calls this method after the Isolate
0925: * has started, it has no effect.<p>
0926: *
0927: * In additional, after an Isolate has started, if it has access
0928: * to the Isolate API, it can call this method to disable
0929: * it. However, once it loses the access, attempts to call this
0930: * method would result in a SecurityException.
0931: */
0932: public void setAPIAccess(boolean access) {
0933: _APIAccess = (access == true ? 1 : 0);
0934:
0935: // Only allow access to be degraded after starting.
0936: if (!access && equals(currentIsolate())) {
0937: _API_access_ok = 0;
0938: }
0939: }
0940:
0941: public void setDebug(boolean mode) {
0942: _ConnectDebugger = (mode == true ? 1 : 0);
0943: }
0944:
0945: public void attachDebugger() {
0946: securityCheck();
0947: attachDebugger0(this );
0948: }
0949:
0950: /**
0951: * Controls whether or not classes for this isolate need to be
0952: * verified. When creating a new Isolate, the AMS may waive
0953: * verification for classes that have already been verified. The
0954: * default is <code>false</code>. This method should be called
0955: * before the Isolate is started.
0956: */
0957: public void setUseVerifier(boolean verify) {
0958: _UseVerifier = (verify == true ? 1 : 0);
0959: }
0960:
0961: /**
0962: * Returns the current status of the task represented by this Isolate.
0963: *
0964: * @return one of NEW, STARTED, STOPPING or STOPPED
0965: */
0966: private native int getStatus();
0967:
0968: /**
0969: * Notify all threads that are waiting on the status of any Isolate object
0970: * that represent the same task as this Isolate object.
0971: *
0972: * To simplify VM design, this method does NOT need to be called
0973: * while holding a lock of such Isolate objects. To avert race conditions,
0974: * the waiting threads must be blocked using waitStatus() instead
0975: * of wait(). See comments inside waitForExit() for details.
0976: */
0977: private native void notifyStatus();
0978:
0979: /**
0980: * Blocks the current thread until getStatus() would return a value
0981: * greater than maxStatus, or (CLDC Spec 1.1 only) until this
0982: * thread is interrupted. <p>
0983: *
0984: * See comments inside waitForExit() to see why this method method
0985: * must be used instead of wait() to avert race conditions.
0986: */
0987: private native void waitStatus(int maxStatus)
0988: throws InterruptedException;
0989:
0990: /* For now, ignore the links argument.
0991: * Native method will use the JNI invocation API to start a new in-process
0992: * JVM to execute the new Isolate.
0993: */
0994: private native void nativeStart() throws IsolateStartupException;
0995:
0996: /**
0997: * The last non-daemon thread returned from main.
0998: */
0999: private static final int EXIT_REASON_IMPLICIT_EXIT = 1;
1000:
1001: /**
1002: * The last non-daemon thread exited due to an uncaught exception.
1003: *
1004: * <p>Note that if a daemon thread dies with an uncaught exception,
1005: * that will not cause the containing isolate to die. Additionally,
1006: * only if the <emph>last</emph> non-daemon thread dies with
1007: * an uncaught exception will this reason be noted. Uncaught exceptions
1008: * in shutdown hooks do not count, either.
1009: */
1010: private static final int EXIT_REASON_UNCAUGHT_EXCEPT = 6;
1011:
1012: /**
1013: * The isolate invoked {@link System#exit System.exit},
1014: * {@link Runtime#exit Runtime.exit}, or
1015: * {@link Isolate#exit Isolate.exit} on itself.
1016: */
1017: private static final int EXIT_REASON_SELF_EXIT = 2;
1018:
1019: /**
1020: * The isolate invoked
1021: * {@link Runtime#halt Runtime.halt} or
1022: * {@link Isolate#halt Isolate.halt} on itself.
1023: */
1024: private static final int EXIT_REASON_SELF_HALT = 3;
1025:
1026: /**
1027: * Some other isolate invoked {@link Isolate#exit Isolate.exit}
1028: * on the isolate.
1029: */
1030: private static final int EXIT_REASON_OTHER_EXIT = 4;
1031:
1032: /**
1033: * Some other isolate invoked {@link Isolate#halt Isolate.halt}
1034: * on the isolate.
1035: */
1036: private static final int EXIT_REASON_OTHER_HALT = 5;
1037:
1038: /**
1039: * Sets active profile name for isolate. This method must be
1040: * called before the isolate is started.
1041: *
1042: * If isolate is already started the method throws an
1043: * <code>IllegalIsolateStateException</code>.
1044: *
1045: * The method also determines if <code>profile</code>
1046: * is a name of existing profile which is defined in ROM
1047: * configuration file. If not, throws runtime
1048: * <code>IllegalArgumentException</code>.
1049: *
1050: * @param profile The new active profile name.
1051: */
1052: public native void setProfile(String profile)
1053: throws IllegalArgumentException,
1054: IllegalIsolateStateException;
1055:
1056: /**
1057: * Sets the packages which will be hidden. See definition of hidden package in
1058: * doc/misc/Romizer.html. Note, that this function call overrides previous settings.
1059: *
1060: * If isolate is already started the method throws an
1061: * <code>IllegalIsolateStateException</code>.
1062: *
1063: * @param package_name. The name of package for marking.
1064: */
1065: public void setHiddenPackages(String[] package_names)
1066: throws IllegalIsolateStateException {
1067: if (getStatus() > NEW) {
1068: throw new IllegalIsolateStateException(
1069: "Can only set hidden packages before Isolate starts");
1070: }
1071: _hidden_packages = package_names;
1072: }
1073:
1074: /**
1075: * Sets the packages which will be restricted. See definition of restricted package in
1076: * doc/misc/Romizer.html. Note, that this function call overrides previous settings.
1077: *
1078: * If isolate is already started the method throws an
1079: * <code>IllegalIsolateStateException</code>.
1080: *
1081: * @param package_name The name of package for marking.
1082: */
1083: public void setRestrictedPackages(String[] package_names)
1084: throws IllegalIsolateStateException {
1085: if (getStatus() > NEW) {
1086: throw new IllegalIsolateStateException(
1087: "Can only set restricted packages before Isolate starts");
1088: }
1089: _restricted_packages = package_names;
1090: }
1091:
1092: private native void attachDebugger0(Isolate obj);
1093: }
|