alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (VirtualMachineImpl.java)

This example Java source code file (VirtualMachineImpl.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

arraylist, arrayreferenceimpl, exception, instanceklass, jdi, list, list\/\*, objectreferenceimpl, referencetypeimpl, softobjectreference, string, symbol, threadgroupreferenceimpl, threadreferenceimpl, util, virtualmachineimpl

The VirtualMachineImpl.java Java example source code

/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code 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 code 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 in the LICENSE file that
 * accompanied this code).
 *
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.jdi;

import com.sun.jdi.*;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.request.EventRequestManager;

import sun.jvm.hotspot.HotSpotAgent;
import sun.jvm.hotspot.types.TypeDataBase;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.ArrayKlass;
import sun.jvm.hotspot.oops.ObjArrayKlass;
import sun.jvm.hotspot.oops.TypeArrayKlass;
import sun.jvm.hotspot.oops.Oop;
import sun.jvm.hotspot.oops.Instance;
import sun.jvm.hotspot.oops.Array;
import sun.jvm.hotspot.oops.ObjArray;
import sun.jvm.hotspot.oops.TypeArray;
import sun.jvm.hotspot.oops.Symbol;
import sun.jvm.hotspot.oops.ObjectHeap;
import sun.jvm.hotspot.oops.DefaultHeapVisitor;
import sun.jvm.hotspot.oops.JVMDIClassStatus;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.runtime.JavaThread;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.memory.SymbolTable;
import sun.jvm.hotspot.memory.Universe;
import sun.jvm.hotspot.utilities.Assert;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Iterator;
import java.util.Collections;
import java.util.HashMap;
import java.util.Observer;
import java.util.StringTokenizer;
import java.lang.ref.SoftReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.Reference;

public class VirtualMachineImpl extends MirrorImpl implements PathSearchingVirtualMachine {

    private HotSpotAgent     saAgent = new HotSpotAgent();
    private VM               saVM;
    private Universe         saUniverse;
    private SystemDictionary saSystemDictionary;
    private SymbolTable      saSymbolTable;
    private ObjectHeap       saObjectHeap;

    VM saVM() {
        return saVM;
    }

    SystemDictionary saSystemDictionary() {
        return saSystemDictionary;
    }

    SymbolTable saSymbolTable() {
        return saSymbolTable;
    }

    Universe saUniverse() {
        return saUniverse;
    }

    ObjectHeap saObjectHeap() {
        return saObjectHeap;
    }

    com.sun.jdi.VirtualMachineManager vmmgr;

    private final ThreadGroup             threadGroupForJDI;

    // Per-vm singletons for primitive types and for void.
    // singleton-ness protected by "synchronized(this)".
    private BooleanType theBooleanType;
    private ByteType    theByteType;
    private CharType    theCharType;
    private ShortType   theShortType;
    private IntegerType theIntegerType;
    private LongType    theLongType;
    private FloatType   theFloatType;
    private DoubleType  theDoubleType;

    private VoidType    theVoidType;

    private VoidValue voidVal;
    private Map       typesByID;             // Map<Klass, ReferenceTypeImpl>
    private List      typesBySignature;      // List<ReferenceTypeImpl> - used in signature search
    private boolean   retrievedAllTypes = false;
    private List      bootstrapClasses;      // all bootstrap classes
    private ArrayList allThreads;
    private ArrayList topLevelGroups;
    final   int       sequenceNumber;

    // ObjectReference cache
    // "objectsByID" protected by "synchronized(this)".
    private final Map            objectsByID = new HashMap();
    private final ReferenceQueue referenceQueue = new ReferenceQueue();

    // names of some well-known classes to jdi
    private Symbol javaLangString;
    private Symbol javaLangThread;
    private Symbol javaLangThreadGroup;
    private Symbol javaLangClass;
    private Symbol javaLangClassLoader;

    // used in ReferenceTypeImpl.isThrowableBacktraceField
    private Symbol javaLangThrowable;

    // names of classes used in array assignment check
    // refer to ArrayTypeImpl.isAssignableTo
    private Symbol javaLangObject;
    private Symbol javaLangCloneable;
    private Symbol javaIoSerializable;

    // symbol used in ClassTypeImpl.isEnum check
    private Symbol javaLangEnum;

    Symbol javaLangObject() {
        return javaLangObject;
    }

    Symbol javaLangCloneable() {
        return javaLangCloneable;
    }

    Symbol javaIoSerializable() {
        return javaIoSerializable;
    }

    Symbol javaLangEnum() {
        return javaLangEnum;
    }

    Symbol javaLangThrowable() {
        return javaLangThrowable;
    }

    // name of the current default stratum
    private String defaultStratum;

    // initialize known class name symbols
    private void initClassNameSymbols() {
        SymbolTable st = saSymbolTable();
        javaLangString = st.probe("java/lang/String");
        javaLangThread = st.probe("java/lang/Thread");
        javaLangThreadGroup = st.probe("java/lang/ThreadGroup");
        javaLangClass = st.probe("java/lang/Class");
        javaLangClassLoader = st.probe("java/lang/ClassLoader");
        javaLangThrowable = st.probe("java/lang/Throwable");
        javaLangObject = st.probe("java/lang/Object");
        javaLangCloneable = st.probe("java/lang/Cloneable");
        javaIoSerializable = st.probe("java/io/Serializable");
        javaLangEnum = st.probe("java/lang/Enum");
    }

    private void init() {
        saVM = VM.getVM();
        saUniverse = saVM.getUniverse();
        saSystemDictionary = saVM.getSystemDictionary();
        saSymbolTable = saVM.getSymbolTable();
        saObjectHeap = saVM.getObjectHeap();
        initClassNameSymbols();
    }

    static public VirtualMachineImpl createVirtualMachineForCorefile(VirtualMachineManager mgr,
                                                                     String javaExecutableName,
                                                                     String coreFileName,
                                                                     int sequenceNumber)
        throws Exception {
        if (Assert.ASSERTS_ENABLED) {
            Assert.that(coreFileName != null, "SA VirtualMachineImpl: core filename = null is not yet implemented");
        }
        if (Assert.ASSERTS_ENABLED) {
            Assert.that(javaExecutableName != null, "SA VirtualMachineImpl: java executable = null is not yet implemented");
        }

        VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
        try {
            myvm.saAgent.attach(javaExecutableName, coreFileName);
            myvm.init();
        } catch (Exception ee) {
            myvm.saAgent.detach();
            throw ee;
        }
        return myvm;
    }

    static public VirtualMachineImpl createVirtualMachineForPID(VirtualMachineManager mgr,
                                                                int pid,
                                                                int sequenceNumber)
        throws Exception {

        VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
        try {
            myvm.saAgent.attach(pid);
            myvm.init();
        } catch (Exception ee) {
            myvm.saAgent.detach();
            throw ee;
        }
        return myvm;
    }

    static public VirtualMachineImpl createVirtualMachineForServer(VirtualMachineManager mgr,
                                                                String server,
                                                                int sequenceNumber)
        throws Exception {
        if (Assert.ASSERTS_ENABLED) {
            Assert.that(server != null, "SA VirtualMachineImpl: DebugServer = null is not yet implemented");
        }

        VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
        try {
            myvm.saAgent.attach(server);
            myvm.init();
        } catch (Exception ee) {
            myvm.saAgent.detach();
            throw ee;
        }
        return myvm;
    }


    VirtualMachineImpl(VirtualMachineManager mgr, int sequenceNumber)
        throws Exception {
        super(null);  // Can't use super(this)
        vm = this;

        this.sequenceNumber = sequenceNumber;
        this.vmmgr = mgr;

        /* Create ThreadGroup to be used by all threads servicing
         * this VM.
         */
        threadGroupForJDI = new ThreadGroup("JDI [" +
                                            this.hashCode() + "]");

        ((com.sun.tools.jdi.VirtualMachineManagerImpl)mgr).addVirtualMachine(this);

        // By default SA agent classes prefer Windows process debugger
        // to windbg debugger. SA expects special properties to be set
        // to choose other debuggers. We will set those here before
        // attaching to SA agent.

        System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true");
    }

    // we reflectively use newly spec'ed class because our ALT_BOOTDIR
    // is 1.4.2 and not 1.5.
    private static Class vmCannotBeModifiedExceptionClass = null;
    void throwNotReadOnlyException(String operation) {
        RuntimeException re = null;
        if (vmCannotBeModifiedExceptionClass == null) {
            try {
                vmCannotBeModifiedExceptionClass = Class.forName("com.sun.jdi.VMCannotBeModifiedException");
            } catch (ClassNotFoundException cnfe) {
                vmCannotBeModifiedExceptionClass = UnsupportedOperationException.class;
            }
        }
        try {
            re = (RuntimeException) vmCannotBeModifiedExceptionClass.newInstance();
        } catch (Exception exp) {
            re = new RuntimeException(exp.getMessage());
        }
        throw re;
    }

    public boolean equals(Object obj) {
        // Oh boy; big recursion troubles if we don't have this!
        // See MirrorImpl.equals
        return this == obj;
    }

    public int hashCode() {
        // big recursion if we don't have this. See MirrorImpl.hashCode
        return System.identityHashCode(this);
    }

    public List classesByName(String className) {
        String signature = JNITypeParser.typeNameToSignature(className);
        List list;
        if (!retrievedAllTypes) {
            retrieveAllClasses();
        }
        list = findReferenceTypes(signature);
        return Collections.unmodifiableList(list);
    }

    public List allClasses() {
        if (!retrievedAllTypes) {
            retrieveAllClasses();
        }
        ArrayList a;
        synchronized (this) {
            a = new ArrayList(typesBySignature);
        }
        return Collections.unmodifiableList(a);
    }

    // classes loaded by bootstrap loader
    List bootstrapClasses() {
        if (bootstrapClasses == null) {
            bootstrapClasses = new ArrayList();
            List all = allClasses();
            for (Iterator itr = all.iterator(); itr.hasNext();) {
               ReferenceType type = (ReferenceType) itr.next();
               if (type.classLoader() == null) {
                   bootstrapClasses.add(type);
               }
            }
        }
        return bootstrapClasses;
    }

    private synchronized List findReferenceTypes(String signature) {
        if (typesByID == null) {
            return new ArrayList(0);
        }

        // we haven't sorted types by signatures. But we can take
        // advantage of comparing symbols instead of name. In the worst
        // case, we will be comparing N addresses rather than N strings
        // where N being total no. of classes in allClasses() list.

        // The signature could be Lx/y/z; or [....
        // If it is Lx/y/z; the internal type name is x/y/x
        // for array klasses internal type name is same as
        // signature
        String typeName = null;
        if (signature.charAt(0) == 'L') {
            typeName = signature.substring(1, signature.length() - 1);
        } else {
            typeName = signature;
        }

        Symbol typeNameSym = saSymbolTable().probe(typeName);
        // if there is no symbol in VM, then we wouldn't have that type
        if (typeNameSym == null) {
            return new ArrayList(0);
        }

        Iterator iter = typesBySignature.iterator();
        List list = new ArrayList();
        while (iter.hasNext()) {
            // We have cached type name as symbol in reference type
            ReferenceTypeImpl type = (ReferenceTypeImpl)iter.next();
            if (typeNameSym.equals(type.typeNameAsSymbol())) {
                list.add(type);
            }
        }
        return list;
    }

    private void retrieveAllClasses() {
        final List saKlasses = new ArrayList();
        SystemDictionary.ClassVisitor visitor = new SystemDictionary.ClassVisitor() {
                public void visit(Klass k) {
                    for (Klass l = k; l != null; l = l.arrayKlassOrNull()) {
                        // for non-array classes filter out un-prepared classes
                        // refer to 'allClasses' in share/back/VirtualMachineImpl.c
                        if (l instanceof ArrayKlass) {
                           saKlasses.add(l);
                        } else {
                           int status = l.getClassStatus();
                           if ((status & JVMDIClassStatus.PREPARED) != 0) {
                               saKlasses.add(l);
                           }
                        }
                    }
                }
        };

        // refer to jvmtiGetLoadedClasses.cpp - getLoadedClasses in VM code.

        // classes from SystemDictionary
        saSystemDictionary.classesDo(visitor);

        // From SystemDictionary we do not get primitive single
        // dimensional array classes. add primitive single dimensional array
        // klasses from Universe.
        saVM.getUniverse().basicTypeClassesDo(visitor);

        // Hold lock during processing to improve performance
        // and to have safe check/set of retrievedAllTypes
        synchronized (this) {
            if (!retrievedAllTypes) {
                // Number of classes
                int count = saKlasses.size();
                for (int ii = 0; ii < count; ii++) {
                    Klass kk = (Klass)saKlasses.get(ii);
                    ReferenceTypeImpl type = referenceType(kk);
                }
                retrievedAllTypes = true;
            }
        }
    }

    ReferenceTypeImpl referenceType(Klass kk) {
        ReferenceTypeImpl retType = null;
        synchronized (this) {
            if (typesByID != null) {
                retType = (ReferenceTypeImpl)typesByID.get(kk);
            }
            if (retType == null) {
                retType = addReferenceType(kk);
            }
        }
        return retType;
    }

    private void initReferenceTypes() {
        typesByID = new HashMap();
        typesBySignature = new ArrayList();
    }

    private synchronized ReferenceTypeImpl addReferenceType(Klass kk) {
        if (typesByID == null) {
            initReferenceTypes();
        }
        ReferenceTypeImpl newRefType = null;
        if (kk instanceof ObjArrayKlass || kk instanceof TypeArrayKlass) {
            newRefType = new ArrayTypeImpl(this, (ArrayKlass)kk);
        } else if (kk instanceof InstanceKlass) {
            if (kk.isInterface()) {
                newRefType = new InterfaceTypeImpl(this, (InstanceKlass)kk);
            } else {
                newRefType = new ClassTypeImpl(this, (InstanceKlass)kk);
            }
        } else {
            throw new RuntimeException("should not reach here:" + kk);
        }

        typesByID.put(kk, newRefType);
        typesBySignature.add(newRefType);
        return newRefType;
    }

    ThreadGroup threadGroupForJDI() {
        return threadGroupForJDI;
    }

    public void redefineClasses(Map classToBytes) {
        throwNotReadOnlyException("VirtualMachineImpl.redefineClasses()");
    }

    private List getAllThreads() {
        if (allThreads == null) {
            allThreads = new ArrayList(10);  // Might be enough, might not be
            for (sun.jvm.hotspot.runtime.JavaThread thread =
                     saVM.getThreads().first(); thread != null;
                     thread = thread.next()) {
                // refer to JvmtiEnv::GetAllThreads in jvmtiEnv.cpp.
                // filter out the hidden-from-external-view threads.
                if (thread.isHiddenFromExternalView() == false) {
                    ThreadReferenceImpl myThread = threadMirror(thread);
                    allThreads.add(myThread);
                }
            }
        }
        return allThreads;
    }

    public List allThreads() { //fixme jjh
        return Collections.unmodifiableList(getAllThreads());
    }

    public void suspend() {
        throwNotReadOnlyException("VirtualMachineImpl.suspend()");
    }

    public void resume() {
        throwNotReadOnlyException("VirtualMachineImpl.resume()");
    }

    public List topLevelThreadGroups() { //fixme jjh
        // The doc for ThreadGroup says that The top-level thread group
        // is the only thread group whose parent is null.  This means there is
        // only one top level thread group.  There will be a thread in this
        // group so we will just find a thread whose threadgroup has no parent
        // and that will be it.

        if (topLevelGroups == null) {
            topLevelGroups = new ArrayList(1);
            Iterator myIt = getAllThreads().iterator();
            while (myIt.hasNext()) {
                ThreadReferenceImpl myThread = (ThreadReferenceImpl)myIt.next();
                ThreadGroupReference myGroup = myThread.threadGroup();
                ThreadGroupReference myParent = myGroup.parent();
                if (myGroup.parent() == null) {
                    topLevelGroups.add(myGroup);
                    break;
                }
            }
        }
        return  Collections.unmodifiableList(topLevelGroups);
    }

    public EventQueue eventQueue() {
        throwNotReadOnlyException("VirtualMachine.eventQueue()");
        return null;
    }

    public EventRequestManager eventRequestManager() {
        throwNotReadOnlyException("VirtualMachineImpl.eventRequestManager()");
        return null;
    }

    public BooleanValue mirrorOf(boolean value) {
        return new BooleanValueImpl(this,value);
    }

    public ByteValue mirrorOf(byte value) {
        return new ByteValueImpl(this,value);
    }

    public CharValue mirrorOf(char value) {
        return new CharValueImpl(this,value);
    }

    public ShortValue mirrorOf(short value) {
        return new ShortValueImpl(this,value);
    }

    public IntegerValue mirrorOf(int value) {
        return new IntegerValueImpl(this,value);
    }

    public LongValue mirrorOf(long value) {
        return new LongValueImpl(this,value);
    }

    public FloatValue mirrorOf(float value) {
        return new FloatValueImpl(this,value);
    }

    public DoubleValue mirrorOf(double value) {
        return new DoubleValueImpl(this,value);
    }

    public StringReference mirrorOf(String value) {
        throwNotReadOnlyException("VirtualMachinestop.mirrorOf(String)");
        return null;
    }

    public VoidValue mirrorOfVoid() {
        if (voidVal == null) {
            voidVal = new VoidValueImpl(this);
        }
        return voidVal;
    }


    public Process process() {
        throwNotReadOnlyException("VirtualMachine.process");
        return null;
    }

    // dispose observer for Class re-use. refer to ConnectorImpl.
    private Observer disposeObserver;

    // ConnectorImpl loaded by a different class loader can not access it.
    // i.e., runtime package of <ConnectorImpl, L1> is not the same that of
    // <VirtualMachineImpl, L2> when L1 != L2. So, package private method
    // can be called reflectively after using setAccessible(true).

    void setDisposeObserver(Observer observer) {
       disposeObserver = observer;
    }

    private void notifyDispose() {
        if (Assert.ASSERTS_ENABLED) {
            Assert.that(disposeObserver != null, "null VM.dispose observer");
        }
        disposeObserver.update(null, null);
    }

    public void dispose() {
        saAgent.detach();
        notifyDispose();
    }

    public void exit(int exitCode) {
        throwNotReadOnlyException("VirtualMachine.exit(int)");
    }

    public boolean canBeModified() {
        return false;
    }

    public boolean canWatchFieldModification() {
        return false;
    }

    public boolean canWatchFieldAccess() {
        return false;
    }

    public boolean canGetBytecodes() {
        return true;
    }

    public boolean canGetSyntheticAttribute() {
        return true;
    }

    // FIXME: For now, all monitor capabilities are disabled
    public boolean canGetOwnedMonitorInfo() {
        return false;
    }

    public boolean canGetCurrentContendedMonitor() {
        return false;
    }

    public boolean canGetMonitorInfo() {
        return false;
    }

    // because this SA works only with 1.5 and update releases
    // this should always succeed unlike JVMDI/JDI.
    public boolean canGet1_5LanguageFeatures() {
        return true;
    }

    public boolean canUseInstanceFilters() {
        return false;
    }

    public boolean canRedefineClasses() {
        return false;
    }

    public boolean canAddMethod() {
        return false;
    }

    public boolean canUnrestrictedlyRedefineClasses() {
        return false;
    }

    public boolean canPopFrames() {
        return false;
    }

    public boolean canGetSourceDebugExtension() {
        // We can use InstanceKlass.getSourceDebugExtension only if
        // ClassFileParser parsed the info. But, ClassFileParser parses
        // SourceDebugExtension attribute only if corresponding JVMDI/TI
        // capability is set to true. Currently, vmStructs does not expose
        // JVMDI/TI capabilities and hence we conservatively assume false.
        return false;
    }

    public boolean canRequestVMDeathEvent() {
        return false;
    }

    // new method since 1.6
    public boolean canForceEarlyReturn() {
        return false;
    }

    // new method since 1.6
    public boolean canGetConstantPool() {
        return true;
    }

    // new method since 1.6
    public boolean canGetClassFileVersion() {
        return true;
    }

    // new method since 1.6.
    public boolean canGetMethodReturnValues() {
        return false;
    }

    // new method since 1.6
    // Real body will be supplied later.
    public boolean canGetInstanceInfo() {
        return true;
    }

    // new method since 1.6
    public boolean canUseSourceNameFilters() {
        return false;
    }

    // new method since 1.6.
    public boolean canRequestMonitorEvents() {
        return false;
    }

    // new method since 1.6.
    public boolean canGetMonitorFrameInfo() {
        return true;
    }

    // new method since 1.6
    // Real body will be supplied later.
    public long[] instanceCounts(List classes) {
        if (!canGetInstanceInfo()) {
            throw new UnsupportedOperationException(
                      "target does not support getting instances");
        }

        final long[] retValue = new long[classes.size()] ;

        final Klass [] klassArray = new Klass[classes.size()];

        boolean allAbstractClasses = true;
        for (int i=0; i < classes.size(); i++) {
            ReferenceTypeImpl rti = (ReferenceTypeImpl)classes.get(i);
            klassArray[i] = rti.ref();
            retValue[i]=0;
            if (!(rti.isAbstract() || ((ReferenceType)rti instanceof InterfaceType))) {
                allAbstractClasses = false;
            }
        }

        if (allAbstractClasses) {
            return retValue;
        }
        final int size = classes.size();
        saObjectHeap.iterate(new DefaultHeapVisitor() {
                public boolean doObj(Oop oop) {
                    for (int i=0; i < size; i++) {
                        if (klassArray[i].equals(oop.getKlass())) {
                            retValue[i]++;
                            break;
                        }
                    }
                                        return false;
                }
            });

        return retValue;
    }

    private List getPath (String pathName) {
        String cp = saVM.getSystemProperty(pathName);
        String pathSep = saVM.getSystemProperty("path.separator");
        ArrayList al = new ArrayList();
        StringTokenizer st = new StringTokenizer(cp, pathSep);
        while (st.hasMoreTokens()) {
            al.add(st.nextToken());
        }
        al.trimToSize();
        return al;
    }

    public List classPath() {
        return getPath("java.class.path");
    }

    public List bootClassPath() {
        return getPath("sun.boot.class.path");
    }

    public String baseDirectory() {
        return saVM.getSystemProperty("user.dir");
    }

    public void setDefaultStratum(String stratum) {
        defaultStratum = stratum;
    }

    public String getDefaultStratum() {
        return defaultStratum;
    }

    public String description() {
        return java.text.MessageFormat.format(java.util.ResourceBundle.
                                              getBundle("com.sun.tools.jdi.resources.jdi").getString("version_format"),
                                              "" + vmmgr.majorInterfaceVersion(),
                                              "" + vmmgr.minorInterfaceVersion(),
                                              name());
    }

    public String version() {
        return saVM.getSystemProperty("java.version");
    }

    public String name() {
        StringBuffer sb = new StringBuffer();
        sb.append("JVM version ");
        sb.append(version());
        sb.append(" (");
        sb.append(saVM.getSystemProperty("java.vm.name"));
        sb.append(", ");
        sb.append(saVM.getSystemProperty("java.vm.info"));
        sb.append(")");
        return sb.toString();
    }

    // from interface Mirror
    public VirtualMachine virtualMachine() {
        return this;
    }

    public String toString() {
        return name();
    }

    public void setDebugTraceMode(int traceFlags) {
        // spec. says output is implementation dependent
        // and trace mode may be ignored. we ignore it :-)
    }

    // heap walking API

    // capability check
    public boolean canWalkHeap() {
        return true;
    }

    // return a list of all objects in heap
    public List/*<ObjectReference>*/ allObjects() {
        final List objects = new ArrayList(0);
        saObjectHeap.iterate(
            new DefaultHeapVisitor() {
                public boolean doObj(Oop oop) {
                    objects.add(objectMirror(oop));
                                        return false;
                }
            });
        return objects;
    }

    // equivalent to objectsByType(type, true)
    public List/*<ObjectReference>*/ objectsByType(ReferenceType type) {
        return objectsByType(type, true);
    }

    // returns objects of type exactly equal to given type
    private List/*<ObjectReference>*/ objectsByExactType(ReferenceType type) {
        final List objects = new ArrayList(0);
        final Klass givenKls = ((ReferenceTypeImpl)type).ref();
        saObjectHeap.iterate(new DefaultHeapVisitor() {
                public boolean doObj(Oop oop) {
                    if (givenKls.equals(oop.getKlass())) {
                        objects.add(objectMirror(oop));
                    }
                        return false;
                }
            });
        return objects;
    }

    // returns objects of given type as well as it's subtypes
    private List/*<ObjectReference>*/ objectsBySubType(ReferenceType type) {
        final List objects = new ArrayList(0);
        final ReferenceType givenType = type;
        saObjectHeap.iterate(new DefaultHeapVisitor() {
                public boolean doObj(Oop oop) {
                    ReferenceTypeImpl curType = (ReferenceTypeImpl) referenceType(oop.getKlass());
                    if (curType.isAssignableTo(givenType)) {
                        objects.add(objectMirror(oop));
                    }
                        return false;
                }
            });
        return objects;
    }

    // includeSubtypes - do you want to include subclass/subtype instances of given
    // ReferenceType or do we want objects of exact type only?
    public List/*<ObjectReference>*/ objectsByType(ReferenceType type, boolean includeSubtypes) {
        Klass kls = ((ReferenceTypeImpl)type).ref();
        if (kls instanceof InstanceKlass) {
            InstanceKlass ik = (InstanceKlass) kls;
            // if the Klass is final or if there are no subklasses loaded yet
            if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
                includeSubtypes = false;
            }
        } else {
            // no subtypes for primitive array types
            ArrayTypeImpl arrayType = (ArrayTypeImpl) type;
            try {
                Type componentType = arrayType.componentType();
                if (componentType instanceof PrimitiveType) {
                    includeSubtypes = false;
                }
            } catch (ClassNotLoadedException cnle) {
                // ignore. component type not yet loaded
            }
        }

        if (includeSubtypes) {
            return objectsBySubType(type);
        } else {
            return objectsByExactType(type);
        }
    }

    Type findBootType(String signature) throws ClassNotLoadedException {
        List types = allClasses();
        Iterator iter = types.iterator();
        while (iter.hasNext()) {
            ReferenceType type = (ReferenceType)iter.next();
            if ((type.classLoader() == null) &&
                (type.signature().equals(signature))) {
                return type;
            }
        }
        JNITypeParser parser = new JNITypeParser(signature);
        throw new ClassNotLoadedException(parser.typeName(),
                                         "Type " + parser.typeName() + " not loaded");
    }

    BooleanType theBooleanType() {
        if (theBooleanType == null) {
            synchronized(this) {
                if (theBooleanType == null) {
                    theBooleanType = new BooleanTypeImpl(this);
                }
            }
        }
        return theBooleanType;
    }

    ByteType theByteType() {
        if (theByteType == null) {
            synchronized(this) {
                if (theByteType == null) {
                    theByteType = new ByteTypeImpl(this);
                }
            }
        }
        return theByteType;
    }

    CharType theCharType() {
        if (theCharType == null) {
            synchronized(this) {
                if (theCharType == null) {
                    theCharType = new CharTypeImpl(this);
                }
            }
        }
        return theCharType;
    }

    ShortType theShortType() {
        if (theShortType == null) {
            synchronized(this) {
                if (theShortType == null) {
                    theShortType = new ShortTypeImpl(this);
                }
            }
        }
        return theShortType;
    }

    IntegerType theIntegerType() {
        if (theIntegerType == null) {
            synchronized(this) {
                if (theIntegerType == null) {
                    theIntegerType = new IntegerTypeImpl(this);
                }
            }
        }
        return theIntegerType;
    }

    LongType theLongType() {
        if (theLongType == null) {
            synchronized(this) {
                if (theLongType == null) {
                    theLongType = new LongTypeImpl(this);
                }
            }
        }
        return theLongType;
    }

    FloatType theFloatType() {
        if (theFloatType == null) {
            synchronized(this) {
                if (theFloatType == null) {
                    theFloatType = new FloatTypeImpl(this);
                }
            }
        }
        return theFloatType;
    }

    DoubleType theDoubleType() {
        if (theDoubleType == null) {
            synchronized(this) {
                if (theDoubleType == null) {
                    theDoubleType = new DoubleTypeImpl(this);
                }
            }
        }
        return theDoubleType;
    }

    VoidType theVoidType() {
        if (theVoidType == null) {
            synchronized(this) {
                if (theVoidType == null) {
                    theVoidType = new VoidTypeImpl(this);
                }
            }
        }
        return theVoidType;
    }

    PrimitiveType primitiveTypeMirror(char tag) {
        switch (tag) {
        case 'Z':
                return theBooleanType();
        case 'B':
                return theByteType();
        case 'C':
                return theCharType();
        case 'S':
                return theShortType();
        case 'I':
                return theIntegerType();
        case 'J':
                return theLongType();
        case 'F':
                return theFloatType();
        case 'D':
                return theDoubleType();
        default:
                throw new IllegalArgumentException("Unrecognized primitive tag " + tag);
        }
    }

    private void processQueue() {
        Reference ref;
        while ((ref = referenceQueue.poll()) != null) {
            SoftObjectReference softRef = (SoftObjectReference)ref;
            removeObjectMirror(softRef);
        }
    }

    // Address value is used as uniqueID by ObjectReferenceImpl
    long getAddressValue(Oop obj) {
        return vm.saVM.getDebugger().getAddressValue(obj.getHandle());
    }

    synchronized ObjectReferenceImpl objectMirror(Oop key) {

        // Handle any queue elements that are not strongly reachable
        processQueue();

        if (key == null) {
            return null;
        }
        ObjectReferenceImpl object = null;

        /*
         * Attempt to retrieve an existing object object reference
         */
        SoftObjectReference ref = (SoftObjectReference)objectsByID.get(key);
        if (ref != null) {
            object = ref.object();
        }

        /*
         * If the object wasn't in the table, or it's soft reference was
         * cleared, create a new instance.
         */
        if (object == null) {
            if (key instanceof Instance) {
                // look for well-known classes
                Symbol className = key.getKlass().getName();
                if (Assert.ASSERTS_ENABLED) {
                    Assert.that(className != null, "Null class name");
                }
                Instance inst = (Instance) key;
                if (className.equals(javaLangString)) {
                    object = new StringReferenceImpl(this, inst);
                } else if (className.equals(javaLangThread)) {
                    object = new ThreadReferenceImpl(this, inst);
                } else if (className.equals(javaLangThreadGroup)) {
                    object = new ThreadGroupReferenceImpl(this, inst);
                } else if (className.equals(javaLangClass)) {
                    object = new ClassObjectReferenceImpl(this, inst);
                } else if (className.equals(javaLangClassLoader)) {
                    object = new ClassLoaderReferenceImpl(this, inst);
                } else {
                    // not a well-known class. But the base class may be
                    // one of the known classes.
                    Klass kls = key.getKlass().getSuper();
                    while (kls != null) {
                       className = kls.getName();
                       // java.lang.Class and java.lang.String are final classes
                       if (className.equals(javaLangThread)) {
                          object = new ThreadReferenceImpl(this, inst);
                          break;
                       } else if(className.equals(javaLangThreadGroup)) {
                          object = new ThreadGroupReferenceImpl(this, inst);
                          break;
                       } else if (className.equals(javaLangClassLoader)) {
                          object = new ClassLoaderReferenceImpl(this, inst);
                          break;
                       }
                       kls = kls.getSuper();
                    }

                    if (object == null) {
                       // create generic object reference
                       object = new ObjectReferenceImpl(this, inst);
                    }
                }
            } else if (key instanceof TypeArray) {
                object = new ArrayReferenceImpl(this, (Array) key);
            } else if (key instanceof ObjArray) {
                object = new ArrayReferenceImpl(this, (Array) key);
            } else {
                throw new RuntimeException("unexpected object type " + key);
            }
            ref = new SoftObjectReference(key, object, referenceQueue);

            /*
             * If there was no previous entry in the table, we add one here
             * If the previous entry was cleared, we replace it here.
             */
            objectsByID.put(key, ref);
        } else {
            ref.incrementCount();
        }

        return object;
    }

    synchronized void removeObjectMirror(SoftObjectReference ref) {
        /*
         * This will remove the soft reference if it has not been
         * replaced in the cache.
         */
        objectsByID.remove(ref.key());
    }

    StringReferenceImpl stringMirror(Instance id) {
        return (StringReferenceImpl) objectMirror(id);
    }

    ArrayReferenceImpl arrayMirror(Array id) {
       return (ArrayReferenceImpl) objectMirror(id);
    }

    ThreadReferenceImpl threadMirror(Instance id) {
        return (ThreadReferenceImpl) objectMirror(id);
    }

    ThreadReferenceImpl threadMirror(JavaThread jt) {
        return (ThreadReferenceImpl) objectMirror(jt.getThreadObj());
    }

    ThreadGroupReferenceImpl threadGroupMirror(Instance id) {
        return (ThreadGroupReferenceImpl) objectMirror(id);
    }

    ClassLoaderReferenceImpl classLoaderMirror(Instance id) {
        return (ClassLoaderReferenceImpl) objectMirror(id);
    }

    ClassObjectReferenceImpl classObjectMirror(Instance id) {
        return (ClassObjectReferenceImpl) objectMirror(id);
    }

    // Use of soft refs and caching stuff here has to be re-examined.
    //  It might not make sense for JDI - SA.
    static private class SoftObjectReference extends SoftReference {
       int count;
       Object key;

       SoftObjectReference(Object key, ObjectReferenceImpl mirror,
                           ReferenceQueue queue) {
           super(mirror, queue);
           this.count = 1;
           this.key = key;
       }

       int count() {
           return count;
       }

       void incrementCount() {
           count++;
       }

       Object key() {
           return key;
       }

       ObjectReferenceImpl object() {
           return (ObjectReferenceImpl)get();
       }
   }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java VirtualMachineImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.