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をリモートデバッグする

以下を参考に設定した。

forums.docker.com


Macの設定

Macでターミナルを立ち上げて次のコマンドを入力

sudo ifconfig lo0 alias 10.254.254.254
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
PhpStormの設定

あとはここを参考にしたらいけた
qiita.com


ちょっとトリッキーすぎる・・・。

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時間でハマったこと

はまったことメモ

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 でハイブリッドアプリ開発」です!よろしくお願いします!