EasyBuggy Bootのトリセツ

「EasyBuggy Boot」は、バグだらけのWebアプリケーション「EasyBuggy」のSpring Bootベースのクローンで、JavaのWebアプリケーションで起こりうる様々な問題を、非常に手軽に体験できるWebアプリケーションです。EasyBuggyと機能的な差異はほとんどありませんが、起動方法等に若干異なる部分があります。EasyBuggyよりも新しい技術が使われており、開発やデバッグがしやすくなっています。

easybuggy

EasyBuggy Bootの特徴

基本的にはEasyBuggyと同等の機能を持っているので、用途などはこちらのページを参照下さい。「EasyBuggy」と「EasyBuggy Boot」の主な構成の相違点は以下の通りです。

相違点 EasyBuggy EasyBuggy Boot
ベースとなる技術 Servlet 3.0.1 Spring Boot 1.5.6 (Servlet 3.0.1)
プレゼンテーション層 未使用 (一部 JSP 2.2 + JSTL 1.2) Thymeleaf 2.1.5 (一部 JSP 2.3 + JSTL 1.2)
DBクライアント/サーバー JDBC / Derby 10.8.3.0 Spring JDBC 4.3.9 / Derby 10.12.1.1 (Java 7の場合)、または10.13.1.1 (Java 8の場合)
LDAPクライアント/サーバー Apache DS Client API 1.0.0 / Server 1.5.5 Spring LDAP 2.3.1 / unboundid-ldapsdk 3.2.1
メール JavaMail 1.5.1 JavaMail 1.5.1 (Spring Boot Mailで導入されるJavaMail 1.5.6をオーバーライド)
開発ツール 無し Spring Boot Developer Tools 1.5.6
Java Java 6以上をサポート Java 7以上をサポート

スクリーンショット

以下はメインページで、ブラウザの言語設定によって日本語と英語が切り替えられるようになっています。見ての通り、いろいろなバグを確認できます。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f34333836392f34633864333931322d383736302d626363312d383834652d3465356131346536373131642e706e67

バグのリンクをクリックすると、そのバグが確認できます。

起動方法

EasyBuggyを起動して、http://localhost:8080にアクセスすると、メインページが表示されます。起動方法には次の3つがあります。

  • javaコマンドで起動
  • mvnコマンドで起動
  • warファイルをサーブレットコンテナにデプロイして起動

それぞれどのように使い分けるか説明します。

● javaコマンドで起動:

もっとも関単にEasyBuggyを起動する方法です。ROOT.warをダウンロードして、次のコマンドで起動します。

$ java -jar ROOT.war

この時、以下のようにJVMオプションを指定しておくと、問題が発生しやすく、またログを確認しやすくなります。

$ java -Xmx256m -XX:MaxMetaspaceSize=64m -XX:MaxDirectMemorySize=90m -XX:+UseSerialGC -Xloggc:logs/gc.log -Xloggc:logs/gc_%p_%t.log -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -XX:GCTimeLimit=15 -XX:GCHeapFreeLimit=50 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:ErrorFile=logs/hs_err_pid%p.log -XX:NativeMemoryTracking=summary -agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n -Dderby.stream.error.file=logs/derby.log -Dderby.infolog.append=true -Dderby.language.logStatementText=true -Dderby.locks.deadlockTrace=true -Dderby.locks.monitor=true -Dderby.storage.rowLocking=true -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -ea -jar ROOT.war

● mvnコマンドで起動:

GitHubからEasyBuggy Bootをgit cloneして下さい。

$ git clone https://github.com/k-tamura/easybuggy4sb 
$ cd easybuggy4sb

その後、次のコマンドでビルドから、起動までが一気にできます。

$ mvn clean spring-boot:run

新しい機能を追加したり、ソースコードを変更して動作確認してみたい場合、このコマンドを実行すればビルドして、すぐに動作確認をすることができます。

● warファイルをサーブレットコンテナにデプロイして起動:

Tomcat以外のコンテナにもデプロイできます。ROOT.warをダウンロードして、PayaraやJettyなどにデプロイすれば、起動します。javaコマンドで起動したときと同様に、JVMオプションを指定することをお勧めします。

開発の方法

STS (Spring Tool Suite)を使用して、EasyBuggy Bootのソースコードを参照したり、開発、デバッグする方法についても載せておきます。STSはEclipseベースのIDEで、Springベースの アプリケーションの開発が簡単にできるようにカスタマイズされています。

  1. このページからSTSをダウンロードして下さい。
  2. GitHubからEasyBuggy Bootをgit cloneして下さい。
    $ git clone https://github.com/k-tamura/easybuggy4sb
    $ cd easybuggy4sb
    
  3. 以下のコマンドを実行します。このコマンドでSTSでの開発に必要なファイル(.projectファイルや.classpathファイル)が作成されます。また、依存するライブラリのソースコードも参照できます。
    $ mvn dependency:sources
    $ mvn eclipse:eclipse
    
  4. STSを起動します。
  5. パッケージエクスプローラからクローンしたプロジェクトをインポートします。「Existing Maven Projects」を選択して、「Next」をクリックして下さい。
    Screenshot-Import .png
    「Root Directory」にクローンしたプロジェクトへのパスを入力し、「Finish」をクリックします。
    Screenshot-Import Maven Projects .png
  6. パッケージエクスプローラのeasybuggy4sbプロジェクトを右クリックし、「Debug As」、「Spring Boot App」と選択すると、デバッグモードでEasyBuggy Bootが起動します。
    Screenshot-Spring - easybuggy4sb-src-main-java-org-t246osslab-easybuggy4sb-Easybuggy4sbApplication.java - Spring Tool Suite .png

ソースコードを修正すると、自動的にリロードされて、修正が反映されることも確認してみて下さい。

リモートデバッグする方法

リモートのEasyBuggy Bootをデバッグする場合は、次のデバッグ設定を追加することでデバッガーをアタッチできます。

  • Connection type: Standard (Socket Listen)
  • Host: localhost
  • Port: 9009

Screenshot-Debug Configurations

 ビルドの方法

以下のコマンドで、実行可能かつデプロイ可能なwarファイルを作成することができます。

$ mvn clean package

注意事項

OutOfMemoryError関連のリンク(特にネイティブメモリを操作するもの)をクリックすると、PCの動作が不安定になる可能性があります。CPUやメモリを制限したVM上で起動するなどしてから、自己責任でリンクをクリックして下さい。

広告

EasyBuggy のトリセツ

EasyBuggyは、JavaのWebアプリケーションで起こりうる様々な問題を、非常に手軽に体験できるWebアプリケーションです。ここでいう問題とは、メモリリークやデッドロックなどの障害、SQLインジェクションやオープンリダイレクトなどの脆弱性、OutOfMemoryErrorなどのエラー、算術オーバーフロー、性能上の問題などいろいろなものが含まれます。

なぜそのようなものをつくったかというと、教育や実験に活用できると考えたからです。問題を再現させて事象を解析してみると、トラブルシューティングの方法やバグ修正の仕方を学ぶことができます。実践的に学習すると予想外な結果が出ることもあり、理由を調査して理解を深めることができます。そして、その経験があることで、実際に本番環境で問題が発生した時でも冷静に対応できるのではないかと考えます。

EasyBuggyの特徴

以下のような点にこだわって開発しました。

  • 簡単、手軽である
  • 多くの技術を使わず、基本的な技術のみを使う
  • IDE、ビルドツールと連携し、開発からデプロイまでが短時間にできる
  • サーブレットコンテナ、DB、LDAPなどを組み込み、インストールや初期設定が不要
  • 単純なパッケージ・クラス構成 (基本的に1機能 – 1サーブレットの関係)
  • デザインは最小限に (本当はこだわりたいんですが…)

スクリーンショット

以下はメインの画面で、ブラウザの言語設定によって日本語と英語が切り替えられるようになっています。見ての通り、いろいろなバグを確認できます。

main

バグのリンクをクリックすると、そのバグが確認できます。以下はOSコマンドインジェクションを確認できるページです。

math

java.lang.Mathを使用した数式を入力すると、計算結果が表示されるという単純な機能の中に、OSコマンドインジェクションの脆弱性があります。(i)マークで始まる説明の通り、特定の文字列を入力すると、致命的な問題が発生します。

起動方法

EasyBuggyを起動して、http://localhost:8080にアクセスすると、先ほどのメインページが表示されます。起動方法には次の3つがあります。

  • javaコマンドで起動
  • mvnコマンドで起動
  • warファイルをサーブレットコンテナにデプロイして起動

それぞれどのように使い分けるか説明します。

● javaコマンドで起動:

もっとも関単にEasyBuggyを起動する方法です。easybuggy.jarをダウンロードして、次のコマンドで起動します。

$ java -jar easybuggy.jar

この時、以下のようにJVMオプションを指定しておくと、問題が発生しやすく、またログを確認しやすくなります。

$ java -Xmx256m -XX:MaxPermSize=64m -XX:MaxDirectMemorySize=90m -XX:+UseSerialGC -Xloggc:logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -XX:GCTimeLimit=15 -XX:GCHeapFreeLimit=50 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:ErrorFile=logs/hs_err_pid%p.log -XX:NativeMemoryTracking=summary -agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n -Dderby.stream.error.file=logs/derby.log -Dderby.infolog.append=true -Dderby.language.logStatementText=true -Dderby.locks.deadlockTrace=true -Dderby.locks.monitor=true -Dderby.storage.rowLocking=true -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar easybuggy.jar

easybuggy.jarはPayara Microを組み込んでいるので、Tomcatなどのサーブレットコンテナが無くても、起動することができます。easybuggy.jarはTomcatを組み込んでいるので、サーブレットコンテナが無くても、起動することができます(バージョン1.3.0から変更しました)。

● mvnコマンドで起動:

次のコマンドでビルドから、起動までが一気にできます。

$ mvn clean install exec:exec

新しい機能を追加したり、ソースコードを変更して動作確認してみたい場合、このコマンドを実行すればビルドして、すぐに動作確認をすることができます。

mvnコマンドを実行する場合は、Payara Microではなく、組み込みのJettyサーバーが起動します。mvnコマンドを実行する場合も、組み込みのTomcatサーバーが起動します(バージョン1.3.0から変更しました)。

● warファイルをサーブレットコンテナにデプロイして起動:

Tomcat以外のコンテナにもデプロイできます。ROOT.warをダウンロードして、PayaraやJettyなどにデプロイすれば、起動します。easybuggy.jarを起動したときと同様にJVMオプションを指定することをお勧めします。

開発する方法

EasyBuggyはMavenのプロジェクトとして開発しているので、Eclipseで開発するためには、次のコマンドを実行します。

> mvn eclipse:eclipse

このコマンドを実行すると、Eclipseのプロジェクトに必要な .classpath や .project ファイルが作成されます。このプロジェクトをインポートすれば、Eclipseでソースコードを参照したり、改造したりすることができます。

デバッグする方法

Eclipseの場合は、次のデバッグ設定を追加することでデバッガーをアタッチすることができます。

  • Connection type: Standard (Socket Listen)
  • Host: localhost
  • Port: 9009

Screenshot-Debug Configurations

注意事項

OutOfMemoryError関連のリンク(特にネイティブメモリを操作するもの)をクリックすると、PCの動作が不安定になる可能性があります。CPUやメモリを制限したVM上で起動するなどしてから、自己責任でリンクをクリックして下さい。

既知の問題と対策の方法

Javaやサーブレットコンテナのバージョンにも依存しますが、Windows上での動作で問題が出る場合があります。

● メインページにアクセスすると、内部サーバーエラーが発生する(v 1.3.0より前のバージョンでの問題):

easybuggy.jarで起動した場合、Javaのバージョンによっては、メインページにアクセスすると次のエラーが発生する場合があります。

HTTP Status 500 – Internal Server Error

org.apache.jasper.JasperException: PWC6345: There is an error in invoking javac.  A full JDK (not just JRE) is required

この場合は、JDK/binを環境変数「path」に追加し、JRE/bin/javaを実行して下さい。

> set path=%path%;C:\Program Files\Java\jdk1.8.0_121\bin
> "C:\Program Files\Java\jdk1.8.0_121\jre\bin\java" -jar easybuggy.jar

● 「Failed to delete ○○.jar」のエラーが出力されて起動できない:

mvnコマンドで起動した場合、JavaのバージョンによってはCtrl+CでもEasyBuggyのプロセスが停止しない場合があります。この場合は、起動時に次のようなエラーが出力されます。

> mvn clean install exec:exec
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building easybuggy 1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ easybuggy ---
[INFO] Deleting C:\Users\ktamura\git\easybuggy\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.681 s
[INFO] Finished at: 2017-03-14T09:45:18+09:00
[INFO] Final Memory: 7M/155M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clean) on project easybuggy: Failed to clean project: Failed to delete C:\easybuggy\target\easybuggy-1-SNAPSHOT\WEB-INF\lib\xom-1.2.5.jar -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

この場合は、「JVMクラッシュ」や「コードインジェクション」のページにアクセスして、EasyBuggyのプロセスを強制的に停止させてしまうのが、手っ取り早いです 🙂 。「JVMクラッシュ」で停止させる場合は、logsディレクトリにコアダンプが出力されるので、増えてきたら削除して下さい。