📄 kvmlistener.java
字号:
/* * Copyright (c) 2000 Sun Microsystems, Inc., 901 San Antonio Road, * Palo Alto, CA 94303, U.S.A. All Rights Reserved. * * Sun Microsystems, Inc. has intellectual property rights relating * to the technology embodied in this software. In particular, and * without limitation, these intellectual property rights may include * one or more U.S. patents, foreign patents, or pending * applications. Sun, Sun Microsystems, the Sun logo, Java, KJava, * and all Sun-based and Java-based marks are trademarks or * registered trademarks of Sun Microsystems, Inc. in the United * States and other countries. * * This software is distributed under licenses restricting its use, * copying, distribution, and decompilation. No part of this * software may be reproduced in any form by any means without prior * written authorization of Sun and its licensors, if any. * * FEDERAL ACQUISITIONS: Commercial Software -- Government Users * Subject to Standard License Terms and Conditions */package kdp;import kdp.classparser.*;import kdp.classparser.attributes.*;import java.io.*;import java.net.*;class KVMListener extends ProxyListener implements VMConstants { SocketConnection connKvm; ProxyListener debuggerListener=null; ClassManager manager; Options options; boolean Ready = false; boolean useClassParser = false; Socket remoteSocket = null; public KVMListener(Options options) { super(); this.options = options; useClassParser = options.getUseClassParser(); } public void set( ProxyListener debuggerListener, ClassManager manager ) { this.debuggerListener = debuggerListener; this.manager = manager; } /* * Sends packet to our output socket */ public synchronized void send(Packet p) throws IOException{ 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 void quit() { boolean oldtimeToQuit = timeToQuit; timeToQuit = true; if (oldtimeToQuit != timeToQuit) { try { if (remoteSocket != null) {// remoteSocket.shutdownInput();// remoteSocket.shutdownOutput(); remoteSocket.close(); } } catch (IOException e) {} debuggerListener.quit(); } } public void run() { 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("VM 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, "VM Handshake return string: " + s); Log.LOGN(1, "VM 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 VM"); } 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(); while (numEvents-- > 0) { 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) { } } private void handleSteppingInfo(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 String toString() { return (new String("KVMListener: ")); }} // KVMListener
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -