トップ «前の日記(2004-09-25) 最新 次の日記(2004-09-27)» 編集

日々の破片

著作一覧

2004-09-26

_ PDAにあって、携帯に無いものなんだ?

手書き。これはどうにもならんな、今のところ。

本は一応読める。そう言えば青空文庫を見てないけどHTML版は読めるかな?

スケジューラも一応はあるし、アラームはPDAより強力だから移行できそうだ。

電話帳もある。

ゲームもある。つい、ぴちょん君の四川省とか買ってしまったが。

MP3プレイヤーと思ったけどその気になればFMラジオもあるし、iPodがあるからこれは不要。

TODOもあることはある。

操作性は低い。でもコギャル打ち込みをマスターすればどうにかなるんだろう、きっと。

それでもメモ帳もあることはある。

バックアップもSDカードへできる。

バイザーを持ち運ぶのをやめることはできそうな気がしてきた。購入後今月で丸3年かな。想像以上に役に立ったがガジェットを3個も持ち歩くのはちょっとごめんになってきたし。

あとは、MySyncか。自分で作れるかな? インターフェイス次第だな。結局、SDカードリーダライタだけではだめで、USBケーブルは必要ということのようだ。

PCとの連動を考えなければ手書きメモ+カメラで撮影という方法もありかも。

_ JNIの本

FAQを読むといかにも買わなきゃだめに見える。でも、コード例はこちらと書いたリンクをたどるとどうも全文らしきPDFがダウンロードできる。って言うかHTML版もある。

ってことは、もしかしてEffective Javaもか? と思うと(持ってはいるが拠点は3ヶ所、本は1冊)、こちらは3章と5章だけだった。

_ rjb+マルチスレッドの問題点

スタックを参照するGCがまずいというRuby側の問題はおいておくとして(いざとなれば、コールバック中――Rjbでメインスレッド以外の呼び出しが発生するのはインターフェイス経由で他のスレッドからのイベント通知の場合だけのはずだ――はGCを停止すれば良い)(追記:大甘。jumpバッファのこと忘れてるジャン)、わかっているのは次の2点。

1. メインスレッド用JNIEnvポインタを使用。この動作を変更するのは難しい。Win32専門とすればTLSの使い方くらいはわかるが、一応、他のOSのことも(AWT利用以外でメインスレッド以外からのコールバックがあるかという点はおいておくとして)考える必要があり、かつ現時点ではpthreadのAPIについて見る気はしない。

ただし、コールバック関数にJVMがJNIEnvポインタを与えるからこれを利用するという手段はある。ただし、相当制限を付けなければだめだが。

仮にマルチスレッディングでもシーケンシャルに動作すると前提すれば

  メイン        ワーカ
    |
    +------>   + (コールバックの実行)
                  |  −JNIEnvの摩り替え
                  |
    +  <----------+    JNIEnvの復元
    | (復元されたJNIEnv)
    |

とできる。しかし、複数のイベントが入れ子になるような状況では(ワーカスレッドBとCが同時にコールバックされると仮定すれば)、-B(A)…… -C(B) ----- +A() --- +B() となりえるからだ。()がスタックに保持された元のJNIEnv。かつ、Cが入り込んだ時点でグローバルなJNIEnvはCとなるため、Bの動作に問題が起きる。

結局、グローバル変数としてJNIEnvを保持するのは無理がある。すると、すべてのJNIEnvを利用する関数に引数としてJNIEnvを与える必要が出てくる。わっ、かったるい。だったらTLSを(#ifdefで切り替えて)使うほうがましだ。

問題はそれだけではなく、

2. Rjbデータとして保存したJavaオブジェクトのローカル参照がだめ。

ということもある。たまに動作することがあるから、常にダメというわけではないようだが、使えるとは前提できない仕様なんだからだめはだめなわけだ。これも問題だ。同様にjclassのキャッシュが使えない前提となるからだ。

だったら、コールバックされた時点でグローバルのJNIEnvと異なれば(この判定方法が正しいかどうかは不明。とりあえずそうだと仮定)メインスレッドに対してシグナルを送って、メインスレッドで動かすという手段もありそうだ(ASRの手法)。ところがどっこい、ここで大前提となっているのはAWT/Swingでの利用なのだから、メインスレッドからAWTスレッドを触ること自体が禁じ手だからお話にならない。と思ったけど、Runnableを起動するスタブを作ればどうか? と思ったがその場合はRuby側のコードは動かせないから(元の条件と同じになる)結局これもだめ。

_ JNI: グローバルリファレンスとローカルリファレンス

うむ、良くJNIの仕様を読んだら、ちゃんと書いてあった。

すべてのJNI関数はローカル参照を返すが、グローバル参照も受け付ける。

したがって、その場で解放する必要がない、というかキャッシュすべきオブジェクトはすべてグローバル参照として保持すれば良いということだ。多分(と微妙に自信がなかったり)。(オーバーヘッドの問題か、GCの阻害要因になるかでローカル参照を主としてるのかな)

というわけで、とりあえず、コールバックではJNIEnvの摩り替え、rjb内でのキャッシュにはグローバル参照を利用、というように変えてみる。

本日のツッコミ(全6件) [ツッコミを入れる]
_ AC (2004-09-27 14:08)

手書き付きfoma<br>http://arena.nikkeibp.co.jp/rev/av/20040702/108993/index2.shtml<br><br>ところでartonさん。rjbのコードレビュー希望。<br>そもそも今までDL使ってるの気付かなかったわけだが。

_ AC (2004-09-27 15:57)

invokeで実際に実行する直前(2370行付近)で<br> JNIEnv* cenv;<br> (*jvm)->AttachCurrentThread(jvm, &cenv, NULL);<br>してjenvからcenvに置換したらshowMessageDialog出来た。<br>けどexceptionが出ると`stack level too deep (SystemStackError)'とか出る。<br>check_exception_env(JNIEnv*, int)を作ったけど変わらず。

_ arton (2004-09-27 22:56)

うーむ、その点はfomaすごいな。<br>で、Ruby側がメインスレッドのスタックを保持したjumpbuffをワーカスレッド側に戻しているのではないかと予想してます。<br>どうにかなるかならないか、見る予定で週末まで放置。<br>#コードレビューってどのあたり?

_ arton (2004-09-27 23:44)

とぼけたこと書いてたみたいだ。15:57の修正のレビューについてですね。<br>多分、問題になるのはオブジェクトだろうからinvokeの直前を特別扱いで済むかも知れませんが、コールバックされたrubyコード内でのRjbメソッド呼び出しでの引数変換、戻り値変換などにもjenvは使われます。プリミティブ変換は良いとしてもオブジェクトによってはまずい可能性があります。だから、面倒だけど関連する全関数の引数として現在のjenvを与えるしかないのではないかと思います。

_ AC (2004-09-28 03:11)

Ruby側で保持するインスタンスについては全てグローバル参照なら問題となるのはインスタンスメソッドの呼び出しぐらいだと思って簡単に対処してみたんですが、やっぱり毎度AttachCurrentThreadして取得するしかないと思う。<br>というか、微妙な対策版ではスペース連打しただけで落ちた(w<br>だいたい、スレッド周りはJavaだけで書いてても普通にハマれるとこだし、仕様策定した人もJNIでここまでやるとは思ってないだろうきっと。<br>でもふと思ったけど、JNI側ではsynchronize出来ないんだからどうやったってスレッド周りはいつか破綻する様な…。<br><br>レビューはstatic const jconv_table jcvt[]とかstatic jprimitive_table jpcvt[]とか希望。<br>関数ポインタテーブルは読み慣れてないのです。<br><br>ところでASCIIの外側の文字列なんですがjava.lang.String(byte[] bytes, String charsetname)があるので、make時の環境から標準の文字コードをとっておいて、あとは$KCODEから判別すればそれなりになると思うのだけど、コンストラクタがとれなくてょんぼりです。ドキュメント無いですか?<init>と()Vとか言われても欲しいのはデフォルトコンストラクタじゃないのだよ>Google。<br>(*jenv)->GetMethodID(jenv, j_string, "<init>", "([BLjava.lang.String;)V");<br>では駄目らしい。

_ arton (2004-09-28 09:17)

レビューの件は了解(週末くらい)。<br>Global参照での保持は、まだ作業中のソースでしかやってない。<br>あとJNIからの同期にはモニターが使えます(http://java.sun.com/docs/books/jni/html/other.html#5561)。<br>コンストラクタが取れないのは3個目の引数を"([BLjava/lang/String;)V"にしてみてください。JNI内ではパッケージの区切り文字はドットじゃなくてスラッシュです。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|

ジェズイットを見習え