HSDB CLIを使ってJavaオブジェクトを調べる
このへん参照してやった。
http://www.oracle.com/webfolder/technetwork/jp/javamagazine/Java-JA12-architect-bajaj.pdf
事前準備
export SA_JAVA=/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java
Javaのプロセスを調べる
$ jps 17968 GradleDaemon 17971 DemoApplication 17956 GradleWrapperMain 17800 RemoteMavenServer 17998 Jps
コアダンプを取得
$ sudo gcore -v -o core.17971 17971
HSDB CLIを起動
java -Dsun.jvm.hotspot.debugger.useProcDebugger=true -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/sa-jdi.jar sun.jvm.hotspot.CLHSDB
取得したコアダンプをアタッチ
hsdb> attach /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java core.17971 Opening core file, please wait...
Javaオブジェクトを調査
hsdb> class java.lang.Object java/lang/Object @0x00000007c0000f28 hsdb> inspect 0x00000007c0000f28 Type is InstanceKlass (size of 440) juint Klass::_super_check_offset: 40 Klass* Klass::_secondary_super_cache: Klass @ null Array<Klass*>* Klass::_secondary_supers: Array<Klass*> @ 0x000000011c04f088 Klass* Klass::_primary_supers[0]: Klass @ 0x00000007c0000f28 oop Klass::_java_mirror: Oop for java/lang/Class @ 0x00000006c00007f0 Oop for java/lang/Class @ 0x00000006c00007f0 jint Klass::_modifier_flags: 1 Klass* Klass::_super: Klass @ null Klass* Klass::_subklass: Klass @ 0x00000007c036ba18 jint Klass::_layout_helper: 16 Symbol* Klass::_name: Symbol @ 0x00000001019160b0 AccessFlags Klass::_access_flags: 553648161 markOop Klass::_prototype_header: 5 Klass* Klass::_next_sibling: Klass @ null u8 Klass::_trace_id: 589824 Klass* InstanceKlass::_array_klasses: Klass @ 0x00000007c00117a8 Array<Method*>* InstanceKlass::_methods: Array<Method*> @ 0x000000011c04f3d0 Array<Method*>* InstanceKlass::_default_methods: Array<Method*> @ null Array<Klass*>* InstanceKlass::_local_interfaces: Array<Klass*> @ 0x000000011c04f088 Array<Klass*>* InstanceKlass::_transitive_interfaces: Array<Klass*> @ 0x000000011c04f088 Array<u2>* InstanceKlass::_fields: Array<u2> @ 0x000000011c04f3b8 u2 InstanceKlass::_java_fields_count: 0 ConstantPool* InstanceKlass::_constants: ConstantPool @ 0x000000011c04f0f8 ClassLoaderData* InstanceKlass::_class_loader_data: ClassLoaderData @ 0x00007fd16c60d470 u2 InstanceKlass::_source_file_name_index: 48 char* InstanceKlass::_source_debug_extension: char @ null Array<jushort>* InstanceKlass::_inner_classes: Array<jushort> @ 0x000000011c04f058 int InstanceKlass::_nonstatic_field_size: 0 int InstanceKlass::_static_field_size: 0 u2 InstanceKlass::_static_oop_field_count: 0 int InstanceKlass::_nonstatic_oop_map_size: 0 bool InstanceKlass::_is_marked_dependent: 0 u2 InstanceKlass::_minor_version: 0 u2 InstanceKlass::_major_version: 52 u1 InstanceKlass::_init_state: 4 Thread* InstanceKlass::_init_thread: Thread @ 0x00007fd16e00a800 int InstanceKlass::_vtable_len: 5 int InstanceKlass::_itable_len: 2 u1 InstanceKlass::_reference_type: 0 OopMapCache* InstanceKlass::_oop_map_cache: OopMapCache @ 0x00007fd16c4cd270 JNIid* InstanceKlass::_jni_ids: JNIid @ null nmethod* InstanceKlass::_osr_nmethods_head: nmethod @ null BreakpointInfo* InstanceKlass::_breakpoints: BreakpointInfo @ null u2 InstanceKlass::_generic_signature_index: 0 jmethodID* InstanceKlass::_methods_jmethod_ids: jmethodID @ null u2 InstanceKlass::_idnum_allocated_count: 14 Annotations* InstanceKlass::_annotations: Annotations @ null nmethodBucket* InstanceKlass::_dependencies: nmethodBucket @ null Array<int>* InstanceKlass::_method_ordering: Array<int> @ 0x000000011c04f040 Array<int>* InstanceKlass::_default_vtable_indices: Array<int> @ null
SierraではOpenJDKをビルドできない
タイトルそのまま。
ここにあるとおり OpenJDK 9で Yosemite になる。
https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms
SierraでOpenJDKのデバッグ版が欲しい場合は Dockerを使おう。
https://hub.docker.com/r/fbecker/openjdk-8-debug/
github.com
この辺を参考にしたらできると思うし、このイメージをそのまま使ってもいいと思う。(まだ使ってない)
Docker for Mac から PHPをリモートデバッグする
以下を参考に設定した。
Dockerfileの例(抜粋)
# PHP RUN echo "[Xdebug]" >> /etc/php.ini && \ echo "zend_extension=/path/to/xdebug.so" >> /etc/php.ini && \ echo 'xdebug.idekey = "PHPSTORM"' >> /etc/php.ini && \ echo "xdebug.max_nesting_level=1000" >> /etc/php.ini && \ echo "xdebug.remote_autostart=1" >> /etc/php.ini && \ echo "xdebug.remote_host=10.254.254.254" >> /etc/php.ini && \ echo "xdebug.remote_enable=1" >> /etc/php.ini && \ echo "xdebug.remote_handler=dbgp" >> /etc/php.ini && \ echo "xdebug.remote_port=49190" >> /etc/php.ini && \ echo "xdebug.profiler_enable=1" >> /etc/php.ini && \ echo "xdebug.profiler_output_dir=/tmp" >> /etc/php.ini && \ echo "xdebug.remote_log=/tmp/xdebug.log" >> /etc/php.ini
これをビルドするとDocker上の /etc/php.ini は以下のようになる
[Xdebug] zend_extension=/path/to/xdebug.so xdebug.idekey = "PHPSTORM" xdebug.max_nesting_level=1000 xdebug.remote_autostart=1 xdebug.remote_host=10.254.254.254 xdebug.remote_enable=1 xdebug.remote_handler=dbgp xdebug.remote_port=49190 xdebug.profiler_enable=1 xdebug.profiler_output_dir=/tmp xdebug.remote_log=/tmp/xdebug.log
sbt console で scalacOptions を指定する
これでOK
% sbt > set scalacOptions ++=Seq("-Xprint:parser") [info] Defining *:scalacOptions [info] The new value will be used by compile:scalacOptions [info] Reapplying settings... [info] Set current project > set scalacOptions ++=Seq("-Xlog-implicit-conversions") [info] Defining *:scalacOptions [info] The new value will be used by compile:scalacOptions [info] Reapplying settings... [info] Set current project > console ... scala> for { | x <- List(1,2,3) | y <- Some(1) | } yield { | x + y | } [[syntax trees at end of parser]] // <console> package $line3 { object $read extends scala.AnyRef { def <init>() = { super.<init>(); () }; object $iw extends scala.AnyRef { def <init>() = { super.<init>(); () }; object $iw extends scala.AnyRef { def <init>() = { super.<init>(); () }; val res0 = List(1, 2, 3).flatMap(((x) => Some(1).map(((y) => x.$plus(y))))) } } } } <console>:10: inferred view from Option[Int] to scala.collection.GenTraversableOnce[?] = scala.this.Option.option2Iterable[Int]:(xo: Option[Int])Iterable[Int] y <- Some(1) ^ [[syntax trees at end of parser]] // <console> package $line3 { object $eval extends scala.AnyRef { def <init>() = { super.<init>(); () }; lazy val $result = $line3.$read.$iw.$iw.res0; val $print: String = { $read.$iw.$iw; "".$plus("res0: List[Int] = ").$plus(scala.runtime.ScalaRunTime.replStringOf($line3.$read.$iw.$iw.res0, 1000)) } } } res0: List[Int] = List(2, 3, 4)
株式会社プラグラムを退職しました
私事で恐縮ですが、2015年6月30日をもって、株式会社プラグラムを退職しました。株式会社プラグラムには、会社ができるジェネフィックスデザインという会社の頃からフリーランスとして、プラグラムという会社ができてからは社員として関わってきました。
約4年と半年ぐらいですが、受託から始まりスマレジという自社サービスを開始し、受託をやめて自社サービスひとつに絞ったり、最近ではアメリカ進出したりと短いなりにとても濃い時間を過ごせました。
関わっていただいた皆さまには大変お世話になり、ありがとうございました。
スマレジでは主に業務のコアになる取引周りやWebAPIなど担当させてもらい、IT業界とは違う小売業の方々や飲食店の方々がどのように業務を行っているかなど普段行ってるIT勉強会とはまた違った意味でとても勉強になりました。
明日からはフリーランスのITエンジニアとして働く予定です。
プラグラムとも引き続き一緒に仕事をしていく予定ですが、長期常駐でなければたぶん大丈夫なので、お気軽に仕事を依頼ください。(7月はすでに仕事で埋まってますので、8月以降が有難いです)
CasperJS歴3時間でハマったこと
はまったことメモ
- HTTPレスポンスのステータスコード(404)を取得したい
casper.on('http.status.404', function(resource) { this.echo('wait, this url is 404: ' + resource.url); });
- HTMLページを読み込んだときにJSのシンタックスエラーがあるかどうか知りたい(ほかのエラーも)
casper.on( 'page.error', function (msg, trace) { this.echo( 'Error: ' + msg, 'ERROR' ); });
- 指定したForm内にどんなものがあるか知りたい
var utils = require('utils'); utils.dump(this.getFormValues('#form'));
- SSLのページでもCasperを動かしたい
casperjs test --ssl-protocol=any sample.js
自分がプロジェクトでKnockoutを使うときに気をつけていること
れはKnockoutJSアドベントカレンダー24日目の記事です。
KnockoutJS Advent Calendar 2014 - Qiita
今日はネタも尽きたので自分がプロジェクトでKnockoutを使うときに気をつけていることをグダグダ書こうと思います。
1. ViewModelやModelにjQueryなどのDOM操作をするライブラリを使用しない
これは責務の問題とテストしやすくするためです。
KnockoutJSでは MVVM (Model-View-View Model) というデザインパターンを適用することでUIをシンプルに記述できるようにしています。
この "Model", "View", "View Model" という役割ですが、それぞれ
Model: データ自体を扱う
View: ユーザインターフェースを扱う
ViewModel: UIバインディングを行ったりモデルからデータ取得したり更新したりする
といったような役割分担があります。
例えばHTMLは基本的にViewレイヤー。あるデータに特化したロジックやサーバとの通信を用いた永続化処理などはModel(JS)に書きます。ViewModelはJSです。
ただ、たまにバインディング時にjQueryでDOM指定して何かやりたい場合があります。
そういう場合は自分はカスタムバインディングを使ったりしますが、基本的には使わないよう気をつけます。
こうすることで ViewModel はほぼPOJO?(Plain Old JavaScript Object)で書くことができます。
ただModelでサーバと通信をしたりします。その場合は jquery-mockjax を使ったりモックで代用します。
テストをセットアップについては以前ブログを書いたので参考にしてみるといいかもしれません。
Knockout.jsとKarmaで簡単TDD開発 - 418 | I'm a teapot
2. データを引数にModelを作成するときはコンバータを挟む
サーバからデータを取得しModelを作成するときですが、場合により形が違うデータ(JSオブジェクト)がくる場合があります。
例えば、以下のような業務システム(発注業務)を考えてみます。
- 初期データ取得時、サーバから商品IDに紐付く商品情報を取得しModelを作成して発注明細に追加する
- 商品検索ボタンを押すと検索ダイアログが開く。そのダイアログから商品を選択してModelを作成して発注明細に追加する
- 商品追加ボタンを押すと空の商品情報入力フォームが発注明細に追加される。
この場合、同じモデル(商品情報)を作る場合でも場合によりModelを作成するときの引数に渡されるJSオブジェクトのデータ構造が変わる場合があります。
こういった場合、都度Model内で変換してもいいのですが、別途以下のようなコンバータみたいなのを作ってやると管理が楽になります。
var converter = { // 発注情報に登録されている商品情報を発注明細に追加したとき fromServer: function(item){ return { productCode: item.order.product_code productName: item.order.product_name }; }, // 検索ダイアログから商品情報を発注明細に追加したとき fromSearchDialog: function(item){ return { productCode: item.productCode productName: item.productName }; }, // 空の商品情報入力フォームが発注明細に追加されたとき createEmpty: function(){ return { productCode: null, productName: null }; } };
例えば初期データ取得時、サーバから商品IDに紐付く商品情報を発注明細に追加する場合は、
サーバから取得した商品情報のJSオブジェクトに converter.fromServer() を使います。
model.load("/product/1", {}, function(result){ var product = converter.fromServer(result); self.orderDetals.push(product); } );
同様に検索ダイアログから商品情報を発注明細に追加する場合は以下のようにします。
function selectProduct(selectedProduct) { var product = converter.fromSearchDialog(selectedProduct); self.orderDetals.push(product); }
上記はあくまでサンプルですがイメージとしてはこんな感じです。
そろそろ本格的にグダグダしてきたのでこれぐらいで・・・。
明日はいよいよラスト! @sukobuto さんの「KO + TypeScript + Cordova でハイブリッドアプリ開発」です!よろしくお願いします!