FileDocCategorySizeDatePackage
KVMListener.javaAPI DocJ2ME CLDC 1.111593Wed Feb 05 15:56:04 GMT 2003kdp

KVMListener

public class KVMListener extends ProxyListener implements VMConstants

Fields Summary
SocketConnection
connKvm
ProxyListener
debuggerListener
ClassManager
manager
Options
options
boolean
Ready
boolean
useClassParser
Socket
remoteSocket
Constructors Summary
public KVMListener(Options options)


       
    super();
    this.options = options;
    useClassParser = options.getUseClassParser();
    
Methods Summary
private voidhandleSteppingInfo(PacketStream in)

    ClassFile cf;
    MethodInfo mi;
    int index, index2, currentIndex;
        long offs, offs2, offs3;

    int cep = in.readInt();    // opaque buffer pointer we just pass back
        int cid = in.readInt();
        int mid = in.readInt() - method_index_base;
        long offset = in.readLong();

        Log.LOGN(3, "handleSteppingInfo: cep = " + Integer.toHexString(cep) +
            " cid = " + Integer.toHexString(cid) + " mid = " +
            Integer.toHexString(mid));
    PacketStream ps = new PacketStream(this, KVM_CMDSET,
        KVM_GET_STEPPINGINFO_CMD);

    ps.writeInt(cep);
    cf = (ClassFile)ClassManager.classMap.get(new Integer(cid));
    if (cf == null || (mi = cf.getMethodInfoByIndex(mid)) == null) {
        ps.writeLong(0);
        ps.writeLong(0);
                ps.send();
            try {
            ps.waitForReply();
            } catch ( Exception e ) {}
        return;
    }

    LineNumberTableAttribute table = null;
    CodeAttribute ca = mi.getCodeAttribute();
    if (ca != null)
            table = ca.getLineNumberTable();

/*
        int line = table.getLineThatContainsOpcode( offset );
        System.out.println( "handle..." + table.getLineThatContainsOpcode( 271 ) );
*/

        //line = table.getNextExecutableLineIndex( line );
        if (ca == null || table == null) {
            offs = offs2 = offs3 = -1;
            index = index2 = currentIndex = -1;
        } else {
        // where are we now.
        currentIndex = table.getCurrentLineCodeIndex(offset);
        // what is the index of the next line we should execute
            index = table.getNextExecutableLineCodeIndex( offset );
        // does the current offset have a duplicate line?
            index2 = table.getDupCurrentExecutableLineCodeIndex(offset);
        // offset of current line
            offs = table.getStartPCFromIndex(index);
        // offset of possible duplicate of current line
            offs2 = table.getStartPCFromIndex(index2);
        // offset of next line after duplicate
        offs3 = table.getOffsetofDupNextLine(index2);
        }
        Log.LOGN(3, "handleSteppingInfo  current offset = " + offset );
        Log.LOGN(3, "handleSteppingInfo  target offset = " + offs );
        Log.LOGN(3, "handleSteppingInfo  dup current line offset = " + offs2 );
        Log.LOGN(3, "handleSteppingInfo  offset after current dup = " + offs3 );
    if (table != null)
        Log.LOGN(3, "handleSteppingInfo current line number = " + table.getLineNumberFromIndex(currentIndex));
/*
        long offs = table.getCodeIndexBySourceLineNumber( line );
*/

        ps.writeLong( offs );
        ps.writeLong( offs2 );
        ps.writeLong( offs3 );
        ps.send();
   
        try {
        ps.waitForReply();
        } catch ( Exception e ) {}
    
public voidquit()

    boolean oldtimeToQuit = timeToQuit;
    timeToQuit = true;
    if (oldtimeToQuit != timeToQuit) {
        try {
        if (remoteSocket != null) {
//            remoteSocket.shutdownInput();
//            remoteSocket.shutdownOutput();
                remoteSocket.close();
        }
        } catch (IOException e) {}
        debuggerListener.quit();
    }
    
public voidrun()


        boolean handled;
    PacketStream ps;
    byte typeTag;
    int classID;
    String className;
    int classStatus;
    ClassFile cf;

        try {
            /* Attempt to reconnect to KVM by polling every 2000ms until 
             * connection is established.
             */
            while (remoteSocket == null) {
                try { 
                remoteSocket = new Socket(options.getRemoteHost(), 
                                              options.getRemotePort());
                } catch (ConnectException e) {
                    System.err.println("KVM not ready");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException ie) {}
                }
             }
             connKvm = new SocketConnection(this, remoteSocket);
         } catch (IOException e) {
             System.out.println("KVMListener: " + e.getMessage());
         } catch (SecurityException e) {
             System.out.println("KVMListener: " + e.getMessage());
         }

    synchronized(this) {
        Ready = true;
        this.notify();
    }
    if (!useClassParser) {
        byte [] handshake = new String("JDWP-Handshake").getBytes();
        try {
            // debugger -> vm
            for ( int i=0; i < handshake.length; i++ )
                connKvm.sendByte(handshake[i]);

            // debugger <- vm
            for ( int i=0; i < handshake.length; i++ )
                connKvm.receiveByte();
        } catch (IOException e) {
        }
    }

    new Thread(connKvm).start();

    if (useClassParser) {

        ps = new PacketStream(this, KVM_CMDSET, KVM_HANDSHAKE_CMD);
        ps.writeString("KVM Reference Debugger Agent");
        ps.writeByte((byte)MAJOR_VERSION);    // Major version
        ps.writeByte((byte)MINOR_VERSION);    // minor version
        ps.send();
        try {
            ps.waitForReply();
        } catch (Exception e) {
            System.out.println("Exception during handshake: " + e +
                " exiting...");
            Runtime.getRuntime().exit(1);
        }
        String s = ps.readString();
        int option_bits = ps.readInt();
        Log.LOGN(1, "KVM Handshake return string: " + s);
        Log.LOGN(1, "KVM Handshake return options: " + option_bits);

            if (((option_bits & METHOD_BASE_BITS) >> METHOD_BASE_SHIFT) == METHOD_BASE_ONE_FLAG) {
                Log.LOGN(1, "Method index base being set to 1");
                method_index_base = 1;
            }
        ps = new PacketStream(this, VIRTUALMACHINE_CMDSET,
        ALL_CLASSES_CMD);
        ps.send();
        try {
        ps.waitForReply();
        } catch (Exception e) {
        System.out.println("Couldn't get list of classes from KVM");
        }
        int numClasses = ps.readInt();
        Log.LOGN(2, numClasses + " classes");
        for (int i = 0; i < numClasses; i++) {
                typeTag = ps.readByte();
                classID = ps.readInt();
                className = ps.readString();
        if (typeTag != TYPE_TAG_ARRAY) {
                    // strip off leading 'L' and trailing ';'
                    className = new String(className.substring(1,
            className.length() - 1));
        }
                classStatus = ps.readInt();
            if ((cf = (ClassFile)ClassManager.classMap.get(new
                Integer(classID))) == null) {
                Log.LOGN(3, "allclasses: new class: " +
                    className + " " + Integer.toHexString(classID));
                cf = manager.findClass(typeTag, className);
                if (cf != null) {
            cf.setClassID(classID);
            cf.setClassStatus(classStatus);
                ClassManager.classMap.put(new
                      Integer(classID), cf);
                } else {
                    Log.LOGN(3, "allclasses: couldn't find class "
                        + className);
                }
                }
            }
    }
        try {
            while (!timeToQuit) {
        PacketStream in;
     
                handled = false;
        Packet p = waitForPacket();
        if (p == null){
            break;        // must be time to quit
        }
        if (useClassParser && (p.flags & Packet.Reply) == 0) {
        switch (p.cmdSet) {
        case EVENT_CMDSET:
            switch (p.cmd) {
            case COMPOSITE_CMD:
            in = new PacketStream(this, p);
                byte suspendPolicy = in.readByte();
                int numEvents = in.readInt();
                // we KNOW that KVM only sends one event
                byte eventKind = in.readByte();
                if (eventKind != JDWP_EventKind_CLASS_PREPARE)
                    break;
                int requestID = in.readInt();
                int threadID = in.readInt();
                typeTag = in.readByte();
                classID = in.readInt();
                className = in.readString();
            classStatus = in.readInt();
            if (typeTag != TYPE_TAG_ARRAY) {
                // strip off leading 'L' and trailing ';'
                className =
                        new String(className.substring(1,
                        className.length() - 1));
            }
                Log.LOGN(3, "ClassPrepare:  " + className + ", ID = "
                + Integer.toHexString(classID));
                // see if we have a class parser reference
                if ((cf = (ClassFile)ClassManager.classMap.get(new Integer(classID))) == null) {
                    cf = manager.findClass(typeTag, className);
                    if (cf != null) {
                    ClassManager.classMap.put(new Integer(classID),
                    cf);
                    cf.setClassID(classID);
                cf.setClassStatus(classStatus);
                } else {
                Log.LOGN(3, "ClassPrepare: null cf!");
                }
                } else {
                Log.LOGN(3, "ClassPrepare: got classfile " + cf.getClassName());
                cf.setClassStatus(classStatus);
            }
                break;
            }
            break;
        case KVM_CMDSET:
                    switch (p.cmd) {
                    case KVM_STEPPING_EVENT_CMD: /* need stepping info */
            in = new PacketStream(this, p);
                        handleSteppingInfo(in);
                        handled = true;
                        break;
            }
            break;
                }
        }

                if ( !handled ) {
                    Log.LOG(3, "KVMListener:: ");
                    disp(p);
            if (p.cmdSet == 64 && p.cmd == 100)
            Log.LOGN(3, "Eventkind = " + p.data[5]);
                    debuggerListener.send(p);
                }
            }
        } catch (IOException e) {
        }
    
public synchronized voidsend(Packet p)

        synchronized(this) {
            while (!Ready) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                }
            }
        }
        String id = String.valueOf(p.id);
        synchronized(waitingQueue) {
            if ((p.flags & Packet.Reply) == 0 && p.id < 0)
                waitingQueue.put(id, p);
            }
        connKvm.send(p);
    
public voidset(ProxyListener debuggerListener, ClassManager manager)

        this.debuggerListener = debuggerListener;
        this.manager = manager;
    
public java.lang.StringtoString()

    return (new String("KVMListener: "));