logicalvm.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 405 行

JAVA
405
字号
/* * @(#)LogicalVM.java	1.8 06/10/27 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */package sun.misc;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.InvocationTargetException;import java.util.Vector;/* * Comments (FIXMEs) on the current Logical VM implementation: * * - Still under development. * - Java isolation API is still under discussion under JSR-121. *   Hopefully this implementation will cover major requirements. * - A parent LVM can die before its children, except the main LVM *   (the main LVM keeps itself alive until all the child LVMs get  *   terminated). * - Killing a parent LVM doesn't cause its children to die, except *   the main LVM (if we terminate the main LVM, all go die). * - No security checking done yet (no SecurityException). * - No state management (no "IllegalLogicalVMStateException" thrown) * - Uses remote (asynchronous) exception mechanism (ThreadDeath) when *   we terminate an LVM.  Enabling and disabling remote exceptions *   to protect key data structures are not completely revised yet. * - We also need to protect some of important finalizers (like one of *   FileOutputStream) so that it doesn't get terminated in the middle *   before freeing native resource by remote exceptions. * - Supposed to interrupt blocking operations performed by threads when *   we terminate an LVM, but this part is not implemented yet. *   We need to interrupt blocking I/O, monitor operations (including *   monitor enter), etc. * - Monitors for Class and String object are supposed to be replicated *   per LVM, but not implemented yet.  CVM code assumes one Class object *   per a class, so, instead of having multiple replicated Class objects *   per LVM, we replicate its monitor only.  There may need some other *   consideration so as for a Class object not to leak any objects from  *   one LVM to another.  As for String object, although it is immutable, *   the interned string support is making the situation difficult. *   Instead of going down the route to replicate the interned string  *   table in the VM, we just share the object and replicate its monitor  *   per LVM. * - None of JVMTI, JVMPI, RMI nor Personal[Basis]Profile work has done yet. *//* * Implementation of a handle class of Logical VM */public final class LogicalVM {    private Isolate isolate;    private LogicalVM(Isolate isolate) {	this.isolate = isolate;    }        public LogicalVM(String className, String[] args, String n) {	isolate = new Isolate(className, args, n);    }    public static LogicalVM getCurrentLogicalVM() {	return new LogicalVM(Isolate.getCurrent());    }    public LogicalVM getParent() {	return new LogicalVM(isolate.getParent());    }    public String getName() {	// A String objects is immutable and shared (we use per-LVM 	// String object lock).	return isolate.getName();    }    public void start() {	isolate.start();    }    public void join() throws InterruptedException {	isolate.join();    }    public void join(long millis) throws InterruptedException {	isolate.join(millis);    }    public void join(long millis, int nanos) throws InterruptedException {	isolate.join(millis, nanos);    }    public void exit(int exitCode) {	isolate.exit(exitCode);    }    public void halt(int exitCode) {    	isolate.halt(exitCode);    }    public boolean equals(Object obj) {	if (obj instanceof LogicalVM) {	    LogicalVM other = (LogicalVM)obj;	    return (this.isolate == other.isolate);	}	return false;    }}/* * Actual implementation of Logical VM */final class Isolate {    // Used by the native code to store pointer to per-Logical VM     // info data structure.    private int context = 0; /* FIXME: What about 64 bit support. */    private String name;    private Isolate parent;    private Isolate main;    private Thread launcher;    private RequestHandler requestHandler;    private String className;    private String[] args;    // Special attention needs to be paid for use of static fields    private static Isolate current;    private native void initContext(Thread initThread);    private native void destroyContext();    private static native void switchContext(Isolate target);    // Worm hole to invoke java.lang.Shutdown.waitAllUserThreads...()    private static native void waitAllUserThreadsExitAndShutdown();    // Worm hole to invoke java.lang.ref.Finalizer.runAllFinalizers()    private static native void runAllFinalizersOfSystemClass();    /*     * Private constructor for the main (primordial) Logical VM.     * This constructor will be invoked from native code during the JVM     * start up and before completion of the JVM initialization.     */    private Isolate() {	// We are still in the middle of main LVM initialization.	// Do not perform anything fancy (like starting a new thread).	name = "main";	parent = null;	main = this;	current = this;    }    public Isolate(String className, String[] args, String name) {	this.name = name;	parent = getCurrent();	main = parent.main;	this.className = className;	// Make duplicates of arguments so as not to share mutable objects 	// across LVMs.  String objects are immutable and shared.	this.args = new String[args.length];	System.arraycopy(args, 0, this.args, 0, args.length);	launcher = new Launcher("LVM " + name + " start-up thread");    }    public static Isolate getCurrent() {	return current;    }    public Isolate getParent() {	return parent;    }    public String getName() {	return name;    }    public void start() {	// Start this LVM form the context of the main LVM.	// This effectively keeps the main LVM alive until this LVM 	// terminates.	main.remoteRequest(launcher);    }    public void join() throws InterruptedException {	launcher.join();    }    public void join(long millis) throws InterruptedException {	launcher.join(millis);    }    public void join(long millis, int nanos) throws InterruptedException {	launcher.join(millis, nanos);    }    public void exit(int exitCode) {	remoteHaltOrExit(this, false, exitCode);    }    public void halt(int exitCode) {    	remoteHaltOrExit(this, true, exitCode);    }    private static void remoteHaltOrExit(Isolate target,					 final boolean isHalt,					 final int exitCode) {	Isolate initiatingLVM = getCurrent();	if (target != initiatingLVM) {	    target.remoteRequest(new Runnable() {		public void run() {		    haltOrExit(isHalt, exitCode);		}	    });	} else {	    haltOrExit(isHalt, exitCode);	}    }    private static void haltOrExit(boolean isHalt, int exitCode) {	Runtime rt = Runtime.getRuntime();	if (isHalt) {	    rt.halt(exitCode);	} else {	    rt.exit(exitCode);	}    }    private void startRequestHandler() {	requestHandler = new RequestHandler("LVM " + name +" request handler");	requestHandler.start();    }    private void startMainRequestHandler() {	startRequestHandler();	// The following line is for main LVM to make join()	// implementation simpler.  Anyway, the main LVM never terminates 	// while any of Java threads is running.  So, it doesn't matter.	launcher = requestHandler;    }    private void remoteRequest(Runnable proc) {	requestHandler.request(proc);    }    /*     * Helper class for executing a piece of code in this LVM's context.     */    private class RequestHandler extends Thread {	private Vector queue = new Vector();	public RequestHandler(String name) {	    super(name);	    setDaemon(true);	}	public synchronized void run() {	    setPriority(MAX_PRIORITY - 2);	    current = Isolate.this;	    while (!ThreadRegistry.exitRequested()) {		if (queue.size() == 0) {		    try {			wait();		    } catch (InterruptedException e) {			continue;		    }		}		Thread handler;		Object proc = queue.remove(0);		if (proc instanceof Thread) {		    handler = (Thread)proc;		} else {		    handler = new Thread((Runnable)proc);		}		handler.setDaemon(false);		handler.start();	    }	}	public synchronized void request(Runnable proc) {	    queue.add(proc);	    notify();	}    }    /*     * Helper class for launching an application in a new Logical VM.     */    private class Launcher extends Thread {	Launcher(String name) {	    super(name);	}	public void run() {	    // Don't allow any remote exception all the way	    CVM.disableRemoteExceptions();	    // Initializes a new Logical VM context and switch to it.	    initContext(this);	    current = Isolate.this;	    setPriority(Thread.NORM_PRIORITY);	    startRequestHandler();	    Throwable uncaughtException = null;	    try {		// Obtain the main ThreadGroup.  There should only be 		// one sub-group yet because of initContext().		ThreadGroup sys = Thread.currentThread().getThreadGroup();		ThreadGroup[] list = new ThreadGroup[1];		sys.enumerate(list, false);		ThreadGroup mainGroup = list[0];		// Start-up the main thread of this LVM		Thread main = new Thread(mainGroup, new MainExec(), "main");		main.start();		// Shutdown procedure for this LVM		waitAllUserThreadsExitAndShutdown();		ThreadRegistry.waitAllSystemThreadsExit();		runAllFinalizersOfSystemClass();	    } catch (Throwable t) {		uncaughtException = t;	    }	    // Switch the context back to the main LVM so that this 	    // thread gets removed from the main LVM's ThreadRegistry.	    // In this way, we keep the main LVM alive while any of	    // child LVMs is running.	    switchContext(main);	    // This is the last thread of this LVM	    Isolate.this.destroyContext();	    // Rethrow the uncaughtException and let the caller,	    // Thread.startup(), deal with it.	    if (uncaughtException != null) {		CVM.throwLocalException(uncaughtException);	    }	}    }    private class MainExec implements Runnable {	// Use Runnable so that a plain Thread object is used to run	// the main method of the new LVM.	public void run() {	    Throwable uncaughtException = null;	    try {		// Load the target class using the system class loader.		// This makes the main class loading procedure same		// as the ordinary JVM start-up.		ClassLoader scl = ClassLoader.getSystemClassLoader();		Class cls = scl.loadClass(className);		Class[] argClses = {String[].class};		// Returns public method only		Method mainMethod = cls.getMethod("main", argClses);		if (mainMethod.getReturnType() != Void.TYPE) {		    throw new NoSuchMethodException("return type is not void");		}		if (!Modifier.isStatic(mainMethod.getModifiers())) {		    throw new IllegalAccessException("main is not static");		}		Object[] argObjs = {args};		mainMethod.invoke(null, argObjs);	    } catch (InvocationTargetException ite) {		uncaughtException = ite.getTargetException();	    } catch (Throwable t) {		uncaughtException = t;	    }	    // Rethrow the uncaughtException and let the caller,	    // Thread.startup(), deal with it.	    if (uncaughtException != null) {		CVM.throwLocalException(uncaughtException);	    }	}    }    private static void dprintln(String s) {	if (CVM.checkDebugFlags(CVM.DEBUGFLAG_TRACE_LVM) != 0) {	    System.err.println(s);	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?