SUGGESTED FIX
// low-level hook, to be wrapped in one or more safe APIs:
class sun.misc.Unsafe;
/**
* Captures a snapshot of the JVM state, places it into the given exception,
* and throws it. The caller may choose to catch it immediately, or let
* someone up the call-chain catch it.
* <p>
* Later on, if the captured JVM state is resumed, the function returns normally,
* with whatever value the resumer provides, or (again) throws an exception,
* with whatever throwable the resumer provides. This can happen any number of
* times. Thus, we distinguish between the initial call to copyStack,
* and any number (zero or more) of returns.
* <p>
* If the context is null, the captured JVM state specifies all frames of
* the current thread. Otherwise, the context must correspond to a live
* call (in the same thread, not yet returned) to doCopyStackContext.
* (Correspondence is determined by reference identity, not Object.equals.)
* The captured JVM state then specifies only stack frames which are younger than
* that call to doCopyStackContext. It is an error for a resumed computation
* to attempt to return to that call to doCopyStackContext.
* The context is stored into the supplied CopyStackException, which must
* not already have a stored context. (That is, its 'stack' field must be null.)
* <p>
* Security note: The caller must be privileged, as TBD.
* All methods on the stack trace will have an opportunity to
* observe the thrown exception, but some may be less-privileged,
* and must be prevented from observing the contents of the stack.
* <p>
* Note: This method must return twice, and so two different execution
* paths must be created, either by some sort of data test (e.g., a boolean
* or a 2-array with one null element) or by distinguishing normal return
* from an exceptional return. This API uses the last option, because
* in many use cases (but not all) the copyStack call will be followed by
* some sort of suspension of the computation, back to a containing context,
* which will only ever be resume by an explicit resumeStack call.
*/
public native Object copyStack(Object context, CopyStackException ex)
throws CopyStackException;
/**
* Resume a captured snapshot of a JVM state, which is suspended at a call
* to copyStack. This call returns normally with the given value, or (if the
* exception is not null) by immediately throwing the given exception.
* <p>
* A captured snapshot may be resumed any number of times, with any combination
* of normal and abnormal exits, and in any thread (or many threads, concurrently).
* <p>
* Note that the stack object must be obtained from inside a CopyStackException.
* This is not possible unless copyStack and resumeStack agree on which
* subclass of CopyStackException they are using, and if that subclass
* grants resumeStack access to its internal 'stack' field.
*/
public native /*unreached*/ void resumeStack(Object stack, Object value, Throwable exception);
/**
* Establish a context for any nested calls to copyStack.
* The context object is arbitrary; often the expression new Object() works well.
* The run method is called.
* The only interesting use of this context object is as a non-null argument to copyStack.
*/
public native void doCopyStackContext(Object context, Runnable r);
+
/** Exception thrown by an initial call to copyStack. */
public static class CopyStackException extends RuntimeException {
/** The JVM state, in an implementation dependent format. */
protected Object stack;
}
|