FileDocCategorySizeDatePackage
Isolate.javaAPI DocphoneME MR2 API (J2ME)41071Wed May 02 17:59:54 BST 2007com.sun.cldc.isolate

Isolate

public final class Isolate extends Object

Last modified: 05/03/31 13:22:49.

Note: this document is still a draft. Details in the API are subject to change.


The Isolate class provides the means of creating and managing isolated computations and arranging for their communication with each other.

Terminology

Each isolated computation is called a Task. An Isolate object is a Java representation of the task. Multiple Isolate objects may be created to represent the same task. Where the context is clear, the words "task", "isolate" and "isolate object" may be used interchangeably. When a distinction needs to be made, the word "task" is used to describe the underlying computation, and the word "isolate" is used to describe the Java object(s) that represent the computation.

When two Isolate objects represent the same task, they are said to be equivalent to each other. Equivalent Isolate objects are created to avoid the sharing of Isolate objects across task boundaries. For example, in the following program, task A launches task B using the object b1, and task B gets a reference to itself using the object b2. b1 and b2 are two distinct objects:

class TaskA {
void launchB() {
Isolate b1 = new Isolate("TaskB", ....);
b1.start();
}
}
class TaskB {
public static void main(String args[]) {
Isolate b2 = Isolate.currentIsolate();
}
}

Degree of Isolation

Tasks in the CLDC environment are isolated in the following sense:
  • Each task has a separate namespace for loading Java classes.
  • Each task has a separate set of static variables for Java classes
  • A synchronized static method uses a different monitor object inside each task.
  • Typically no Java objects are shared across task boundaries. (see Object Sharing below for exceptions).
  • Resource quotas are controlled by the runtime environment to prevent tasks to use excessive amount of resources. The implementation currently supports resource control for memory or CPU cycles.

Class path

Part of the definition of an isolate is its classpath, where the basic classes for the isolate are found. The CLDC runtime searches for classes in three sets of locations:

  • The romized system classes.
  • The isolate system class path.
  • The isolate application class path.

System and application class paths are specified separately for an isolate when it is created. Classes on system and application class paths have different access rights:

  • Only classes loaded from the system class path can access hidden classes.
  • Only classes on the system class path can be loaded to restricted packages.
For the definition of hidden and restricted packages, see doc/misc/Romizer.html.

When an isolate requests a class, the class is first looked up the romized system classes, then searched in the isolate system class path, and then searched in the isolate application class path.

User application classes should be put on the application class path, system class path can contain only trusted system classes.

WARNING: UNTRUSTED USER APPLICATION CLASSES MUST NEVER BE PUT ON THE SYSTEM CLASS PATH, AS IT GRANTS THEM ACCESS TO SYSTEM INTERNALS AND BREAKS SYSTEM SECURITY.

Object Sharing

The Isolate API in CLDC does not support the sharing of arbitrary Java object across Isolate boundaries. The only exception is String objects: String objects may be passed as arguments from a parent isolate to a child isolate's main() method. Such Strings are passed by reference instead of by value in order to conserve resource. Also, interned Strings (such as literal Strings that appear inside Java source code) may be shared across Isolate boundaries.

Even though String objects may be shared across isolates, different isolates should not attempt to coordinate their activities by synchronizing on these Strings. Specifically, an interned Strings cannot be synchronized across isolate boundaries because it uses a different monitor object in each Isolate.

Inter-Isolate Communication

Isolates may need to communicate with each to coordinate their activities. The recommended method of inter-isolate communication is a native event queue. On many CLDC/MIDP environments a native event queue already exists. Such event queues can be extended for one isolate to send events to another isolate.

Some CLDC/MIDP implementors may be tempted to use native code to pass shared objects from one isolate to another, and use traditional Java object-level synchronization to perform inter-isolate communication. In our experience this could easily lead to inter-isolate deadlock that could be exploited by downloaded malicious Midlets. For example, if a shared object is used to synchronize screen painting, a malicious Midlet may stop other Midlets from painting by not returning from its paint() method.

In our experience, with shared objects, it would take significant effort to design a system that can prevent such attacks. In contrast, event queues are much more easily understood to design a safe environment. Thus, we strongly recommend against using shared objects for inter-isolate communication.

The following code is an example of how an isolate can create other isolates:

import com.sun.cldc.isolate.*;

class HelloWorld {

// Usage: cldc_vm -classpath  HelloWorld HelloWorld2 
public static void main(String [] argv) {
System.out.println("HelloWorld");
for (int i = 0; i < 6; i++) {
try {
// pass i as an argument to the isolate just for fun
String[] isoArgs = {Integer.toString(i)};
Isolate iso = new Isolate(argv[0], isoArgs);
iso.start();
} catch (Exception e) {
System.out.println("caught exception " + e);
e.printStackTrace();
}
System.out.println("HelloWorld: Iso " + i + " started.");

}
}
}


class HelloWorld2 {
static String st = "HelloWorld2[";

public static void main(String [] argv) {
st = st.concat(argv[0]);
st = st.concat("]");
System.out.println("st is " + st);
System.exit(42);
}
} 
see
javax.isolate.IsolateStartupException

Fields Summary
private static int
_API_access_ok
Controls access to each public API entry point. The isolate creator can grant API access to the child. Note this is a static so it is private to each Isolate
private int
_priority
Priority level of this Isolate that was set using setPriority before the isolate has started.
private Isolate
_next
Links to the next Isolate in a task's _seen_isolates list. See Task.cpp for more information.
private long
_uniqueId
A number that uniquely identifies the task represented by this Isolate object.
private int
_terminated
Called by native code when the task corresponding to this Isolate has terminated
private int
_saved_exit_code
If this isolate has terminated, this variable saves the exit code -- Normally the exitCode() method would retrieve the exit code from the Task. _saved_exit_code is used only if this Isolate object has been dis-associated from the Task (i.e., the Task has exited).
private String
_mainClass
Saves the mainClass parameter passed to Isolate() constructor.
private String[]
_mainArgs
Saves the mainArgs parameter passed to Isolate() constructor.
private String[]
_app_classpath
Saves app_classpath[] parameter passed to Isolate() constructor.
private String[]
_sys_classpath
Saves sys_classpath[] parameter passed to Isolate() constructor.
private String[]
_hidden_packages
Packages we want to be hidden in this Isolate. See definition of hidden package in doc/misc/Romizer.html
private String[]
_restricted_packages
Packages we want to be restricted in this Isolate. See definition of restricted package in doc/misc/Romizer.html
private int
_memoryReserve
Amount of memory reserved for this isolate The isolate cannot get OutOfMemory exception until it allocates at least memoryReserve bytes. If the system cannot reserve the requested amount, the isolate will not start.
private int
_memoryLimit
Memory allocation limit for this isolate OutOfMemoryError exception is thrown if - the isolate exceeds its memory allocation limit - excess over the reserved amount for this isolate cannot be allocated in the heap or conflicts with reserves of other isolates
private int
_APIAccess
Used during bootstrap of new Isolate to store API access value
private int
_ConnectDebugger
private int
_UseVerifier
private int
_profileId
private static final int
DEFAULT_PROFILE_ID
ID of default profile.
private static final int
SUSPEND
A special priority level to indicate that an Isolate is suspended.
public static final int
MIN_PRIORITY
The minimum priority that an Isolate can have.
public static final int
NORM_PRIORITY
The default priority that is assigned to an Isolate.
public static final int
MAX_PRIORITY
The maximum priority that an Isolate can have.
static final int
INVALID_TASK_ID
static final int
NEW
static final int
STARTED
static final int
STOPPING
static final int
STOPPED
private static final int
EXIT_REASON_IMPLICIT_EXIT
The last non-daemon thread returned from main.
private static final int
EXIT_REASON_UNCAUGHT_EXCEPT
The last non-daemon thread exited due to an uncaught exception.

Note that if a daemon thread dies with an uncaught exception, that will not cause the containing isolate to die. Additionally, only if the last non-daemon thread dies with an uncaught exception will this reason be noted. Uncaught exceptions in shutdown hooks do not count, either.

private static final int
EXIT_REASON_SELF_EXIT
The isolate invoked {@link System#exit System.exit}, {@link Runtime#exit Runtime.exit}, or {@link Isolate#exit Isolate.exit} on itself.
private static final int
EXIT_REASON_SELF_HALT
The isolate invoked {@link Runtime#halt Runtime.halt} or {@link Isolate#halt Isolate.halt} on itself.
private static final int
EXIT_REASON_OTHER_EXIT
Some other isolate invoked {@link Isolate#exit Isolate.exit} on the isolate.
private static final int
EXIT_REASON_OTHER_HALT
Some other isolate invoked {@link Isolate#halt Isolate.halt} on the isolate.
Constructors Summary
public Isolate(String mainClass, String[] mainArgs)
Creates a new isolated java application with a default configuration.

This constructor has the same effect as invoking {@link #Isolate(String,String[],String[])} and passing null for the app_classpath and sys_classpath parameters. See the long constructor documentation for more details.

param
mainClass fully qualified name of the main method class
param
mainArgs the arguments of the main method in the new isolate
throws
IsolateStartupException if an error occurs in the configuration or startup of the new isolate before any application code is invoked


                                                                                           
        
          
        this(mainClass, mainArgs, (String[])null);
    
public Isolate(String mainClass, String[] mainArgs, String[] app_classpath)
Creates a new isolated java application with a default configuration.

This constructor has the same effect as invoking {@link #Isolate(String,String[],String[], String[])} and passing null for the sys_classpath parameter. See the long constructor documentation for more details.

param
mainClass fully qualified name of the main method class
param
mainArgs the arguments of the main method in the new isolate
param
app_classpath the application classpath(s) for the isolate (see Class path)
throws
IsolateStartupException if an error occurs in the configuration or startup of the new isolate before any application code is invoked

        this(mainClass, mainArgs, app_classpath, (String[])null);
    
public Isolate(String mainClass, String[] mainArgs, String[] app_classpath, String[] sys_classpath)
Creates a new Isolate with the specified arguments and classpath.

The new isolate will execute the main method of class mainClass with arguments mainArgs. The mainClass parameter must reference a class present in the romized system classes, or in one of the classpath elements specified by the sys_classpath and app_classpath parameters.

When the constructor returns, the new isolate is not yet running. The new isolate does not start execution until the {@link #start start} method is invoked. The {@link #halt halt} and {@link #exit exit} methods will fail if before {@link #start start} is invoked.

Class resolution and loading are performed in the new task represented by this new isolate. Any loading exceptions (such as ClassNotFoundException), including the loading exception of the specified mainClass, will occur inside the new task when it is started, not the creator task.

Changes made to any of the constructor's parameters after control returns from this constructor will have no effect on the newly created isolate.

If mainArgs is null, a zero-length String array will be provided to the main method of mainClass.

User application classes should be put on app_classpath, while sys_classpath can contain only trusted system classes.

WARNING: UNTRUSTED USER APPLICATION CLASSES MUST NEVER BE PUT ON THE SYSTEM CLASS PATH, AS IT GRANTS THEM ACCESS TO SYSTEM INTERNALS AND BREAKS SYSTEM SECURITY.

param
mainClass fully qualified name of the main method class
param
mainArgs the arguments of the main method in the new isolate
param
app_classpath the application classpath(s) for the isolate
param
sys_classpath the system classpath(s) for the isolate (see Class path)
throws
IsolateStartupException if an error occurs in the configuration of the new isolate before any application code is invoked
throws
IllegalArgumentException if any parameters are found to be invalid.

        securityCheck();
        if (mainClass == null) {
            throw new IllegalArgumentException("specified class name is null");
        }
        registerNewIsolate();
        _priority = NORM_PRIORITY;
        _mainClass = mainClass;
        _mainArgs = argCopy(mainArgs);
        _app_classpath = argCopy(app_classpath);
        _sys_classpath = argCopy(sys_classpath);

        /*
         * <p>WARNING: DO NOT REMOVE THIS MESSAGE UNLESS YOU HAVE READ AND
         * UNDERSTOOD THE SECURITY IMPLICATIONS: HAVING UNTRUSTED USER
         * APPLICATION CLASSES ON THE SYSTEM CLASS PATH GRANTS THEM ACCESS TO
         * SYSTEM INTERNALS AND BREAKS SYSTEM SECURITY.
         */
        if (_sys_classpath.length != 0) {
          System.err.println();
          System.err.println("****warning****");
          System.err.println("****Untrusted user classes must never be put");
          System.err.println("****on the system class path");
          System.err.println("****warning****");
          System.err.println();
        }
    
Methods Summary
private java.lang.String[]argCopy(java.lang.String[] args)

        if (args == null) {
            return new String[0];
        }
        String[] result = new String[args.length];
        JVM.unchecked_obj_arraycopy(args, 0, result, 0, args.length);
        return result;
    
public voidattachDebugger()

        securityCheck();
        attachDebugger0(this);
    
private native voidattachDebugger0(com.sun.cldc.isolate.Isolate obj)

public static com.sun.cldc.isolate.IsolatecurrentIsolate()
Returns the Isolate object corresponding to the currently executing task.

This method never returns null.

return
the Isolate object for the current task

        securityCheck();
        return currentIsolate0();
    
private static native com.sun.cldc.isolate.IsolatecurrentIsolate0()

public voidexit(int status)
Requests normal termination of this Isolate. Invocation of this method is equivalent to causing the isolate to invoke {@link java.lang.Runtime#exit(int)}. If this method invocation is, in fact, the cause of the isolate's termination, the status supplied will be the isolate's termination status.

No exception is thrown if this isolate is already terminated. Even if {@link #isTerminated()} returns false prior to invoking exit, an invocation of exit may occur after the isolate exits on its own or is terminated by another isolate. In these cases, the actual exit code reported by the isolate may be different from status.

If this isolate is not yet started, it will be marked as already terminated. A subsequent invocation to {@link #start()} would result in an IsolateStartupException.

If this isolate is suspended, it will be terminated without being resumed.

param
status Termination status. By convention, a nonzero status code indicates abnormal termination.

        try {
            stop(status, this == currentIsolate() ?
                 EXIT_REASON_SELF_EXIT :
                 EXIT_REASON_OTHER_EXIT);
        } catch (SecurityException se) {
            stop(status, EXIT_REASON_SELF_EXIT);
        }
    
public intexitCode()
Returns the exit code of the isolate. If this Isolate has terminated, this method returns the exit code parameter to the first invocation of System.exit(), Isolate.exit() or Isolate.halt() that caused the Isolate to terminate. If this Isolate has terminated without calling System.exit(), Isolate.exit() or Isolate.halt(), then 0 is returned. If this Isolate has not started or has not terminated, 0 is returned.

return
the exit code of the isolate.

        return exitCode0();
    
private native intexitCode0()

public java.lang.String[]getClassPath()
Returns the classpath the Isolate was started with.

return
String[] that is equal to classpath argument passed to Isolate constructor

        return argCopy(_app_classpath);
    
public static com.sun.cldc.isolate.Isolate[]getIsolates()
Returns an array of Isolate objects representing all tasks that have been started but have not terminated. New tasks may have been constructed or existing ones terminated by the time this method returns.

return
the active Isolate objects at the time of the call

        securityCheck();
        return getIsolates0();
    
private static native com.sun.cldc.isolate.Isolate[]getIsolates0()

public intgetPriority()
Returns the priority of this isolate.

return
the priority of this isolate. If the isolate has already terminated, the returned value is undefined.

        return _priority;
    
private native intgetStatus()
Returns the current status of the task represented by this Isolate.

return
one of NEW, STARTED, STOPPING or STOPPED

public voidhalt(int status)
Forces termination of this Isolate. If this method invocation is in fact the cause of the isolate's termination, the status supplied will be the isolate's termination status.

No exception is thrown if this isolate is already terminated. Even if {@link #isTerminated()} returns false prior to invoking halt, an invocation of halt may occur after the isolate exits on its own or is terminated by another isolate. In these cases, the actual exit code reported by the isolate may be different from status.

If this isolate is not yet started, it will be marked as already terminated. A subsequent invocation to {@link #start()} would result in an IsolateStartupException.

If this isolate is suspended, it will be terminated without being resumed.

Implementation Note

Implementations should strive to implement "quick" termination with as little coordination with the target isolate as possible. The only information required of a terminated isolate is the exit code it was terminated with.

param
status Termination status. By convention, a nonzero status code indicates abnormal termination.

        try {
            stop(status, this == currentIsolate() ?
                 EXIT_REASON_SELF_HALT :
                 EXIT_REASON_OTHER_HALT);
        } catch (SecurityException se) {
            stop(status, EXIT_REASON_SELF_HALT);
        }
    
public intid()
Returns a small integer ID that uniquely identifies this Isolate among the current set of active Isolates. The returned ID will remain unchanged and reserved for this Isolate during its entire lifetime. However, after this Isolate is terminated, the ID may be resumed for a new Isolate.

return
-1 if the task has not been started or it has been terminated,

   // isolate was terminated --
                                            // see IsolateEvent.TERMINATED

                                                                               
       
        return id0();
    
private native intid0()

synchronized booleanisStarted()

        return getStatus() <= NEW;
    
public booleanisSuspended()
Returns if this isolate has been suspended.

return
true iff the isolate has been suspended.

        return (isSuspended0() != 0 ? true : false);
    
private native intisSuspended0()

public booleanisTerminated()
Returns true if this Isolate is terminated.

        int state = getStatus();
        return (state >= STOPPED);
    
private native voidnativeStart()

private native voidnotifyStatus()
Notify all threads that are waiting on the status of any Isolate object that represent the same task as this Isolate object. To simplify VM design, this method does NOT need to be called while holding a lock of such Isolate objects. To avert race conditions, the waiting threads must be blocked using waitStatus() instead of wait(). See comments inside waitForExit() for details.

private native voidregisterNewIsolate()
Add this Isolate to the TaskDesc::_seen_isolates list of the current task and return the globally unique isolate identifier.

public intreservedMemory()

return
the amount of object heap memory reserved for this Isolate.

        return _memoryReserve;
    
public voidresume()
The opposite of the suspend method. This method will resume the isolate only if the isolate is currently started, suspended and not terminated. Otherwise this method has no effect.

        resume0();
    
private native voidresume0()

private static voidsecurityCheck()
Determine if this isolate has permission to access the API If not, throw runtime exception

        if (_API_access_ok == 0) {
            throw new SecurityException("Access to Isolate API not allowed");
        }
    
public voidsetAPIAccess(boolean access)
Sets the access to Isolate API for this Isolate. This method should be used by the AMS, before the Isolate is started, to control whether or not a created Isolate is able to call the Isolate API. The default for all but the first Isolate is false. If the AMS calls this method after the Isolate has started, it has no effect.

In additional, after an Isolate has started, if it has access to the Isolate API, it can call this method to disable it. However, once it loses the access, attempts to call this method would result in a SecurityException.

        _APIAccess = (access == true ? 1 : 0);

        // Only allow access to be degraded after starting.
        if (!access && equals(currentIsolate())) {
            _API_access_ok = 0;
        }
    
public voidsetDebug(boolean mode)

        _ConnectDebugger = (mode == true ? 1 : 0);
    
public voidsetHiddenPackages(java.lang.String[] package_names)
Sets the packages which will be hidden. See definition of hidden package in doc/misc/Romizer.html. Note, that this function call overrides previous settings. If isolate is already started the method throws an IllegalIsolateStateException.

param
package_name. The name of package for marking.


                                                                         
          
      
      

                                                    
         
       
        if (getStatus() > NEW) {
            throw new IllegalIsolateStateException("Can only set hidden packages before Isolate starts");
        }
      _hidden_packages = package_names;
    
public voidsetMemoryQuota(int reserved)
Sets the object heap memory reserved and maximum limits to the same value. Note that if the system does not have sufficient resources to guaranteed the reserved amount, the start() method of this Isolate would fail. This method should only be called before the Isolate is started. Calling it after the isolate has started will cause undetermined behavior.

param
reserved The minimum amount of memory guaranteed to be available to the isolate at any time. Also the total amount of memory that the isolate can reserve.

        setMemoryQuota(reserved, reserved);
    
public voidsetMemoryQuota(int reserved, int total)
Sets the object heap memory quota for this Isolate. Note that if the system does not have sufficient resources to guaranteed the reserved amount, the start() method of this Isolate would fail. This method should only be called before the Isolate is started. Calling it after the isolate has started will cause undetermined behavior.

param
reserved The minimum amount of memory guaranteed to be available to the isolate at any time.
param
total The total amount of memory that the isolate can reserve.

        if (reserved < 0 || reserved > total) {
            throw new IllegalArgumentException();
        }
        _memoryReserve = reserved;
        _memoryLimit   = total; 
    
public voidsetPriority(int new_priority)
Adjust the priority of this Isolate. The priority controls the amount of CPU time that VM allocates to execute threads in this Isolate. Note: thread scheduling and task scheduling use separate mechanisms. In the current imeplentation, each task is guaranteed execution time relative to its priority.

param
new_priority must be between MIN_PRIORITY and MAX_PRIORITY, or else this method call will have no effect.

        if (new_priority >= MIN_PRIORITY && new_priority <= MAX_PRIORITY) {
            _priority = new_priority;
            setPriority0(new_priority);
        }
    
private native voidsetPriority0(int new_priority)

public native voidsetProfile(java.lang.String profile)
Sets active profile name for isolate. This method must be called before the isolate is started. If isolate is already started the method throws an IllegalIsolateStateException. The method also determines if profile is a name of existing profile which is defined in ROM configuration file. If not, throws runtime IllegalArgumentException.

param
profile The new active profile name.

public voidsetRestrictedPackages(java.lang.String[] package_names)
Sets the packages which will be restricted. See definition of restricted package in doc/misc/Romizer.html. Note, that this function call overrides previous settings. If isolate is already started the method throws an IllegalIsolateStateException.

param
package_name The name of package for marking.

        if (getStatus() > NEW) {
            throw new IllegalIsolateStateException("Can only set restricted packages before Isolate starts");
        }
      _restricted_packages = package_names;
    
public voidsetUseVerifier(boolean verify)
Controls whether or not classes for this isolate need to be verified. When creating a new Isolate, the AMS may waive verification for classes that have already been verified. The default is false. This method should be called before the Isolate is started.

        _UseVerifier = (verify == true ? 1 : 0);
    
public synchronized voidstart()
Start execution of this Isolate. Any code that belongs to this Isolate (including static initializers) is executed only after this method is called.

Control will return from this method when the new isolate's first user level thread starts executing, or if an error occurs during the initialization of the new isolate.

If any exception is thrown by this method, no code in the Isolate will have executed.

Errors such as the main class being invalid or not visible in the classpath will occur handled within the new isolate.

throws
IsolateStartupException if an error occurs in the initialization or configuration of the new isolate before any application code is invoked, or if this Isolate was already started or is terminated.
throws
IsolateResourceError if systems exceeds maximum Isolate count
throws
OutOfMemoryError if the reserved memory cannot be allocated

        if (getStatus() > NEW) {
            throw new IsolateStartupException("Isolate has already started");
        }

        try {
            nativeStart();
        } catch (IsolateResourceError e) {
            throw e;
        } catch (OutOfMemoryError e) {
            throw e;
        } catch (Throwable t) {
            // To be somewhat compilant to JSR-121, we do not pass any
            // other errors back to the caller of start().  Instead,
            // the caller can use Isolate.exitCode() to discover that
            // the isolate has exited. See CR 6270554.
        }

        // Wait till the fate of the started isolate is known
        // (STARTED or STOPPED...)
        while (getStatus() <= NEW) {
            try {
                // Note: do NOT use wait(). See comments inside waitForExit().
                waitStatus(NEW);
            } catch (InterruptedException e) {
                throw new IsolateStartupException(
                      "Exception was thrown while Isolate was starting");
            }
        }
    
private native voidstop(int exit_code, int exit_reason)
Stopping execution of an Isolate. Used by implementation of exit and halt.

If this isolate is not yet started, it will be marked as already terminated. A subsequent invocation to {@link #start()} would result in an IsolateStartupException.

If this isolate is suspended, it will be terminated without being resumed.

public voidsuspend()
Suspends all threads in this isolate from execution. This method should be used carefully if objects shared between isolates (passed via native methods) are used for synchornization. A suspended isolate holding a lock on such an object will stop other tasks from ever receiving that lock. See introduction for better ways of communicating between isolates. This method will suspend the isolate only if the isolate is currently started, not suspended and not terminated. Otherwise this method has no effect.

        suspend0();
    
private native voidsuspend0()

public inttotalMemory()

return
the maximum amount of object heap memory that can be allocated by this Isolate.

        return _memoryLimit;
    
public intusedMemory()
This function returns the approximate amount of object heap memory currently used by this Isolate. The approximate value may not be accurate: it may not include recent allocations made by the Isolate, and it may count objects allocated by the Isolate that have since become unreachable.

return
the approximate amount of object heap memory currently used by this Isolate.

        return usedMemory0();
    
private native intusedMemory0()

public synchronized voidwaitForExit()
Blocks the execution of the calling thread until this Isolate has exited. If waitForExit() is called on the current Isolate, the result is undefined.

throws
InterruptedException (unimplemented yet): if CLDC Specification 1.1 is enabled, when a thread is blocked inside this method, it may be interrupted by an invocation of Thread.interrupt, in which case an InterruptedException is thrown regardless of the termination status of this Isolate.

        while (getStatus() <= STOPPING) {
            try {
                // Note: do NOT use wait(): When notifyStatus() is
                // called, the calling thread may not hold the monitor
                // of this object, so if we wrote the code like this
                // we may get into a race condition
                //     while (getStatus() <= STOPPING) {
                //         <thread switch/race condition may happen here>
                //         wait();
                //     }
                // waitStatus() performs the getStatus() <= STOPPING check in
                // native code again, where thread switch is guaranteed to
                // not happen. Hence we won't have a race condition.
                waitStatus(STOPPING);
            } catch (InterruptedException e) {
                // IMPL_NOTE: this method should throw InterruptedException!
                throw new Error();
            }
        }
    
private native voidwaitStatus(int maxStatus)
Blocks the current thread until getStatus() would return a value greater than maxStatus, or (CLDC Spec 1.1 only) until this thread is interrupted.

See comments inside waitForExit() to see why this method method must be used instead of wait() to avert race conditions.