<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ものぐさ備忘録 &#187; JDB</title>
	<atom:link href="http://www.ginriki.net/wd/category/jdb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ginriki.net/wd</link>
	<description>ソフトウェア関係の話を中心とした備忘録的日記</description>
	<lastBuildDate>Sun, 16 Jan 2011 20:07:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JRuby実行中にjdbでアタッチしてrubyプログラムのbacktrace</title>
		<link>http://www.ginriki.net/wd/2010/01/12/114/</link>
		<comments>http://www.ginriki.net/wd/2010/01/12/114/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 22:02:46 +0000</pubDate>
		<dc:creator>ginriki</dc:creator>
				<category><![CDATA[JDB]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[backtrace]]></category>
		<category><![CDATA[JRuby]]></category>

		<guid isPermaLink="false">http://www.ginriki.net/wd/?p=114</guid>
		<description><![CDATA[Ruby自身のデバッガだと、任意のタイミングでアタッチしてbacktrace見るといったことができない（はず）なので、もっと低レベルのデバッガを利用して、それを実現する方法についてメモ。今回はJRubyに対してjdbでア [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby自身のデバッガだと、任意のタイミングでアタッチしてbacktrace見るといったことができない（はず）なので、もっと低レベルのデバッガを利用して、それを実現する方法についてメモ。今回はJRubyに対してjdbでアタッチ＆backtraceする方法についてのメモです。<br />
なお、CRubyの場合は、<a href="http://www.ginriki.net/wd/2009/11/09/80/">以前の記事</a>とか、さらにその先のリンク先を見れば良いです。<br />
ちなみに、今回試したJRubyのversionは以下の通り。OSはCentOS 5.3です。</p>
<pre>
$ jruby --version
jruby 1.3.1 (ruby 1.8.6p287) (2009-06-15 2fd6c3d) (Java HotSpot(TM) Client VM 1.6.0_16) [i386-java]
</pre>
<p><br/></p>
<h2>jdbによるbacktrace</h2>
<p><br/><br />
まず、アタッチ対象例のRubyコードとして以下を用意。</p>
<p>sample.rb</p>
<div class="igBar"><span id="lruby-2"><a href="#" onclick="javascript:showPlainTxt('ruby-2'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-2">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">def</span> foo</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">"abc"</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; bar</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">def</span> bar</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">"foge"</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#CC0066; font-weight:bold;">sleep</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;color:#800000;">1000</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">abc </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>そして、デバッガattach用のポートを開けて起動します<sup>1</sup>。</p>
<pre>
$ jruby -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n sample.rb
</pre>
<p>barメソッド内のsleepの実行をしているうちに、別のターミナルを開いてjdbでアタッチし、スレッドを停止させます。</p>
<pre>
$ jdb -attach 8000
> suspend
すべてのスレッドが中断されました
</pre>
<p>そして、backtraceを表示させます。以下の方法で大体表示できます(いい加減なやり方ですが)。</p>
<pre>
> threads
グループ system:
  (java.lang.ref.Reference$ReferenceHandler)0x9db Reference Handler 状況待機中
  (java.lang.ref.Finalizer$FinalizerThread)0x9da  Finalizer         状況待機中
  (java.lang.Thread)0x9d9                         Signal Dispatcher 実行中
グループ main:
  (java.lang.Thread)0x1                           main              状況待機中
> thread 0x1
main[1] where
  [1] java.lang.Object.wait (ネイティブ メソッド)
  [2] org.jruby.RubyThread.sleep (RubyThread.java:718)
  [3] org.jruby.RubyKernel.sleep (RubyKernel.java:725)
  [4] org.jruby.RubyKernel$s_method_0_1$RUBYINVOKER$sleep.call (null)
  [5] org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call (JavaMethod.java:620)
  ...(以下略)
main[1] up 4
main[5] locals
メソッド引数:
context = instance of org.jruby.runtime.ThreadContext(id=2527)
self = instance of org.jruby.RubyObject(id=2528)
clazz = instance of org.jruby.MetaClass(id=2529)
name = "sleep"
arg0 = instance of org.jruby.RubyFixnum(id=2531)
block = instance of org.jruby.runtime.Block(id=2532)
ローカル変数:
main[5] dump context.frameIndex
 context.frameIndex = 2　#frameStackの上限(たぶん)
main[5] dump context.file + ":" + context.line
 context.file + ":" + context.line = "sample.rb:7" #現在位置
main[5] dump context.frameStack[2].fileName + ": " + context.frameStack[2].name + ":" + context.frameStack[2].line
 ...(省略)... = "sample.rb: bar:2" #１つ前のスタックフレーム
main[5] dump context.frameStack[1].fileName + ": " + context.frameStack[1].name + ":" + context.frameStack[1].line
 ...(省略)... = "sample.rb: foo:10" #2つ前のスタックフレーム
main[5] dump context.frameStack[0].fileName + ": " + context.frameStack[0].name + ":" + context.frameStack[0].line
 ...(省略)... = ": null:0"　#トップレベル
</pre>
<p>以上になります。</p>
<ol class="footnotes"><li id="footnote_0_114" class="footnote"><a href="http://wiki.github.com/datamapper/do/jruby">ここ</a>の「Debugger」の項目を参考にオプション設定しました。</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.ginriki.net/wd/2010/01/12/114/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

