ã¯ããã«
Eclipseã®ãããã¬ãŒãä»ããŠJVMã§å®è¡ãããŠããã¢ããªã±ãŒã·ã§ã³ããããã°ãããšããã¹ããªãŒã ã倿°å€ãªã©ãã¢ããªã±ãŒã·ã§ã³ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããã¢ã¯ã»ã¹éã«åžžã«æéãåããŸããã åæã«ãæã
ãç¹å®ã®ã¢ã¯ã·ã§ã³ããã¹ã¯ãªããåãããããããããããå¶åŸ¡ããããšããèŠæããããŸããã
ããšãã°ããµã€ã¯ã«ã§å€åãã倿°ã®ç¶æ
ããç£èŠãããããã«ãæ¡ä»¶ä»ããã¬ãŒã¯ãã€ã³ãã䜿çšããŸããããã®æ¡ä»¶ã¯ãSystem.out.printlnïŒtheVariableïŒãã®ãããªã³ãŒãã§ããã falseãè¿ããŸãã ãã®ããã¯ã«ãããã¢ããªã±ãŒã·ã§ã³ãã»ãšãã©äžæããããšãªãã倿°å€ã®ãã°ãååŸããããšãå¯èœã«ãªããŸããïŒãã¡ãããæ¡ä»¶ã³ãŒãã®å®è¡äžã¯äžæãããŸãããããã以äžã¯äžæãããŸããã§ããïŒã ããã«ãå€ãã®å Žåã衚瀺ãã¥ãŒã§ããŒã¿ã衚瀺ãããšãã«ãå
¥åããã衚瀺ã®ã³ãŒãè©äŸ¡ã®çµæããã®çŽåŸã«è¿œå ãããã®ã¯é¢åã§ããã
äžè¬ã«ãããšãã°ãååãšããŠãœãããŠã§ã¢ãããã°ã«äŒŒãŠããBean ShellãŸãã¯Groovy Shellãä»ããŠãåãããšãå®è¡ã§ããããã«ãããã£ãã®ã§ãã è«ççã«ã¯ãããã¯é£ããããšã§ã¯ãªãã¯ãã§ã-çµå±ã®ãšãããEclipseèªäœãäœããã®åœ¢ã§ãããè¡ãã®ã§ãããïŒ
å³é¢ãäœæããåŸãããã°ã©ã ã§JVMãããã°æ
å ±ã«ã¢ã¯ã»ã¹ããããšãã§ããæ¥ãã§äŸãå
±æããŸããã
JPDAãšJDIã«ã€ããŠ
JVMã®ãããã°ã®ããã«ã
JPDA -Java Platform Debugger Architectureãšããå
æ¬çãªçšèªã®äžã«ãŸãšããããç¹å¥ãªæšæºãèæ¡ãããŸããã ãããã«ã¯ã
JVMTIïŒ sysh颿°ãåŒã³åºããŠJVMã§ã¢ããªã±ãŒã·ã§ã³ããããã°ããããã®ãã€ãã£ãã€ã³ã¿ãŒãã§ã€ã¹ïŒã
JDWP-ãããã¬ãŒãšJVMéã®ããŒã¿è»¢éãããã³ã«ïŒã¢ããªã±ãŒã·ã§ã³ããããã°ããããªã©ïŒãå«ãŸããŸãã
ããã¯ãã¹ãŠãããŸãé¢é£æ§ããããŸããã§ããã ããããããã«å ããŠãç¹å®ã®
JDIã
JPDA -Java Debug Interfaceã«å«ãŸããŠããŸãã ããã¯ãJVMã¢ããªã±ãŒã·ã§ã³ããããã°ããããã®Java APIã§ããå»åž«ã泚æãããã®ã§ãã
JPDAã®å
¬åŒããŒãžã§ã¯ ãSun / Oracleããã®åç
§JDIå®è£
ã®ååšã確èªããŠããŸãã ã ãããããã䜿ãå§ããã ãã§ãã
äŸ
æŠå¿µå®èšŒãšããŠã2ã€ã®Groovyã·ã§ã«ãå®è¡ããããšã«ããŸããã1ã€ã¯ãå®éšçããªãããã°ã¢ãŒãã§ããã1ã€ã¯ãããã¬ãŒãšããŠå®è¡ããŸãã æåå倿°ã¯å®éšã·ã§ã«ã§èšå®ããããã®å€ã¯ããããã¬ãã·ã§ã«ããååŸããå¿
èŠããããŸããã
被éšè
ã¯æ¬¡ã®ãã©ã¡ãŒã¿ãŒã§éå§ãããŸããã
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7896
ã€ãŸã JVMã¯TCP / IPãä»ããŠãªã¢ãŒããããã°ã¢ãŒãã§èµ·åãããããŒã7896ã§ãããã¬ããã®æ¥ç¶ãåŸ
æ©ããŠããŸããã
次ã®ã³ãã³ããå®éšçãªGroovyã·ã§ã«ã§å®è¡ãããŸããã
myVar = âSome special valueâ;
ãããã£ãŠãå€ãSome special valueãã¯ãããã¬ãŒã§ååŸãããŠããã¯ãã§ãã
ãªããªã ããã¯ããªããžã§ã¯ãã®ãã£ãŒã«ãã®å€ã ãã§ã¯ãããŸããããããååŸããã«ã¯ãGroovy Shellã®å
éšãå°ãç¥ã£ãŠããªããã°ãªããŸããã§ããïŒãŸãã¯ãå°ãªããšããœãŒã¹ãã®ããèŠããªããã°ãªããŸããïŒããã¿ã¹ã¯ã¯ãã£ãšé¢çœããŠçŸå®çã ã£ãããã§ã
ããããããã¯ããããã¬ã次第ã§ããïŒ
ãã¹ãŠã段éçã«èããŠã¿ãŸãããã
JVMæ¥ç¶
JDIã䜿çšããŠããããã°ããããšã«ããJVMã«æ¥ç¶ããŸãïŒåããã·ã³ã§ãã¹ãŠãå®è¡ããããããã¹ã== localhostã§ããããªã¢ãŒããã·ã³ã§ãåãããã«åäœããŸããããŒãã¯ãå®éšçãJVMã®ãããã°ãã©ã¡ãŒã¿ãŒã§èšå®ãããã®ãšåãã§ãïŒã
JDIã䜿çšãããšããœã±ãããä»ããŠããŸãã¯ããŒã«ã«ããã»ã¹ã«çŽæ¥JVMã«åå ã§ããŸãã ãããã£ãŠãVirtualMachineManagerã¯è€æ°ã®AttachingConnectorãè¿ããŸãã ãã©ã³ã¹ããŒãã®ååïŒ "dt_socket"ïŒã§ç®çã®ã³ãã¯ã¿ãéžæããŸã
vmm = com.sun.jdi.Bootstrap.virtualMachineManager(); vmm.attachingConnectors().each{ if("dt_socket".equalsIgnoreCase(it.transport().name())) { atconn = it; } } args = atconn.defaultArguments(); args.get("port").setValue(7896); args.get("hostname").setValue("127.0.0.1"); vm = atconn.attach(args);
ã¡ã€ã³ã®ã¹ããªãŒã ãã¬ãŒã¹ã®ååŸ
çµæãšããŠåŸããããªã¢ãŒãJVMãžã®ã€ã³ã¿ãŒãã§ãŒã¹ã«ãããå®è¡äžã®ã¹ã¬ããã確èªããããäžæåæ¢ãããã§ããŸãã ãã ãããªã¢ãŒãJVMã§ã¡ãœããåŒã³åºããè¡ãã«ã¯ããã¬ãŒã¯ãã€ã³ãã«ãã£ãŠæ£ç¢ºã«åæ¢ãããã¹ã¬ãããå¿
èŠã§ãã
JDI javadocã®æ¬¡ã®
段èœãå®éã«èšã£ãŠããããšïŒ
ãã¡ãœããåŒã³åºãã¯ãæå®ãããã¹ã¬ããããã®ã¹ã¬ããã§çºçããã€ãã³ãã«ãã£ãŠäžæãããå Žåã«ã®ã¿çºçããŸãã ã¿ãŒã²ããVMãVirtualMachine.suspendïŒïŒã«ãã£ãŠäžæãããŠããå ŽåããŸãã¯æå®ãããã¹ã¬ãããThreadReference.suspendïŒïŒã«ãã£ãŠäžæãããŠããå Žåãã¡ãœããåŒã³åºãã¯ãµããŒããããŸããã
ãã¬ãŒã¯ãã€ã³ããèšå®ããããã«ãç§ã¯ããã¶ãç¹å®ã®æ¹æ³ã§è¡ã£ã-groovyã·ã§ã«ã調ã¹ãã®ã§ã¯ãªããçŸåšJVMã§äœãèµ·ãã£ãŠããã®ããèŠãŠãèµ·ããŠããããšã§ãã¬ãŒã¯ãã€ã³ããèšå®ããŸãã
å®éšçãªJVMã®ã¹ã¬ããã§ã¡ã€ã³ã¹ããªãŒã ãæ€åºããããã®éå§ãã©ãã¯ã調ã¹ãŸããã ã¹ããªãŒã ã¯ä»¥åã«åæ¢ãããŠãããããåŸç¶ã®æäœäžã«ããŒãã¬ãŒã¹ãé¢é£ãããŸãŸã«ãªããŸãã
// Find thread by name "main" vm.allThreads().each{ if(it.name().equals("main")) mainThread = it } // Suspend it mainThread.suspend() // Look what's in it's stack trace i=0; mainThread.frames().each{ println String.valueOf(i++)+": "+it; }; println "";
ãã®çµæãç§ã¯ãããåŸãŸããïŒ
0: java.io.FileInputStream.readBytes(byte[], int, int)+-1 in thread instance of java.lang.Thread(name='main', id=1) 1: java.io.FileInputStream:220 in thread instance of java.lang.Thread(name='main', id=1) 2: java.io.BufferedInputStream:218 in thread instance of java.lang.Thread(name='main', id=1) 3: java.io.BufferedInputStream:237 in thread instance of java.lang.Thread(name='main', id=1) 4: jline.Terminal:99 in thread instance of java.lang.Thread(name='main', id=1) 5: jline.UnixTerminal:128 in thread instance of java.lang.Thread(name='main', id=1) 6: jline.ConsoleReader:1453 in thread instance of java.lang.Thread(name='main', id=1) 7: jline.ConsoleReader:654 in thread instance of java.lang.Thread(name='main', id=1) 8: jline.ConsoleReader:494 in thread instance of java.lang.Thread(name='main', id=1) 9: jline.ConsoleReader:448 in thread instance of java.lang.Thread(name='main', id=1) 10: jline.ConsoleReader$readLine.call(java.lang.Object, java.lang.Object)+17 in thread instance of java.lang.Thread(name='main', id=1) 11: org.codehaus.groovy.tools.shell.InteractiveShellRunner:89 in thread instance of java.lang.Thread(name='main', id=1) 12: org.codehaus.groovy.tools.shell.ShellRunner:75 in thread instance of java.lang.Thread(name='main', id=1) 13: org.codehaus.groovy.tools.shell.InteractiveShellRunner.super$2$work()+1 in thread instance of java.lang.Thread(name='main', id=1) .... .., 65
ãã¬ãŒã¯ãã€ã³ããèšå®ãã
ãããã£ãŠãã¡ã€ã³ã¹ããªãŒã ã®ã¹ãããã¬ãŒã¹ã¹ããªãŒã ããããŸãã JDI APIã¯ãã¹ããªãŒã ã®ããããStackFrameãè¿ããããããLocationãååŸã§ããŸãã å®éããã®å Žæã¯ãã¬ãŒã¯ãã€ã³ããèšå®ããããã«å¿
èŠã§ãã
ããããããšãªãããjline.ConsoleReader $ readLine.callãããå ŽæãååŸãããã®äžã«ãã¬ãŒã¯ãã€ã³ããèšå®ãããã®åŸãã¡ã€ã³ã¹ã¬ãããéå§ããŠããã«äœæ¥ããŸããã
evReqMan = vm.eventRequestManager(); frame = mainThread.frames().get(10); bpReq = evReqMan.createBreakpointRequest(frame.location()); mainThread.resume(); bpReq.enable();
ããã§ãã¬ãŒã¯ãã€ã³ããèšå®ãããŸããã å®éšçãªGroovyã·ã§ã«ã«åãæ¿ããŠEnterããŒãæŒããšãåœŒãæ¬åœã«åæ¢ããããšãããããŸããã ãã¬ãŒã¯ãã€ã³ãã§ãããŒã忢ããŸããå®éšçãªJVMã®åäœã«ãã¹ãŠã®æºåãæŽããŸãã
Groovy Shellãªããžã§ã¯ããžã®åç
§ãååŸãã
JDI APIã䜿çšãããšãStackFrameãã倿°ã衚瀺ã§ããŸãã Groovy Shellã³ã³ããã¹ããã倿°ã®å€ãååŸããã«ã¯ãæåã«ã·ã§ã«èªäœãžã®ãªã³ã¯ãæ¡åŒµããå¿
èŠããããŸããã ãããã圌ã¯ã©ãã§ããïŒ
ãã¹ãŠã®ã¹ã¿ãã¯ãã¬ãŒã ã®ãã¹ãŠã®å¯èŠå€æ°ãã¹ãã€ããŸãã
i=0; mainThread.frames().each{ println String.valueOf(i++)+": "+it; try{ it.visibleVariables().each{var-> println " - "+var; }} catch(Exception e) {} }; println;
ãªããžã§ã¯ããorg.codehaus.groovy.tools.shell.Mainãã§ãã·ã§ã«å€æ°ã衚瀺ãããŠããã¹ã¿ãã¯ãã¬ãŒã ãèŠã€ãããŸããã
ã48ïŒorg.codehaus.groovy.tools.shell.MainïŒ131 java.lang.Threadã®ã¹ã¬ããã€ã³ã¹ã¿ã³ã¹ïŒåå= 'main'ãid = 1ïŒãã
Groovy Shellããæ€çŽ¢ãããå€ãååŸãã
Shell.Mainã«ã¯ã€ã³ã¿ãŒããªã¿ãŒãã£ãŒã«ãããããŸãã Groovy Shellã®å
éšãå°ãç¥ã£ãŠããŠãGroovyShellã³ã³ããã¹ã倿°ã
groovy.lang.Bindingåã®ãªããžã§ã¯ãã«æ ŒçŽãããŠããããšãäºåã«ç¥ã£ãŠããŸãããããã¯ã
ã€ã³ã¿ãŒããªã¿ãŒã§ getContextïŒïŒãåŒã³åºãããšã§ååŸã§ããŸãïŒgroovy.lang.Bindingãéèš³è
ãªãïŒã
BindingãããgetVariableïŒString varNameïŒã¡ãœãããåŒã³åºãããšã§å€æ°å€ãååŸã§ããŸãã
frame = mainThread.frames().get(48); vShell = frame.getValue(frame.visibleVariableByName("shell")); vInterp = vShell.getValue(vShell.referenceType().fieldByName("interp")); vContext = vInterp.invokeMethod(mainThread, vInterp.referenceType().methodsByName("getContext").get(0), [], 0) varVal = vContext.invokeMethod(mainThread, vContext.referenceType().methodsByName("getVariable").get(0), [vm.mirrorOf("myVar")], 0)
ã¹ã¯ãªããã®æåŸã®è¡ã¯ãæåŸ
å€ãããã€ãã®ç¹å¥ãªå€ããè¿ããŸãã-ãã¹ãŠãæ©èœããŸãïŒ
æåŸã®ã¿ãã
楜ãã¿ã®ããã«ããããã¬ãããã®å€æ°ã®å€ã倿Žããããšã決å®ããŸããããã®ãããBindingã§setVariableã¡ãœããïŒString varNameãObject varValueïŒãåŒã³åºãã ãã§ååã§ãã äœããã£ãšç°¡åã ãããïŒ
varVal = vContext.invokeMethod(mainThread, vContext.referenceType().methodsByName("setVariable").get(0), [vm.mirrorOf("myVar"), vm.mirrorOf("Surprise!")], 0); bpReq.disable(); mainThread.resume();
ãã¹ãŠãæ©èœããããšã確èªããããã«ããã¬ãŒã¯ãã€ã³ããzadizableã«ãããã¬ãŒã¯ãã€ã³ãã§ä»¥åäžæãããã¡ã€ã³ã¹ããªãŒã ãéå§ããŸããã
æåŸã«å®éšçãªGroovyã·ã§ã«ã«åãæ¿ããŠã倿°myVarã®å€ã確èªãããšããããé©ãïŒãã§ããããšãããããŸããã
çµè«
Javaããã°ã©ããŒã§ããããšã¯ç¥çŠã§ããSunã匷åãªããŒã«ãæäŸããŠãããããã§ããã€ãŸããåªããæ©èœïŒ-ïŒ
ãŸããJDIã®äŸ¿å©ãªã©ãããŒïŒã¡ã¿ã¯ã©ã¹ïŒãGroovyã«è¿œå ãããšãGroovy Shellããã®ããã°ã©ã ã®ãããã°ãéåžžã«æ¥œãããã®ã«ããããšãã§ããŸãã æ®å¿µãªãããçŸæç¹ã§ã¯ãããšãã°ãªãã¬ã¯ã·ã§ã³APIãä»ãããã£ãŒã«ããã¡ãœãããžã®ã¢ã¯ã»ã¹ãšåãããã«èŠããŸãã
UPDïŒ
Groovyã®ã¹ã©ãŒããã³å£ã£ãã©ãããŒã¯ã
youdebug.kenai.comã«ãããŸãã
èªåã§æžãå§ãã
-github.com/mvmn/groovyjdi