FileDocCategorySizeDatePackage
SocketTransportImpl.javaAPI DocphoneME MR2 API (J2ME)14061Wed May 02 17:59:48 BST 2007com.sun.cldchi.tools.memoryprofiler.jdwp

SocketTransportImpl

public class SocketTransportImpl extends Thread
This class implements JDWP socket connection and works in the background thread.
see
jdwp.SocketTransport
version

Fields Summary
private static Object
sync
A synchronisation object. It's used for synchronising access to finished field.
private static Object
sync1
A synchronication object. Using this object a reading loop waits for invoking receive() method.
private static Object
sync2
A synchronisation object. It's used for synchronising access to the buffer that contains data that already read and to the cycleStarted field.
private String
serverName
A host name where VM being debugged is running.
private int
portNumber
A TCP/IP port number that is used for connecting to VM being debugged.
private boolean
finished
Indicates that it's time to finish this thread. May be initiated inside and outside the thread.
private DataInputStream
inputStream
A stream that reads data from the socket.
private DataOutputStream
outputStream
A stream that writes data to the socket.
private Socket
socket
A socket that provides JDWP connection.
private Vector
replies
A reference to the outer object ahere is to put an information about received JDWP replies.
private Vector
repliesInternal
An internal structure for temporary keeping of received JDWP replies. Later this data is copied to replies vector.
private int
expectedSize
If this field is set to -1 a normal JDWP packet is expected. Otherwise it indicates that handshake is expected and is value equals to expected size of handshake string.
private int
currentInPrivateBuffer
A current position in the buffer that contains received handshake string.
private int
handShakeSize
An expected size of received handshake string.
private byte[]
privateBuffer
A buffer that contains a received handshake string.
private boolean
cycleStarted
Indicates that the reading thread doesn't sleep but processes reading of data. Used by handshake procedure to wait until receiving handshake string.
Constructors Summary
public SocketTransportImpl()
Creates a new SocketTransportImpl object.


              
      
        super();
    
Methods Summary
public voidattachToServer()
Establishes TCP/IP connection to the VM being debugged.

NOTE: It's one of few methods in KJDB that produces non-debug output directly. It's not good. For non-debug output classes must use kdb.Log class. So may be it's a good idea to remove the message this method prints.

        socket = new Socket(serverName, portNumber);
        Tools.wait(100);
        System.out.println("Socket Created.");
        socket.setTcpNoDelay(true);
        inputStream = new DataInputStream(socket.getInputStream());
        outputStream = new DataOutputStream(socket.getOutputStream());
    
public intavailableInPrivateBuffer()
Returns the number of bytes that are available in the buffer that that contains received handshake string.

return
the number of bytes that are available in the buffer that that contains received handshake string

        synchronized(sync){
            if(finished){
                throw new SocketException("Connection closed");
            }
        }
        //System.out.println("available");
        synchronized(sync2){
            if(expectedSize == -1){
                return handShakeSize;
            }else{
                return 0;
            }
        }
    
public voiddone()
This method sets the finished field that indicates that the background thread is to be finished. After this it closes JDWP connection.

        synchronized(sync){
            finished = true;
        }
        doneInternal();
    
private synchronized voiddoneInternal()
Internal method that terminates JDWP connection in fact.

        try{
            if(socket == null){
                return;
            }
            socket.close();
        }catch(IOException e){
        }
    
public voidinitAsClient(java.lang.String serverName, int portNumber, java.util.Vector replies)
Intializes some internal fields of the object. Need to be invoked immediately after constructor.

param
serverName a hostname where VM being debugged is running
param
portNumber a TCP/IP port number that should be used for connecting with VM being debugged
param
replies a vector where it's necessary to put received JDWP replies

        this.serverName = serverName;
        this.portNumber = portNumber;
        this.replies = replies;
    
public booleanisStarted()
Checks if the background thread is initialized and is not received request for terminating yet.

return
true if the background thread is initialized and is not received request for terminating yet, false otherwise

        synchronized(sync){
            return !finished;
        }
    
public intreadNextFromPrivateBuffer()
Reads next byte from the buffer that contains received handshake string.

return
next byte from the buffer that contains received handshake string

        synchronized(sync){
            if(finished){
                throw new SocketException("Connection closed");
            }
        }
        //System.out.println("read");
        synchronized(sync2){
            return privateBuffer[currentInPrivateBuffer++];
        }
    
public voidreceive()
Stores a portion of received replies in the outer buffer. If no replies are received since the previous call of this method it does nothing.

see
#replies
see
#repliesInternal
see
jdwp.Transport#Replies

        //System.out.println("receive");
        synchronized(sync){
            if(finished){
                throw new SocketException("Connection closed");
            }
        }
        synchronized(sync1){
            sync1.notifyAll();
        }
        synchronized(repliesInternal){
            replies.addAll(repliesInternal);
            repliesInternal.clear();
        }
    
public voidrun()
It's an entry point of background thread. This method processes reading of handshake and normal JDWP packets and stores the received values in repliesInternal vector. Also this method establishes JDWP connection. The method works in a loop until finished field becomes true. After this the JDWP connections terminates.

        //setPriority(MIN_PRIORITY);
        synchronized(sync){
            finished = false;
        }
        byte[] buf = new byte[100000];
        try{
            attachToServer();
            boolean timeToQuit = false;
            synchronized(sync){
                timeToQuit = finished;
            }
            synchronized(this){
                notifyAll();
            }
            while(!timeToQuit){
                synchronized(sync1){
                    sync1.wait();
                }
                synchronized(sync2){
                    cycleStarted = true;
                }
                
                if(expectedSize != -1){
                    //read handshake
                    int bytesRead = 0;
                    while(bytesRead != expectedSize){
                        bytesRead += inputStream.read(buf, bytesRead, expectedSize - bytesRead);
                    }
                    synchronized(sync2){
                        for(int i=0 ; i<expectedSize ; i++){
                            privateBuffer[i] = buf[i];
                        }
                        expectedSize = -1;
                    }
                    continue;
                }
                
                //System.out.println("read packet");
                
                //Read header
                int bytesRead = 0;
                while(bytesRead != Packet.PacketHeaderSize){
                    int bytesReadDuringLastRead = inputStream.read(buf,                    
                    bytesRead, Packet.PacketHeaderSize - bytesRead);
                    bytesRead += bytesReadDuringLastRead;
                    if(bytesReadDuringLastRead  == -1){
                        throw new IOException("Connection closed");
                    }
                }
                
                //System.out.println("read data");
                
                //Read data
                int size = (((((int)buf[0]) & 0xFF) << 24) |
                ((((int)buf[1]) & 0xFF ) << 16) |
                ((((int)buf[2]) & 0xFF ) << 8) |
                (((int)buf[3]) & 0xFF));
                bytesRead = 0;
                while(bytesRead != size - Packet.PacketHeaderSize){
                    int bytesReadDuringLastRead =
                    inputStream.read(buf, bytesRead + Packet.PacketHeaderSize, 
                    size - Packet.PacketHeaderSize - bytesRead);
                    bytesRead += bytesReadDuringLastRead;
                    if(bytesReadDuringLastRead  == -1){
                        throw new IOException("Connection closed");
                    }
                }
                
                //System.out.println("data read");
                
                Reply r = new Reply();
                r.resetBuffer();
                r.addBytes(buf,0,size);
                synchronized(repliesInternal){
                    repliesInternal.add(r);
                }
                
                synchronized(sync){
                    timeToQuit = finished;
                }
            }
        }catch(IOException e){
            synchronized(sync){
                finished = true;
            }
            synchronized(this){
                notifyAll();
            }
        }catch(InterruptedException e){
            synchronized(sync){
                finished = true;
            }
            synchronized(this){
                notifyAll();
            }
        }
        synchronized(sync){
            finished = true;
        }
        doneInternal();
    
public voidstartHandShake(int len)
Initiates handshake procedure that is physically performed by run() method and waits for run() method's sterting the waiting for reply. After this it exits. This procedure is performed immediately after establishing TCP/IP connection and consist on sending and receiving "JDWP-Handshake" string.

param
an expected length of received handshake string

        currentInPrivateBuffer = 0;
        expectedSize = len;
        handShakeSize = len;
        boolean b = true;
        do{
            synchronized(sync1){
                sync1.notifyAll();
            }
            synchronized(sync2){
                b = !cycleStarted;
            }
        }while(b);
        synchronized(sync2){
            cycleStarted = false;
        }
    
public voidwrite(int b)
Writes a specified byte into the socket.

param
b a byte to be written

        outputStream.write(b);
        //System.out.println("Written byte " + b);