GAEのアプリケーションの名前はJava、Pythonどちらでもプログラム内から参照できるようになっています。 続きを読む Google App Engine でアプリケーション名を取得するには?
タグ: Java
GAE/Jでgsonを使うとVerifyErrorになる件(解決?)
あるときからGoogle App Engine(Java)でgsonライブラリを使うと、java.lang.VerifyErrorが発生するようになってしまった。
別の方(GAE/JでGson利用時にjava.lang.VerifyErrorが発生する)」もとりあげているのと同じ現象のようですが、一応対応がわかったのでメモしておく。 続きを読む GAE/Jでgsonを使うとVerifyErrorになる件(解決?)
【Java】 Mapを値でソートする方法
Javaでソート対応のマップと言えばTreeMapだけど、TreeMapはキーのソートにしか対応してません。
マップの値でのソートはオブジェクト外の要素でソートしたい時などは値でのソートが出来ると便利ですので、今回はその方法をご紹介します。
続きを読む 【Java】 Mapを値でソートする方法
AndroidのTextView、ListViewの使い方まとめ
「Google Android – 雑記帳」さんのTextView, ListViewの使い方についての記事がAndroid開発入門によさそうなドキュメントだったので紹介します。
Android Javaの正規表現の落とし穴
Androidで正規表現を使っていて、全角のパターンマッチで少しはまったのでメモ。
Javaでは他の正規表現エンジンと同様、POSIX文字クラスが利用できます。
if("Hello".match("^\\p{Alpha}+$")){
System.out.println("アルファベットだけ!");
}
Launch error: リモート VM に接続できませんでした
Android開発をしていて、ある時からアプリのデバッグ起動で次のようなエラーが出て固まるようになりました。
[2011-08-03 19:14:42 - com.example.testapp] ------------------------------
[2011-08-03 19:14:42 - com.example.testapp] Android Launch!
[2011-08-03 19:14:42 - com.example.testapp] adb is running normally.
[2011-08-03 19:14:42 - com.example.testapp] Performing com.example.testapp.First activity launch
[2011-08-03 19:14:42 - com.example.testapp] Automatic Target Mode: using device 'CB511J0W90'
[2011-08-03 19:14:42 - com.example.testapp] Uploading com.example.testapp.apk onto device 'CB511J0W90'
[2011-08-03 19:14:42 - com.example.testapp] Installing com.example.testapp.apk...
[2011-08-03 19:14:45 - com.example.testapp] 成功!
[2011-08-03 19:14:45 - com.example.testapp] Starting activity com.example.testapp.First on device CB511J0W90
[2011-08-03 19:14:45 - com.example.testapp] ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.testapp/.First }
[2011-08-03 19:14:45 - com.example.testapp] Attempting to connect debugger to 'com.example.testapp' on port 8610
[2011-08-03 19:14:45 - com.example.testapp] Launch error: リモート VM に接続できませんでした
ポート8610番につなげない、と言われているので調べてみる。
C:\>netstat -an -p tcp ~略~ TCP 127.0.0.1:8600 0.0.0.0:0 LISTENING TCP 127.0.0.1:8601 0.0.0.0:0 LISTENING TCP 127.0.0.1:8602 0.0.0.0:0 LISTENING TCP 127.0.0.1:8603 0.0.0.0:0 LISTENING TCP 127.0.0.1:8604 0.0.0.0:0 LISTENING TCP 127.0.0.1:8605 0.0.0.0:0 LISTENING TCP 127.0.0.1:8606 0.0.0.0:0 LISTENING TCP 127.0.0.1:8607 0.0.0.0:0 LISTENING TCP 127.0.0.1:8608 0.0.0.0:0 LISTENING TCP 127.0.0.1:8609 0.0.0.0:0 LISTENING TCP 127.0.0.1:8610 0.0.0.0:0 LISTENING TCP 127.0.0.1:8612 0.0.0.0:0 LISTENING TCP 127.0.0.1:8613 0.0.0.0:0 LISTENING TCP 127.0.0.1:8614 0.0.0.0:0 LISTENING TCP 127.0.0.1:8615 0.0.0.0:0 LISTENING TCP 127.0.0.1:8616 0.0.0.0:0 LISTENING TCP 127.0.0.1:8620 0.0.0.0:0 LISTENING TCP 127.0.0.1:8621 0.0.0.0:0 LISTENING TCP 127.0.0.1:8622 0.0.0.0:0 LISTENING TCP 127.0.0.1:8623 0.0.0.0:0 LISTENING TCP 127.0.0.1:8624 0.0.0.0:0 LISTENING TCP 127.0.0.1:8626 0.0.0.0:0 LISTENING TCP 127.0.0.1:8627 0.0.0.0:0 LISTENING TCP 127.0.0.1:8629 0.0.0.0:0 LISTENING ~略~
と(やたらLISTENしているポートが多いのが気になるものの)ちゃんと開いているように見える。
ポートが空いてるのは確認できたが、firewallの影響を受けているかもしれないのでさらにしつこくjdbデバッガで調べてみる。
C:\>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8610 uncaught java.lang.Throwable を設定しました 保留した uncaught java.lang.Throwable を設定しました jdb の初期化中です... >
問題なくつなげたので一旦quitを入力して終了。
これで繋げなければJava VM側やネットワークの問題の可能性がありましたが、
これで原因はEclipseの可能性が高いということに。
改めてEclipseの設定を確認すると…
一般 → ネットワーク設定 → プロキシーのバイパスでプロキシが設定されていて、しかもlocalhost, 127.0.0.1 のプロキシが有効になってしまっていました。
これじゃ繋がるわけないわな。
アクティブ・プロバイダーが「ネイティブ」になっていて変更できなかったため「直接」に変更した上で上記2つのチェックを外した所無事解決。
Android で System.exit() を使ってはいけない理由と、終了方法のまとめ
この記事は 2011年に書いた「Android で System.exit() を使ってはいけない理由」を、2026年時点の Android で実測し直したものです。
結論から言うと、今でもアプリコードから System.exit() でプロセスを落とすのは避けた方がよいです。Activity を閉じたいなら finish()、タスクを最近使ったアプリ一覧からも消したいなら finishAndRemoveTask()、アプリを終了ではなく背面へ送るだけなら moveTaskToBack(true) を使います。
まず結論
用途ごとに分けるとこうです。
| やりたいこと | 使うもの | 備考 |
|---|---|---|
| 今の Activity を閉じる | finish() | 基本はこれ |
| ルート Activity からタスクごと閉じ、最近使ったアプリからも消したい | finishAndRemoveTask() | API 21以降 |
| アプリを終了せず、ホームへ戻したように背面へ送る | moveTaskToBack(true) | 終了ではない |
| プロセスを強制終了する | 使わない | System.exit() / killProcess() は通常の終了処理を飛ばす |
「アプリを終了するボタン」を作りたくなることがありますが、Android ではユーザーが戻る操作・ホーム操作・最近使ったアプリ画面でアプリから離れるのが基本です。開発者側がプロセスを落として終了感を作る必要は、ほとんどありません。
実際に試した環境
最小 Activity を作り、各終了方法を呼んだときのライフサイクルログを取りました。
端末: Android Emulator Medium_Phone_API_36.0 OS: Android 16 / API 36 targetSdkVersion: 36 build-tools: 36.1.0 確認日: 2026-07-14
Activity 側では、onCreate / onStart / onResume / onPause / onStop / onDestroy をログに出し、モードごとに次の処理を呼びました。
switch (mode) {
case "finish":
finish();
break;
case "finish_remove":
finishAndRemoveTask();
break;
case "move_task_back":
moveTaskToBack(true);
break;
case "system_exit":
System.exit(0);
break;
case "kill_process":
Process.killProcess(Process.myPid());
break;
}
finish() は Activity の終了
finish() を呼ぶと、Activity の終了ライフサイクルを通りました。
I/ExitProbe: onCreate pid=11507 I/ExitProbe: onStart pid=11507 I/ExitProbe: onResume pid=11507 I/ExitProbe: runMode finish pid=11507 I/ExitProbe: onPause pid=11507 I/ExitProbe: onStop pid=11507 I/ExitProbe: onDestroy pid=11507 pid_after_18s=11507
onDestroy まで呼ばれていますが、18秒後もプロセスIDは残っていました。ここが大事です。finish() は「Activity を閉じる」操作であって、「アプリのプロセスを殺す」操作ではありません。
これは Android では自然な挙動です。プロセスをいつ残すか、いつ回収するかはシステム側が判断します。
finishAndRemoveTask() はタスクを最近使ったアプリから外す
finishAndRemoveTask() も、手元の実測では Activity のライフサイクルは通常通り進みました。
I/ExitProbe: onCreate pid=11548 I/ExitProbe: onStart pid=11548 I/ExitProbe: onResume pid=11548 I/ExitProbe: runMode finish_remove pid=11548 I/ExitProbe: onPause pid=11548 I/ExitProbe: onStop pid=11548 I/ExitProbe: onDestroy pid=11548 pid_after_18s=11548
finishAndRemoveTask() は、Activity を閉じるだけでなく、その Activity が属するタスクを最近使ったアプリ一覧から外したいときに使います。ログを見る限り、これもプロセスを殺すAPIではありません。
「ログアウト完了後にログイン画面へ戻さず、タスク自体を終わらせたい」など、タスクとして残したくない画面で検討するAPIです。普通の画面遷移や戻る操作の代わりに乱用するものではありません。
moveTaskToBack(true) は終了ではなく背面送り
moveTaskToBack(true) は「アプリを閉じたように見せる」ために使われがちですが、実際にはタスクを背面へ送るだけです。
I/ExitProbe: onCreate pid=11587 I/ExitProbe: onStart pid=11587 I/ExitProbe: onResume pid=11587 I/ExitProbe: runMode move_task_back pid=11587 I/ExitProbe: onPause pid=11587 I/ExitProbe: onStop pid=11587 pid_after_18s=11587
onDestroy は呼ばれませんでした。Activity は停止状態になり、タスクは背面に回ります。これはホームボタンを押したときに近い挙動です。
そのため、moveTaskToBack(true) を「終了処理」と呼ぶのは少し危険です。終了ではなく、ユーザーをホームへ戻す・タスクを背面へ送るためのAPIとして説明した方が実態に合います。
System.exit(0) はライフサイクルを飛ばしてプロセスを落とす
System.exit(0) を呼ぶと、ログはこうなりました。
I/ExitProbe: onCreate pid=11636
I/ExitProbe: onStart pid=11636
I/ExitProbe: onResume pid=11636
I/ExitProbe: runMode system_exit pid=11636
I/ActivityManager: Process net.ecoop.exitprobe (pid 11636) has died: fg TOP
W/ActivityTaskManager: Force removing ActivityRecord{... net.ecoop.exitprobe/.MainActivity ...}: app died, no saved state
pid_after_18s=
onPause、onStop、onDestroy は出ていません。システム側のログにも app died, no saved state と出ました。
つまり、Activity に「終わります」と伝えて閉じているのではなく、プロセスごと突然いなくなっています。画面の保存、遷移、後片付けを Activity のライフサイクルに乗せている場合、その処理は通りません。
これが、Android で System.exit() を避けるいちばん大きな理由です。
Process.killProcess() も同じ
android.os.Process.killProcess(Process.myPid()) なら Android のAPIだからよさそうに見えるかもしれません。実際には、これも通常の終了処理ではありません。
I/ExitProbe: onCreate pid=12065
I/ExitProbe: onStart pid=12065
I/ExitProbe: onResume pid=12065
I/ExitProbe: runMode kill_process pid=12065
I/ActivityManager: Process net.ecoop.exitprobe (pid 12065) has died: fg TOP
W/ActivityTaskManager: Force removing ActivityRecord{... net.ecoop.exitprobe/.MainActivity ...}: app died, no saved state
pid_after_18s=
System.exit(0) と同じく、onPause / onStop / onDestroy は出ませんでした。プロセスを殺しているだけなので、アプリの終了処理としては使わない方がよいです。
どう書けばよいか
単に今の画面を閉じたいなら、こうです。
finish()
Java ならこうです。
finish();
タスクごと閉じて、最近使ったアプリにも残したくないなら、ルート Activity で次を使います。
finishAndRemoveTask()
ただし、これは「普通の終了ボタン」のために必ず必要なAPIではありません。最近使ったアプリに残すかどうかまで変えるので、ログアウト完了画面など、タスクとして残したくない理由があるときに使います。
ホームへ戻したいだけなら、終了ではなく背面送りです。
moveTaskToBack(true)
これを使うと Activity は onPause / onStop に進みますが、onDestroy までは行かないことがあります。終了処理を期待して書くのではなく、「タスクを背面に回す」と考えてください。
終了ボタンは本当に必要か
多くのAndroidアプリでは、終了ボタンそのものが不要です。
ユーザーは戻る操作で前の画面へ戻り、ホーム操作でアプリから離れ、最近使ったアプリ画面からタスクを選び直します。開発者がプロセスを落として「終了」を作るより、保存すべき状態を適切なタイミングで保存し、Activity / Fragment / Compose のライフサイクルに合わせる方がAndroidらしい作りになります。
どうしても終了に見える操作を置くなら、「プロセスを落とす」ではなく、「画面を閉じる」「タスクを背面に送る」「ログアウトして初期画面へ戻す」のどれをしたいのかに分けて実装すると事故が減ります。
さいごに
System.exit() は、Javaプログラムとしてはプロセス終了のAPIですが、Androidアプリの画面終了には向いていません。今回の実測でも、Activity の終了ライフサイクルを通らず、システムには「アプリが死んだ」と扱われました。
Androidで終了っぽい処理を書きたくなったら、まず finish()、finishAndRemoveTask()、moveTaskToBack(true) のどれなのかを切り分けてください。プロセスを殺すのは、通常のアプリ終了手段ではありません。
あわせて読みたい:
アクティビティを閉じる際の最良の終了方法です。
現在のアクティビティを閉じて前のアクティビティに戻ります。
アプリケーションの起動アクティビティで呼び出した場合はアプリケーションを終了します。
バックボタンを押した時と同じ動きで、実行すると onPause(), onDestroy()が順番に呼ばれます。
復帰時は新規生成となり onCreate(), onStart(), onResume() の順でイベントが発生します。
■Activity#moveTaskToBack (boolean nonRoot)
アプリケーション全体を終了する際の推奨される終了方法です。
アプリケーションを中断状態にします。
引数に false を指定した場合、アプリケーションの開始アクティビティ以外の呼び出しでは何もしなくなるため、通常は引数にtrueを指定して呼び出します。
ホームボタンを押した時の動作と同じ動きで、実行するとonPause()イベントが発生します。
次の再開までバックグラウンドで待機状態になり、メモリ不足になった時はOSにより自動でonDestroy()イベントが発生してアプリケーションの全てのタスクが終了します。
onDestroy()が呼ばれる前に復帰した時は最後のアクティビティから再開し、onRestart(), onStart(), onResume() の順でイベントが発生します。
例:
this.moveTaskToBack(true);
ドキュメントより引用:
public boolean moveTaskToBack (boolean nonRoot)
Since: API Level 1
Move the task containing this activity to the back of the activity stack.
The activity’s order within the task is unchanged.
If the task was moved (or it was already at the back) true is returned, else false.
訳:このアクティビティを含むタスク全体のアクティビティスタックの順番を後ろに移動させます。
タスク内のアクティビティの順番は変更されません。
パラメータ
nonRoot If false then this only works if the activity is the root of a task; if true it will work for any activity in a task.
訳:falseの場合は現在のアクティビティがタスクのルートアクティビティ(アプリケーションの開始アクティビティ)の時だけ動作します。
trueの場合はタスク内のどのアクティビティであっても動作します。
■android.os.Process.killProcess(int pid)
Process.myPid ()を引数に与えると現在のプロセスを強制終了します。
アクティビティが実行中のプロセスを対象に呼び出すと、finish()と同じくそのアクティビティを終了します。
ただし、onDestroy()などActivityのライフサイクルを全て無視して強制終了するため、通常は Activity.finish() が推奨されます。
例:
android.os.Process.killProcess(Process.myPid());
ドキュメントより引用:
public static final void killProcess (int pid)
Since: API Level 1
Kill the process with the given PID.
Note that, though this API allows us to request to kill any process based on its PID,
the kernel will still impose standard restrictions on which PIDs you are actually able to kill.
Typically this means only the process running the caller’s packages/application and any additional
processes created by that app; packages sharing a common UID will also be able to kill each other’s processes.
訳:指定したIDのプロセスを終了します。
このAPIでは指定のPIDに基づいてどんなプロセスでも終了することが許されていますが、
実際終了できるかどうかはカーネルの標準的な制限で決まる点に注意してください。
つまり、典型的には呼び出し元のパッケージやアプリケーションが実行しているプロセスと、そのアプリが作成した追加のプロセスに限られるという意味です。
UIDを共有しているパッケージもまたお互いのプロセスを終了させる事ができます。
■System.exit(int)
System.exit(RESULT_OK)のように実行することで実行中のプロセスを強制終了します。
android.os.Process.killProcess(Process.myPid()) と同じような動きになりますが、
安全ではないので使うべきではありません。
ドキュメントには、
public static void exit (int code)
Since: API Level 1
Causes the virtual machine to stop running and the program to exit.
If runFinalizersOnExit(boolean) has been previously invoked with a true argument, then all objects will be properly garbage-collected and finalized first.
訳:バーチャルマシンの実行を停止し、プログラムを終了させます。
runFinalizersOnExit(boolean) を事前に引数にtrueを指定して呼び出してれば、全てのオブジェクトは最初に適切にガベージコレクトされてファイナライズされます。
のように一見、runFinalizersOnExit(true)を設定しておけば問題ないかのように書かれていますが、
実際にはrunFinalizersOnExit(boolean)の説明に
This method is deprecated. this method is unsafe.
と、どちらにしても安全ではない事が明確に書かれているためです。
通常は finish() または moveTaskToBack(true)を使い、どうしてもプロセスを強制終了したい場合は、Process.killProcess(Process.myPid ()) を使いましょう。
■おまけ…
アプリ内の全てのタスク(アクティビティ,プロセス)を一度に即終了したい場合, moveTaskToBack(true) を使う以外の方法として次のようなものがあります。
・AndroidManifest.xml で <activity android:noHistory=”true”> オプションを指定して finish() する。
noHistory=”true”を指定しておくとアクティビティのスタックがなくなる事を利用する方法です。
参考:
– Activity(developer.android.com)
アクティビティのライフサイクルについてなど。
– アクティビティとタスクデザイン (ソフトウェア技術ドキュメントを勝手に翻訳)
– Application Fundamentals(developer.android.com)
– android close application
Androidの強制終了の仕方についての議論。
Android – HttpClient のクッキー管理機能をカスタマイズする
HttpClient のクッキー処理の仕様をブラウザに合わせたい、RFC準拠にしたい、自分で管理したい、という時はクッキーポリシーの設定で動作を変更することができます。
方法1: 標準で提供されているクッキーポリシーを選んで設定する
例:
DefaultHttpClient client = new DefaultHttpClient(params);
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.NETSCAPE); // SetCookieの扱いをNetscapeの仕様に変更
設定可能な値:
– CookiePolicy.BEST_MATCH … デフォルトのベストマッチポリシー
– CookiePolicy.RFC_2109 … RFC2109に準拠(時代遅れの厳密なポリシー)
– CookiePolicy.RFC_2965 … RFC2965に準拠(標準的で厳密なポリシー)
– CookiePolicy.NETSCAPE … ネットスケープのドラフトに準拠
– CookiePolicy.BROWSER_COMPATIBILITY … (おかしな)一般的なブラウザと互換性がある動作にする。
方法2:カスタムポリシーを使う
例:
DefaultHttpClient client = new DefaultHttpClient(params);
// カスタムクッキーポリシーを定義する
CookieSpecFactory csf = new CookieSpecFactory() {
@Override
public CookieSpec newInstance(HttpParams params) {
return new BrowserCompatSpec(){
@Override
public void validate(Cookie cookie, CookieOrigin origin)
throws MalformedCookieException {
// ここで判定してクッキー導入処理を行う。
// super.validate(cookie, origin);
}
};
}
};
client.getCookieSpecs().register(“myspec”, csf); // カスタムポリシーに結びつけるキーワードを登録して・・
client.getParams().setParameter(
ClientPNames.COOKIE_POLICY, “myspec”); // そのキーワードでポリシーを設定!
カスタムポリシーを定義する場合は標準で提供されているポリシーのソースが参考になります。
– RFC_2109 … RFC2109Spec.java
– RFC_2965 … RFC2965Spec.java
– NETSCAPE .. NetscapeDraftSpec.java
– BROWSER_COMPATIBLE .. CookieSpecBase.java
その他クッキー関係の設定方法は公式ドキュメントに詳しく書かれています。
参考:
– HttpClientでのCookieの扱い(HttpClient3.0-rc3)
– HttpComponentsライブラリ公式ドキュメント(hc.apache.org)
– RFC2109(日本語訳)
– RFC2965(日本語訳)
– HttpComponentsのcookieパッケージソース(svn.apache.org)
デコンパイラ JD-Eclipse を入れてみた
デコンパイラといえば jad と、 Eclipse 組み込み版の Jadclipse が主流でした。
しかし最近は Jadclipse がメンテナンスされていなかったり、そもそもjad が公式配布停止していたりで残念なことに事実上完全に開発停止になってしまったようです。
そこで代わりを探していたところ、JD-Eclipse というものを見つけました。
Eclipse 3.5 (galileo)ですんなりダウンロード完了。
Java 5 の逆コンパイルにも対応していて、Jad よりも高機能なようです。
Eclipse アップデートサイトからの更新はこちら。
http://java.decompiler.free.fr/jd-eclipse/update
日本語での使い方説明記事はこちら。
究極の問題解析ツール、逆コンパイラJD-Eclipseとは(@IT)
参考:
– JD-Eclipse Java Decompiler
– 究極の問題解析ツール、逆コンパイラJD-Eclipseとは(@IT)
Launch4j – Java から実行可能プログラムを作成する
Launch4j
Windows XP/Vista の .exe をはじめ、Linux, Mac OS X, Soralis などさまざまな環境用のインストーラや実行可能ファイルを生成してくれる Jar のラッパープログラム。
マイコミジャーナルでの紹介記事はこちら。