Play framework + Scala でリクエストが返らずに嵌った
環境
ある時を境にどのURLにリクエストを投げても、
ずっと読み込み中のままいつまでたってもレスポンスがかえってこなくなった。
ログを見ても以下で止ったままで何も出力されない。
... Traversing /home/kiris/project/sample1/tmp/generated/views.defaults.html.welcome.scala Traversing /home/kiris/project/sample1/tmp/generated/views.html.main.scala API phase took : 1.759 s
原因がさっぱりわからないのでThread Dumpだしてみた。
% jps 19264 Jps 18730 Server % jstac 18730 "Thread-3" prio=10 tid=0x00007fe8d87ff000 nid=0x6ba9 waiting for monitor entry [0x00007fe8dc3d7000] java.lang.Thread.State: BLOCKED (on object monitor) at sbt.BufferedLogger.doBufferableIf(BufferedLogger.scala:87) - waiting to lock <0x00000000f6ec6e78> (a sbt.Logger$$anon$1) at sbt.BufferedLogger.doBufferable(BufferedLogger.scala:85) at sbt.BufferedLogger.log(BufferedLogger.scala:75) at sbt.Logger$class.error(Logger.scala:74) at sbt.AbstractLogger.error(Logger.scala:8) at sbt.BasicIO$$anonfun$processErrFully$1.apply(ProcessImpl.scala:51) at sbt.BasicIO$$anonfun$processErrFully$1.apply(ProcessImpl.scala:51) at sbt.BasicIO$.readFully$1(ProcessImpl.scala:73) ...
どうもsbtからエラーログを出力する所で止ってしまっているっぽい。
出力しようとしている文字列がわかれば原因が特定できそうなので、
Eclipse PluginのMemory Analyzer(http://eclipse.org/mat/)を使ってヒープ解析。
Thread-3で検索かけて調べてみると、どうもJPAとAnorm共存させていたせいか、
JPA側のアノテーションプロセッサの処理でコケてたっぽい。怪しい行を削除したら動いた。
まとめ
- PlayでEnsimeのデバッガーを動かせるようしておくべき
- あけましておめでとう
Scala 2.9.1 + sbt 0.11.2 でpicture-showをインストール
picture-showについてはこちらを参照。
[error] {file:/home/iwanaga/repos/picture-show.git/}PictureShow Conscript/*:update: sbt.ResolveException: unresolved dependency: org.scala-tools.sbt#launcher-interface;0.7.4: not found [error] Total time: 31 s, completed 2011/12/16 12:16:11
のように怒られて、picture-showがインストールできない人向け。
ローカルで依存関係を解決しても、conscriptでコケるのでforkしてしまった。
% git clone git://github.com/kiris/picture-show.git % cd picture-show % sbt publish-local % cs kiris/picture-show
Javaでシングルトンの遅延初期化
もっとも簡単なシングルトンの例
@ThreadSafe final class Singleton { public static final Singleton INSTANCE = new Singleton(); private Singleton() {}; }
staticフィールドの初期化は、そのクラスに初めてアクセスされた(≠クラスがロードされた)時に行なわれる。
そこで次の例では、インスタンスが必要になる時まで生成を遅らせている。
@ThreadSafe final class Singleton { private static Singleton instance; private Singleton() {}; public static synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } }
確かにインスタンスの生成は遅らせされたが、getInstanceを実行する度にスレッドの同期が行なわれるのはうれしくない。
そこで登場するのが悪名高きdouble-checked locking pattern。
アウトオブオーダー書き込みのせいで、不完全なインスタンスが別スレッドに公開されることがあるので使ってはいけない。
@NotThreadSafe final class Singleton { private static Singleton instance; private Singleton() {}; public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
Java 5.0からは変数にvolatile修飾子を付けることでこれを防げる。
以下はJava 5.0以降でのみ安全なdouble-checked locking pattern。
@ThreadSafe final class Singleton { private static volatile Singleton instance; private Singleton() {}; public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
そして、最後に示すのがInitialization-on-demand holder idiom。
LazyHolderの初期化は、getInstance()が実行されるまで行なわれないので、
スレッドセーフかつ高速なシングルトンの遅延初期化が実現できる。
@ThreadSafe public class Singleton { private Singleton() {} private static class LazyHolder { public static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return LazyHolder.INSTANCE; } }
refs
Scala 2.9.1 + Ensime 0.7.6 + SBT 0.11.0 でensime-sbtが動かない
エラー内容
... ==== Scala-Tools Maven2 Snapshots Repository: tried http://scala-tools.org/repo-snapshots/org/scala-tools/sbt/sbt_2.9.1/0.7.4/sbt_2.9.1-0.7.4.pom :::::::::::::::::::::::::::::::::::::::::::::: :: UNRESOLVED DEPENDENCIES :: :::::::::::::::::::::::::::::::::::::::::::::: :: org.scala-tools.sbt#sbt_2.9.1;0.7.4: not found :::::::::::::::::::::::::::::::::::::::::::::: :: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS unresolved dependency: org.scala-tools.sbt#sbt_2.9.1;0.7.4: not found Error during sbt execution: Error retrieving required libraries (see /Users/euler/.sbt/boot/update.log for complete log) Error: Could not retrieve sbt 0.7.4 Process sbt exited abnormally with code 1
ensime-sbt-project-dir-pに"/project"をセットするか、空の/project/build.propertiesを作成すれば良いっぽい。
Ubuntu 11.10で開き方にemacsclientを追加する
mkdir -p ~/.local/share/applications cat > !$/emacsclient.desktop <<EOF [Desktop Entry] Version=1.0 Name=Emacsclient GenericName=Text Editor Comment=View and edit files MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; Exec=/usr/bin/emacsclient -c %F Icon=/usr/share/icons/hicolor/scalable/apps/emacs23.svg Type=Application Terminal=false Categories=Utility;Development;TextEditor; StartupWMClass=Emacsclient EOF
refs
Lombokを使えばJavaでScalaのval(っぽいもの)が使えるんだぜ!
という煽りでしかないエントリー書こうと思ってたけど、
なんかもう僕の中で満足しちゃったので、
先日、社内勉強会の発表に使った資料を貼ってお茶濁し。