JdiDemo

Wesley13
• 阅读 657

HelloWorld.java

package com.my.jdi;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        int i = 0;
        while(true) {
            System.out.println(++i);
            Thread.sleep(5000);
        }
    }
}

SimpleDebugger.java

package com.my.jdi;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Location;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.StackFrame;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.VirtualMachineManager;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.connect.VMStartException;
import com.sun.jdi.event.BreakpointEvent;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventIterator;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.VMDeathEvent;
import com.sun.jdi.event.VMDisconnectEvent;
import com.sun.jdi.event.VMStartEvent;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;

/**
 * For javadoc of JDI, please see:
 * @see http://docs.oracle.com/javase/8/docs/jdk/api/jpda/jdi/index.html
 * @see https://www.ibm.com/developerworks/cn/java/j-lo-jpda4/index.html
 */
public class SimpleDebugger {
    private static final int BREAK_POINT_LINE = 6;
    private static final String DEBUG_CLASS = "com.my.jdi.HelloWorld";
    private static EventRequestManager eventRequestManager = null;
    private static EventSet eventSet = null;
    private static boolean vmExit = false;
    
    public static void main(String[] args) throws Exception {
        VirtualMachine targetVM = launchVM();
        
        // Get process which run target VM
        Process process = targetVM.process();
        
        registerVMEvent(targetVM);
        //classPrepareRequest.setEnabled(true);
        
        // Enter event loop 
        eventLoop(targetVM);
     
        process.destroy();
    }

    /**
     * Register ClassPrepareRequest
     */
    private static void registerVMEvent(VirtualMachine targetVM) {
        eventRequestManager = targetVM.eventRequestManager();
        ClassPrepareRequest classPrepareRequest = eventRequestManager.createClassPrepareRequest();
        classPrepareRequest.addClassFilter(DEBUG_CLASS);
        classPrepareRequest.addCountFilter(1);
        classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
        // Event created by eventRequestManager is non-active, need to call enable method
        classPrepareRequest.enable();
    }

    private static void eventLoop(VirtualMachine targetVM) throws Exception {
        // EventQueue manages event from debugger for target VM
        EventQueue eventQueue = targetVM.eventQueue();
        while (!vmExit) {
            // Waits until the next available event comes.
            eventSet = eventQueue.remove();
            EventIterator eventIterator = eventSet.eventIterator();
            while (eventIterator.hasNext()) {
                Event event = (Event) eventIterator.next();
                execute(event);
            }
        }
    }
    
    private static void execute(Event event) throws Exception {
        if (event instanceof VMDisconnectEvent) {
            System.out.println("VM disconnect");
            vmExit = true;
        } else {
            if (event instanceof VMStartEvent) {
                System.out.println("VM started");
            } else if (event instanceof VMDeathEvent) {
                System.out.println("VM death");
            } else if (event instanceof ClassPrepareEvent) {
                ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) event;
                String className = classPrepareEvent.referenceType().name();
                if (DEBUG_CLASS.equals(className)) {
                    System.out.println("Class " + DEBUG_CLASS + " is already prepared");
                }
                if (true) {
                    // Get location
                    ReferenceType referenceType = classPrepareEvent.referenceType();
                    List<Location> locations = referenceType.locationsOfLine(BREAK_POINT_LINE);
                    Location location = locations.get(0);
         
                    // Create BreakpointEvent
                    BreakpointRequest breakpointRequest = eventRequestManager.createBreakpointRequest(location);
                    breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
                    breakpointRequest.enable();
                }
            } else if (event instanceof BreakpointEvent) {
                System.out.println("Reach line 10 of " + DEBUG_CLASS);
                BreakpointEvent breakpointEvent = (BreakpointEvent) event;
                ThreadReference threadReference = breakpointEvent.thread();
                StackFrame stackFrame = threadReference.frame(0);
                LocalVariable localVariable = stackFrame.visibleVariableByName("str");
                Value value = stackFrame.getValue(localVariable);
                
                String str = ((StringReference) value).value();
                System.out.println("The local variable str at line 10 is " + str + " of " + value.type().name());
            } 
            // Unless resume is being handled in another way, each EventSet should invoke EventSet.resume().
            eventSet.resume();
        }
    }
    
    /**
     * Launch the target VM.
     */
    private static VirtualMachine launchVM() {
        VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();
        // Get all launch connectors
        List<LaunchingConnector> list = vmManager.launchingConnectors();
        for (LaunchingConnector conn: list) {
            System.out.println("LaunchingConnector: " + conn.name());
        }
        
        // Get arguments of the default launching connector
        LaunchingConnector launchingConnector = vmManager.defaultConnector();
        Map<String, Connector.Argument> env = launchingConnector.defaultArguments();
        env.get("main").setValue(DEBUG_CLASS);// Set class of main method
        env.get("suspend").setValue("true");
        
        Set<String> keySet = env.keySet();
        for (String key: keySet) {
            System.out.println("Argument: " + env.get(key));
        }
        
        // Launch target VM
        try {
            VirtualMachine vm = launchingConnector.launch(env);
            if (vm == null) {
                System.out.println("Launch failed, vm is null");
                throw new Error("Launch VM failed!");
            } else {
                System.out.println("Launch success!");
                return vm;
            }
        } catch (IOException exc) {
            throw new Error("Unable to launch target VM: " + exc);
        } catch (IllegalConnectorArgumentsException exc) {
            throw new Error("Illegal connector argument to launch target VM: " + exc);
        } catch (VMStartException exc) {
            throw new Error("Target VM failed to initialize: " + exc.getMessage());
        }
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java中的public void是什么意思
最基本的语法:publicclassHelloWorld{publicstaticvoidmain(Stringargs){System.out.println("HelloWorld");}}java里public是类的访问修饰符,void是表示
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java第一句的单词理解
publicclassHelloWorld{publicstaticvoidmain(Stringargs){System.out.println("人生中的第一个代码");}}package包的关键字类文件的首行位置com.zhiyou100包名;结
梦
3年前
若依框架“记住我”历史bug
官网已提出,最新版应该没有了,当前框架还是低版本,所以记录记住我bug解决办法publicstaticvoidmain(Stringargs)throwsException{KeyGeneratorkeygenKeyGenerator.getInstance("AES");SecretKey
Wesley13 Wesley13
3年前
java反射详解 (二)
【案例】通过反射操作属性classhello{publicstaticvoidmain(Stringargs)throwsException{Class<?demonull;Objectobjnull;
Wesley13 Wesley13
3年前
java指令重排序代码演示
Jdk版本:jdk1.8.0\_151代码publicclassSimpleHappenBefore{publicstaticvoidmain(Stringargs)throwsInterruptedException{for(inti0;i<5
Wesley13 Wesley13
3年前
Java中i++和++i的区别
publicstaticvoidmain(Stringargs){inti0;for(intj0;j<100;j){ii;}System.out.println(i);}输出结果是0,
Wesley13 Wesley13
3年前
Java访问MongoDB例子
publicstaticvoidmain(Stringargs)throwsException{MongomnewMongo("10.18.96.160",27017);System.out.println(m.getDatabaseNames());
Wesley13 Wesley13
3年前
Java知识系统回顾整理01基础05控制流程03 while
while和dowhile循环语句一、while:条件为true时重复执行只要while中的表达式成立,就会不断地循环执行!(https://oscimg.oschina.net/oscnet/f7f8d003013b0b12222c5a5cbd78fe0ca96.png)publicclassHelloWorld{